I was planning to write a short tutorial on the use of iptables, however, "short" is no longer in my vocabulary. iptables in itself is very simple, yet can be quite complex depending on the nature of how you plan to use it. Rather than writing one massive tutorial, I plan to take the reader on a magical tour of multiple explanations. With this method, we can work together from the ground up as to not cause any confusion or mass chaos. So put on your reading glasses, and iron that thinking cap! All levels of experience will find this to be an informative piece, or so I hope. Enjoy.. ;) Table of contents/what's under your seat, sir...
1. What came first, the chicken or the egg? 2. Netfilter/iptables defined 3. Installation 4. So, it's your first time? 5. Securing your workstation 6. Conclusion
1. What came first, the chicken or the egg?
Some of you may be asking yourself, "what is this netfilter and iptables lingo?". Before I can answer that question, I need to ask you -- are you running Linux 2.4.x? If so, then keep reading. If not, well, keep reading! Try typing the following command: netstat -a
After you press the return key, you might see something like this:
Active Internet connections (servers and established) Proto Recv-Q Send-Q Local Address Foreign Address State tcp 0 0 *:icq *:* LISTEN tcp 0 0 *:x11 *:* LISTEN tcp 0 0 localhost.localdom:smtp *:* LISTEN tcp 0 0 192.168.1.122:32988 cheezy.box.sk:imap ESTABLISHED tcp 0 0 192.168.1.122:32951 64.12.24.13:5190 ESTABLISHED tcp 0 0 192.168.1.122:32950 msgr-cs132.msgr.ho:1863 ESTABLISHED tcp 0 0 192.168.1.122:32954 64.12.24.26:5190 ESTABLISHED tcp 0 0 192.168.1.122:32955 irc.box.sk:ircd ESTABLISHED tcp 0 0 192.168.1.122:32949 herc.jabber.org:5222 ESTABLISHED ...and so forth...
Netstat is a tool which helps you view network connections. It is available on Unix, Linux, and even Windows platforms. By typing netstat with the -a switch, we are requesting to view active (-a) connections. So, what you are seeing are active connections. Active connections in a sense mean "open", and does not necessarily reflect that they are being used by someone at this very moment -- so don't worry...just yet. An active connection may be a program running and waiting to establish communication with another computer or service, or it is a connection that is currently established. In the above example, underneath State you will notice LISTEN and ESTABLISHED. This is how you know if the connection is in use. There are many more state's than this, however in this example I just want for you to understand the very basics.
Connections, like the ones in the above example, are established through a port. A port is a specific number on your machine, which is pre-defined for a particular service (smtp, www, ftp, etc). In the above example, notice the localhost.localdom:smtp? SMTP (Simple Mail Transport Protocol) is the mail service, and it is running on port 25. How do we know? Just as we did before, we will use the netstat command. But only this time, we will add a new character: netstat -an
After you press the return key, you might see something like this:
Active Internet connections (servers and established)
By typing netstat with the -an switch, we are requesting to view active (-a) connections, but only in numerical format (so we can see the port rather than the service name). Notice how everything looks almost the same? The difference now is, all that you see are the port numbers rather than service names (icq=4000, x11=6000, SMTP=25, etc).
Now, going back to what I said about someone possibly using one of our connections. We'll use the SMTP service for our example. SMTP usually runs on port 25, because that is the standard port for the transfer of electronic mail. SMTP can often times be a security risk, especially when running as root. Exploits are commonly found in the SMTP service, and because of these exploits, outside users could possibly gain remote access to your machine. "It's just a mail service", you may say. Oh, but it's more than that, and it is possible to gain remote access with many services, not just SMTP. But, like I said, we're using SMTP for our example. So, let's take a look at something. Let's telnet to our SMTP service (yes, telnet doesn't have to just connect to a telnet service). Type the following command: telnet localhost 25
After you press the return key, you might see something like this:
Trying 127.0.0.1...Connected to localhost.localdomain (127.0.0.1).Escape character is '^]'.220 localhost.localdomain ESMTP Postfix (1.1.11)
You have now established a connection with your SMTP service. Similar to your command prompt, you can enter commands and receive a response. Try the following command: HELP
After you press the return key, you might see something like this:
214-2.0.0 Topics:214-2.0.0 HELO EHLO MAIL RCPT DATA214-2.0.0 RSET NOOP QUIT HELP VRFY214-2.0.0 EXPN VERB ETRN DSN AUTH214-2.0.0 STARTTLS214-2.0.0 For more info use "HELP ".214 2.0.0 End of HELP info
Not all of you may see the above example, but it's taken from a sendmail service for my example. Yes, for those of you who notice two different mail services (Postfix/Sendmail), I meant to do this. Anywho, if you typed HELP and recieved the above example, you'll notice that there are many commands to which you can function SMTP without the use of a mail client.
Exploiting SMTP, such as a buffer-overflow attack, can often times lead to remote access. The exploiter can enjoy the use of telnet via port 25, just as you used telnet. And if the mail service is running as root, then the person exploiting your machine has root privileges. Ouch, huh?
Soooooo....... let's see... You should now have a firm grasp of connections, services and ports. If not, I highly suggest starting from the top and reading through once more. You must understand these three items before you continue -- it's for your own good! ;)
Before I finish up this section, you should also get a quick run-down of what a packet is. Packets are a short block of data transmitted in a packet switching network. In simplest form, packets deliver information from one place, to another, until it reaches the final destination. Okay, on to the next section!
2. Netfilter/iptables defined
Netfilter and iptables give you flexibility in protecting your services (firewall feature), powerful routing features (network address translation, or NAT), manipulating packets (packet mangling), and most useful is the connection tracking feature. At the packet filtering (firewall) level, you can control which services may be accessed, and how they may be accessed. At the NAT level, you can use the packet filtering feature, process the packets, and send them to a specific host on your network, service on the same box, or simply drop the request at the doorstep. Packet ala deceased.
Netfilter and iptables is the re-designed and heavily improved successor of the previous 2.2.x ipchains and 2.0.x ipfwadm systems. Here is a brief look into the past to help you understand the path to what we now have today, iptables:
ipfw - IP firewall
Facilities in the Linux kernel that provide mechanisms for accounting IP packets, building firewalls based on packet-level filtering, building firewalls using transparent proxy servers, and for masquerading forwarded packets.
ipfwadm - IP firewall administration
Used for Linux kernels 2.0.x and below. It is no longer supported.
ipchains - IP firewall administration
Used to set up, maintain, and inspect the IP firewall rules in the Linux kernel. These rules can be divided into 4 different categories: the IP input chain, the IP output chain, the IP forwarding chain, and user defined chains.
iptables - IP packet filter administration
The framework inside the Linux 2.4.x kernel which enables packet filtering, network address translation (NAT) and other packet mangling. It is the re-designed and heavily improved successor of the previous 2.2.x ipchains and 2.0.x ipfwadm systems.
netfilter is a set of hooks inside the linux 2.4.x kernel's network stack which allows kernel modules to register callback functions called every time a network packet traverses one of those hooks.
iptables is a generic table structure for the definition of rulesets. Each rule within an IP table consists out of a number of classifiers (matches) and one connected action (target).
netfilter, iptables and the connection tracking as well as the NAT subsystems together build the whole framework.
3. Installation
Before you can use iptables, we need to check and see if it is installed and supported by the kernel. A very simple way to do this is by typing the following command (as root!): iptables -L
If after pressing return, and you get a bunch of errors, you most likely don't have netfilter/iptables installed or configured correctly. You will need to have a recent version of netfilter/iptables, along with an up-to-date Linux 2.4.x kernel. Each can be obtained from the following links:
http://www.iptables.org http://www.kernel.org
PLEASE NOTE: just because you get errors, DOES NOT MEAN that netfilter/iptables is NOT installed. If you are running a fairly recent distribution (Debian, RedHat, etc) then you are probably okay. You'll just need to compile a newer kernel with Netfilter support. If you want to run the latest version of netfilter/iptables, then you should download it. If not, then just make sure you download an up-to-date Linux 2.4.x kernel.
Anywho, I will assume you have experience with installing software, and compiling a Linux kernel. If not, after downloading netfilter/iptables, follow the installation instructions. For compiling the kernel, please visit The Linux Documentation Project and read The Linux Kernel HOWTO.
When configuring your new Linux 2.4.x kernel, here is what you'll need to do to ensure you can use iptables. Follow this chart which should correspond with your kernel:
*** for those who might not know... be sure you are ROOT ;) ***
1. MAIN MENU, choose the NETWORKING OPTIONS link. 2. Select the following EXACTLY as shown:
([*] = Include, [M] = Modularize)
[*] Packet socket [*] Network packet filtering (replaces ipchains) [*] Socket Filtering [*] Unix domain sockets [*] TCP/IP networking [*] IP: advanced router [*] IP: policy routing [*] IP: use TOS value as routing key [*] IP: verbose route monitoring [*] IP: tunneling [M] IP: GRE tunnels over IP [*] IP: TCP syncookie support (disabled per default) -
NOTE: you will need to make a script or whatever after your machine boots up, to properly use the TCP syncookie support. Make a script to run this command:
echo 1 >/proc/sys/net/ipv4/tcp_syncookies
Debian users, you don't need to worry about this.. it's already implemented! For other distributions, if you are not familiar with writing scripts, then read up on shell scripting. For most, you can just add this to your network script, near the end of the "start" section. An example would be:
3. Next select the IP: Netfilter Configuration link. 4. Select the following EXACTLY as shown:
([*] = Include, [M] = Modularize)
[M] Connection tracking (required for masq/NAT) [M] FTP protocol support [M] IRC protocol support [*] IP tables support (required for filtering/masq/NAT) [M] limit match support [M] MAC address match support [M] netfilter MARK match support [M] Multiple port match support [M] TOS match support [M] AH/ESP match support [M] LENGTH match support [M] TTL match support [M] tcpmss match support [M] Connection state match support [M] Packet filtering [M] REJECT target support [M] Full NAT [M] MASQUERADE target support [M] REDIRECT target support [*] NAT of local connections (READ HELP) [M] Packet mangling [M] TOS target support [M] MARK target support [M] LOG target support [M] ULOG target support [M] TCPMSS target support
5. Configure the rest of the kernel to your liking. 6. Save, exit, then compile the kernel. 7. After compiling (and no errors), run make modules then make modules_install 8. Install the new kernel, then reboot.
NOTE: make sure you understand how to compile a kernel, and install one properly. You can cause a great deal of headache if not done correctly. You have been warned. ;)
9. After rebooting your machine, run modconf. 10. Select kernel/net/ipv4/netfilter 11. Enable the following modules:
If not, well then, you did something wrong and you are screwed. Good luck, see you on the other side. Heheh, just kidding. Make sure you didn't forget anything above (like in your kernel config). While writing this, I just about went crazy because I forgot to include a small piece of the pie... so don't worry. Just look over everything. Good luck!
4. So, it's your first time?
That's okay, we all start somewhere. And if you've made it this far, then rock on, 'cuz you rule! Let's get familiarized with using iptables, the tool that will help us from here on. In the last section, you learned how to run the list function in iptables. Let's do it again, okay? Type the following command: iptables -L
You'll notice three distinct categories when using this command. Chain INPUT, chain FORWARD, and chain OUTPUT. These categories are called "ip chains". Here's what the function is for each ip chain:
INPUT = any packet entering your computer goes through the INPUT chain FORWARD = any packet that your computer picks up on one network and sends to another goes through the FORWARD chain OUTPUT = any packet that your computer sends out to the network goes through the OUTPUT chain
Now that you have a bit of understanding of iptable chains, let's get familiar with the commands we can use with iptables:
COMMON COMMANDS ------------------------- -A chain = Append rule to the end of the selected chain -D chain = Delete machine rule from chain -D chain rulenum = Delete rule number from chain (1 = first) -I chain [rulenum] = Insert in chain as rule number [default 1=first] -R chain rulenum = Replace rule number in chain (1 = first) -L [chain] = List the rules in a chain or all chains -F [chain] = Delete all rules in chain or all chains
COMMON OPTIONS ------------------------- -p protocol = protocol: by number or name, eg. TCP, UDP, ICMP -s address[/mask] = Source specification -d address[/mask] = Destination specification -i interface[+] = Input network interface name ([+] for wildcard), eg. ppp0, eth0, eth+ (multi-ether) -o interface[+] = Output network interface name -j target = Target for rule (target values are ACCEPT, DROP, QUEUE, RETURN)
Okay, I'm sure you are exhausted from all this reading, so let's do something exciting! Let's look at a very basic iptables command:
# iptables -s 146.57.248.15
This example shows the command iptables, using the -s switch, following with and IP address. This example is actually, invalid. We are simply giving iptables a source address, but what good will that do? We must feed the command more information. After all, it is hungry!
# iptables -s 146.57.248.15 -j DROP
In this example, we are giving the source switch (-s), the IP address, and a new switch (-j DROP). However, this too is invalid. It's only showing the source plus the target, but what will iptables do with it? It will of course ignore the packet (DROP), but where will it drop it? This goes back to the ip chains we discussed earlier. We must supply a chain for our command, as to where it will handle the packet.
# iptables -A INPUT -s 146.57.248.15 -j DROP
There we go! Now our puzzle is complete. Let's break it down, shall we? iptables is the command, -A INPUT means we want this to APPEND to the INPUT chain (incoming traffic), look for the source (-s) IP address (146.57.248.15), and then add a target (-j DROP). Targets can be thought of as an action to take. The targets that are allowed are: ACCEPT, DROP, QUEUE, and RETURN.
TARGETS ------------------------- ACCEPT = Allow the packet through DROP = Ignore the packet completely QUEUE = Pass the packet to the userspace (if supported by the kernel) RETURN = Stop traversing this chain and resume at the next rule in the previous (calling) chain
Let's view our current iptables configuration. Type: iptables -L
We see that our INPUT rule shows the following: target, prot, opt, source, and destination. Target is the action to take, prot is for protocol (explained shortly), opt are options, source is the source IP address, and destination is destination IP address. What if you just want to drop incoming telnet requests? Here is what we would type:
# iptables -A INPUT -s 146.57.248.15 -p tcp --destination-port telnet -j DROP
Breaking this down, we are APPENDING to the INPUT chain, from the source (-s) address of 146.57.248.15, checking packets on the Transmission Control Protocol (-p tcp), packets destined for the telnet service, and last but definately not least -- DROP those packets to the floor! BAM!!!
For those of you not familiar with protocols, here is a quick run-down:
IP - Internet Protocol
The Internet Protocol is designed for use in interconnected systems of packet-switched computer communication networks. Such a system has been called a "catenet". The internet protocol provides for transmitting blocks of data called datagrams from sources to destinations, where sources and destinations are hosts identified by fixed length addresses. The internet protocol also provides for fragmentation and reassembly of long datagrams, if necessary, for transmission through "small packet" networks.
This protocol is called on by host-to-host protocols in an internet environment. This protocol calls on local network protocols to carry the internet datagram to the next gateway or destination host. --source: RFC 791
ICMP - Internet Control Message Protocol
The Internet Protocol is not designed to be absolutely reliable. The purpose of the Internet Control Message Protocol is to provide feedback about problems in the communication environment, not to make IP reliable. There are still no guarantees that a datagram will be delivered or a control message will be returned. Some datagrams may still be undelivered without any report of their loss. The higher level protocols that use IP must implement their own reliability procedures if reliable communication is required.
The ICMP messages typically report errors in the processing of datagrams. To avoid the infinite regress of messages about messages etc., no ICMP messages are sent about ICMP messages. Also ICMP messages are only sent about errors in handling fragment zero of fragemented datagrams. (Fragment zero has the fragment offeset equal zero). --source: RFC 792
The Internet makes two transport protocols available to its applications, UDP and TCP.
UDP - User Datagram Protocol
UDP, defined in [RFC 768], does just about as little as a transport protocol can. Aside from the multiplexing/demultiplexing function and some light error checking, it adds nothing to IP. In fact, if the application developer chooses UDP instead of TCP, then the application is talking almost directly with IP. UDP takes messages from application process, attaches source and destination port number fields for the multiplexing/demultiplexing service, adds two other fields of minor importance, and passes the resulting "segment" to the network layer. The network layer encapsulates the segment into an IP datagram and then makes a best-effort attempt to deliver the segment to the receiving host. If the segment arrives at the receiving host, UDP uses the port numbers and the IP source and destination addresses to deliver the data in the segment to the correct application process. Note that with UDP there is no handshaking between sending and receiving transport-layer entities before sending a segment. For this reason, UDP is said to be connectionless. --source: Keith W. Ross and James F. Kurose
TCP - Transmission Control Protocol
TCP is a connection-oriented, end-to-end reliable protocol designed to fit into a layered hierarchy of protocols which support multi-network applications. The TCP provides for reliable inter-process communication between pairs of processes in host computers attached to distinct but interconnected computer communication networks. Very few assumptions are made as to the reliability of the communication protocols below the TCP layer. TCP assumes it can obtain a simple, potentially unreliable datagram service from the lower level protocols. In principle, the TCP should be able to operate above a wide spectrum of communication systems ranging from hard-wired connections to packet-switched or circuit-switched networks. --source: RFC 793
Now that you have a basic understanding of using iptables, let's move on to creating an iptables configuration.
5. Securing your workstation
Looking at our connections, we'll use it for creating our iptables configuration. With that said, let's use the netstat command again.
In the above example, notice that we are using ports 4000, 6000, 25, 143, 5190, 1863, 6667, and 5222. We want to restrict anyone from coming in on ports below 1023. Ports which run below 1023 are normally services which accept incoming connections, and unless you are a server, people don't need to be coming in. However, we can't just completely block all the ports below 1023, or else we wouldn't enjoy the use of FTP, SSH, WWW, etc. But what about all those other ports? Shouldn't we block them also? No. If we were to block those ports, then what's the point of having an Internet connection? We need to figure out a way to block ports, but yet allow us to use them at the same time.
Here is what we'll start with:
# /sbin/iptables -A INPUT -s 0/0 -p tcp --destination-port 0:1023 -j DROP # /sbin/iptables -A INPUT -s 0/0 -p udp --destination-port 0:1023 -j DROP
We are telling iptables to APPEND into the INPUT chain, to not allow any TCP or UDP packets from ALL IP addresses (0/0 is equivalent to 0.0.0.0/0). Furthermore, --destination-port means packets that are coming IN, and are destined for ports ranging from 0-1023. And of course, our last portion means DROP the packets completely.
But won't this mean that we can't use SSH, FTP, or WEB? No, we still can. Why is that? Well, because we specified --destination-port rather than --source-port. We are telling iptables to deny incoming packets, but allow us to continue transmitting packets on all ports. When we establish a connection with a service, and it requires a connection with us, it will use ports above 1023. To better understand ports, take a look at The Internet Assigned Numbers Authority's port assignment list.
Okay, next let's prevent users from obtaining information from our connection. To do this, we'll restrict all incoming ICMP requests.
# /sbin/iptables -A INPUT -p icmp -j DROP
Notice we didn't specify a source? We won't have to when specifying the Internet Control Message Protocol. It'll just drop all ICMP requests. Now that we have protected ports 0-1023, we must protect higher ports without causing interruption to services which need an open port. The only one we need to worry about here is port 6000, as this is our X11 (X Windows) port, and this does not need to be accessed by outside users. Here's how we'll add this to our iptables ruleset:
# /sbin/iptables -A INPUT -s 0/0 -p tcp --destination-port 6000 -j DROP # /sbin/iptables -A INPUT -s 0/0 -p udp --destination-port 6000 -j DROP
Now nobody can access port 6000 on our box. Oh, crap! But what about us??? Yes, we'll need access to it, of course!
Ahhh, there we go. Now our machine can communication with the X Windows server. Notice something different? I used the -I switch this time. When packets come in, iptables looks from the top of the ruleset, and works its way down. Each time you use the APPEND (-A) switch, the command goes to the bottom of the ruleset list. If we were to reject packets on port 6000, but allow us access, we must be at the top of the list, or else we will be ignored. It's basically a "first come, first serve" kinda operation. ;)
This should give you an idea of how to use iptables, and to have a semi-secured workstation. However, everyone operates their machine differently. This is just an example, and now it's up to you to play around with iptables and get the right configuration.
6. Conclusion
Please take caution when working with iptables. You can end up locking yourself out of your own machine, if you aren't careful. But if you do, just reboot. When you restart the machine, your iptables ruleset will be cleared and you will start with an emtpy list. If you wish to save your configuration (and I suggest making sure it's a working configuration), then you can either to do things.
1. Use the built-in iptables-save tool -or- 2. Write a script, and have it load in your network script
I recommend #2. This way, if you screw up with your configuration, you can safely boot into your machine without starting the network script. Then you can modify your iptables script, or scratch it completely after hours and hours of frustration. Yeah!!
There is a great deal more to iptables, as I stated in the beginning of this tutorial. We have learned the basic function of the iptables packet filtering, and I suggest playing around with what you have learned. The next tutorial will explain routing procedures, connection tracking, and packet mangling.