Difference between revisions of "Iptables"

From Noah.org
Jump to navigationJump to search
 
(17 intermediate revisions by the same user not shown)
Line 4: Line 4:
 
== Linux iptables Basic Examples ==
 
== Linux iptables Basic Examples ==
  
The following are simple iptables firewalls for Linux. I use these as starter firewalls when I setup a machine.
+
The following are simple iptables firewalls for Linux. I use these as starter firewalls when I setup a machine. I don't like using iptables-restore. I prefer to simply script the iptables commands that I would type at the command line.
I don't like using iptables-restore. I prefer to simply script the iptables commands that  
+
 
I would type at the command line.
+
Most of these scripts start by reinitializing iptables, so you will loose any rules, chains, or accounting information that iptables knows about. For example, this deletes any policies, chains, and rules in place.
  
Most of these scripts start by reinitializing iptables, so you will loose
 
any rules, chains, or accounting information that iptables knows about.
 
For example, this deletes any policies, chains, and rules in place.
 
 
<pre>
 
<pre>
 
iptables -P INPUT ACCEPT    # open up default policy on built-in chain
 
iptables -P INPUT ACCEPT    # open up default policy on built-in chain
Line 21: Line 18:
 
=== Block everything firewall ===
 
=== Block everything firewall ===
  
This blocks everything. You will only be able to access the machine from the console. Don't do this if you are working remotely because your connection will instantly be dropped. Another way to do this would be to disable the network interface. The advantage of blocking everything with iptables instead of shutting down a network interface is that this leaves the kernel network layer still running. Running apps will not complain about the network being unavailable. This also blocks all network interfaces at once, so if you have a machine with multiple interfaces this will take care of them all.
+
This blocks everything. You will only be able to access the machine from the console. Don't do this if you are working remotely because your connection will instantly be dropped. Another way to do this would be to disable the network interface. The advantage of blocking everything with iptables instead of shutting down a network interface is that this leaves the kernel network layer still running. Applications will not complain about the network being unavailable. This also blocks all network interfaces at once, so if you have a machine with multiple interfaces this will take care of them all.
  
 
<pre>
 
<pre>
Line 37: Line 34:
 
=== Allow everything firewall ===
 
=== Allow everything firewall ===
  
This opens up everything. It's the exact opposite of [[#Block everything|Block everything]].  
+
This opens up everything. It's the exact opposite of [[#Block everything|Block everything]]. The firewall is still technically running, but every packet is allowed through. This is the safe way to open the firewall without accidentally locking yourself out.
The firewall is still technically running, but every packet is allowed through.
 
This is the safe way to open the firewall without accidentally locking yourself out.
 
  
 
<pre>
 
<pre>
Line 54: Line 49:
 
I use this to shut down everything except SSH port 22. This is my panic script. If something seems suspicious then I use this script to put a machine into as safe a state as possible while still allowing remote SSH connections.
 
I use this to shut down everything except SSH port 22. This is my panic script. If something seems suspicious then I use this script to put a machine into as safe a state as possible while still allowing remote SSH connections.
  
Note that a machine with these rules won't even be visible on the network. If you want to scan it with nmap you will have to use "nmap -P0" which scans without first checking with ICMP (ping).
+
Note that a machine with these rules won't be visible on the network with ping. Nmap by default does a ping test before mapping a machine. If you want to scan it with nmap you will have to use "nmap -P0" to scan without first checking ping.
  
 
<pre>
 
<pre>
Line 70: Line 65:
 
</pre>
 
</pre>
  
=== Basic firewall init.d script ===
+
=== A practical, simple iptables firewall init.d script ===
  
For my real firewall I use an init.d script.
+
For my real firewall I use an init.d script to store the configuration and to load the rules when the system boots. RedHat has a similar mechanism setup by default. Oddly, Ubuntu has no standard for restoring iptables rules on boot which is why I wrote this script to begin with. It turned out that I liked storing the rules this way better than I liked the RedHat style anyway.
The following init script is based on the scripts given previously.
 
Save this in /etc/init.d/firewall. This includes options to start, stop, or
 
show the status of iptables. The "stop" command doesn't really stop iptables.  
 
It just deletes all firewall rules.
 
<pre>
 
#!/bin/sh
 
  
N=/etc/init.d/firewall
+
To restore rules on boot, copy this script to /etc/init.d/firewall. On Ubuntu or Debian systems, run "update-rc.d firewall defaults" and the system will from then on start loading the firewall rules on boot. On RedHat systems, run "chkconfig --add firewall" and the system will run the script on boot.
  
set -e
+
This script includes options to start, stop, and show the status of iptables. The "stop" command doesn't really stop iptables (it is not a daemon). In this case, "stop" just flushes all policies and rules which opens networking to all traffic.
  
case "$1" in
+
Click here to download: [http://www.noah.org/engineering/src/shell/firewall firewall]
  start)
+
<include src="http://www.noah.org/engineering/src/shell/firewall" highlight="sh" />
    # Flush any old policies and rules.
 
    iptables -P INPUT ACCEPT
 
    iptables -P OUTPUT ACCEPT
 
    iptables -P FORWARD ACCEPT
 
    iptables -F
 
    iptables -X
 
  
    # New TCP connections must be SYN packets, else DROP
+
=== Funny story ===
#    iptables -A INPUT -i eth0 -p tcp ! --syn -m state --state NEW -j DROP
 
    iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP
 
  
    # Drop illegal packets
+
At one time I had an iptables rule on all my machines that limited pings to 1 per second. By default the ping command sends 1 ICMP packet per second. Everything was fine and eventually I forgot about the rule. Months later I noticed that mtr was reporting high packet loss to a machine. A co-worker helped me investigate and the packet loss only got worse. Then the machine would intermittently stop accepting new SSH connections. All outside connections go through a load balancer. The load balancer is setup to probe each cluster and if a machine does not respond to a ping every 10 minutes then the load balancer removes that machine from rotation (even if there is only one machine in a cluster). So as we tried to debug our packet loss with ping and mtr it would cause iptables to block ICMP and if the load balancer happened to be doing a probe then it would take the machine off the network. We thought things were really bad because we couldn't even connect to the server through through the load balancer interface. Huge packet loss and dropped SSH connections -- we were thinking to check for bad cables, bad switch, or a bad load balancer. Then we checked the load balancer logs and saw that it had removed the machine because of failed ping probes. Eventually I tried shutting off iptables and the problem went away. Finally we decided to look at the iptables rules which revealed the rule that was causing all the grief. This will cause apparent packet loss if two engineers both ping at the same time:
    iptables -A INPUT -p tcp --tcp-flags ALL FIN,URG,PSH -j DROP
 
    iptables -A INPUT -p tcp --tcp-flags ALL ALL -j DROP
 
    iptables -A INPUT -p tcp --tcp-flags ALL NONE -j DROP # NULL packets
 
    iptables -A INPUT -p tcp --tcp-flags SYN,RST SYN,RST -j DROP
 
    iptables -A INPUT -p tcp --tcp-flags SYN,FIN SYN,FIN -j DROP #XMAS
 
    iptables -A INPUT -p tcp --tcp-flags FIN,ACK FIN -j DROP # FIN packet scans
 
    iptables -A INPUT -p tcp --tcp-flags ALL SYN,RST,ACK,FIN,URG -j DROP
 
  
    #
+
<pre>
    # Accept some remote connections.
+
iptables -A INPUT -p icmp --icmp-type 8 -m limit --limit 1/second -j ACCEPT
    #
+
</pre>
    # SSH
 
    iptables -A INPUT -p tcp --dport 22 -j ACCEPT
 
    # HTTP
 
    iptables -A INPUT -p tcp --dport 80 -j ACCEPT
 
    # HTTPS
 
    iptables -A INPUT -p tcp --dport 443 -j ACCEPT
 
    # SMTP
 
    iptables -A INPUT -p tcp --dport 25 -j ACCEPT
 
    # DNS
 
    iptables -A INPUT -p udp --dport 53 -j ACCEPT
 
    iptables -A INPUT -p tcp --dport 53 -j ACCEPT
 
    # VMware
 
    iptables -A INPUT -p tcp --dport 902 -j ACCEPT
 
    # SNMP
 
    #iptables -A FWALL-INPUT-p udp -m udp --dport 161 -j ACCEPT
 
    #iptables -A FWALL-INPUT-p udp -m udp --sport 1023:2999 -j ACCEPT
 
  
    #
+
== Load firewall on boot ==
    # Accept some localhost connections.
 
    #
 
    # IMAP
 
    iptables -A INPUT -p tcp -s 127.0.0.1 --dport 143 -j ACCEPT
 
    # MySQL
 
    iptables -A INPUT -p tcp -s 127.0.0.1 --dport 3306 -j ACCEPT
 
    # PostgreSQL
 
    iptables -A INPUT -p tcp -s 127.0.0.1 --dport 5432 -j ACCEPT
 
    # BIND RNDC
 
    iptables -A INPUT -p tcp -s 127.0.0.1 --dport 953 -j ACCEPT
 
    # VNC -- You should use an SSH tunnel to expose this to remote connections.
 
    iptables -A INPUT -p tcp -s 127.0.0.1 --dport 5900 -j ACCEPT
 
    # Subversion svnserve (you should probably just use the svn+ssh: URL scheme)
 
    iptables -A INPUT -p tcp -s 127.0.0.1 --dport 3690 -j ACCEPT
 
  
    # Allow some ICMP (ping)
+
When you shutdown your server all the iptables rules will be lost. You need to run a firewall script every time you boot.
    # ICMP is low priority so I put this after other rules.
+
Some people use [http://www.fs-security.com/ firestarter], but I prefer edit my own simple init script.
    iptables -A INPUT -p icmp --icmp-type 0 -j ACCEPT
 
    iptables -A INPUT -p icmp --icmp-type 3 -j ACCEPT
 
    iptables -A INPUT -p icmp --icmp-type 11 -j ACCEPT
 
    iptables -A INPUT -p icmp --icmp-type 8 -m limit --limit 1/second -j ACCEPT
 
    iptables -A INPUT -p icmp -j DROP
 
  
    # Match related and established state connections.
+
=== RedHat ===
    # This allows client-side connections such as ftp work properly.
 
    iptables -A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
 
  
    # Default policies to handle everything not covered by a rule.
+
For RedHat you need to edit:
    iptables -P INPUT DROP
 
    iptables -P OUTPUT ACCEPT
 
    iptables -P FORWARD ACCEPT
 
    ;;
 
  stop)
 
    iptables -P INPUT ACCEPT
 
    iptables -P OUTPUT ACCEPT
 
    iptables -P FORWARD ACCEPT
 
    iptables -F
 
    iptables -X
 
    ;;
 
  status)
 
    iptables -L -v
 
    ;;
 
  *)
 
    echo "Usage: $N {start|stop|status}" >&2
 
    exit 1
 
    ;;
 
esac
 
  
exit 0
+
<pre>/etc/sysconfig/iptables</pre>
</pre>
+
 
 +
Don't confuse this with /etc/sysconfig/iptables-config. Also note that RedHat has a tool called system-security-level that overwrites /etc/sysconfig/iptables, so if you run system-security-level you will loose your changes. You can edit the file manually or you can use system-security-level. Choose one or the other, not both.
  
== Load firewall on boot ==
+
You can also setup the firewall the way you want using the iptables command and then save the settings using RedHat's inti.d script:
When you shutdown your server all the iptables rules will be lost.
 
You need to run a firewall script every time you boot.
 
Some people use [http://www.fs-security.com/ firestarter], but I prefer edit
 
my own simple init script.
 
  
=== RedHat ===
+
<pre>/etc/init.d/iptables save</pre>
For RedHat you need to edit:
 
    <pre>/etc/sysconfig/iptables</pre>
 
Don't confuse this with /etc/sysconfig/iptables-config.
 
Also note that RedHat has a tool called system-security-level that
 
overwrites /etc/sysconfig/iptables, so if you run system-security-level
 
you will loose your changes. You can edit the file manually or you can
 
use system-security-level. Choose one or the other, not both.
 
  
 
=== Ubuntu/Debian ===
 
=== Ubuntu/Debian ===
 +
 
For Ubuntu/Debian you can put an init script into /etc/init.d then link to an 'S' file in /etc/rc2.d
 
For Ubuntu/Debian you can put an init script into /etc/init.d then link to an 'S' file in /etc/rc2.d
 +
 
<pre>
 
<pre>
 
cp firewall /etc/init.d/firewall
 
cp firewall /etc/init.d/firewall
Line 203: Line 113:
  
 
== Traffic shaping ==
 
== Traffic shaping ==
 +
 
Most iptables installs come with the "TOS" module (Type Of Service):
 
Most iptables installs come with the "TOS" module (Type Of Service):
 +
 
<pre>
 
<pre>
 
iptables -m tos -h
 
iptables -m tos -h
 
</pre>
 
</pre>
This lets you set priority options for packets.
 
  
This is a complex topic. I need to expand this with a simple setup that
+
The TOS module lets you flag packets for different processing based on the IP packet header's TOS (now called Differentiated Services Code Point -- DSCP). IP packet headers contain an 8 bit field called DSCP (previously TOS) which can be used by the user application to indicate the priority of traffic. OpenSSH marks its packets depending on whether they originate from `ssh` or `scp`. The `ssh` packets are marked as "low delay" which denotes interactive traffic whereas `scp` packets are marked as "throughput" which denotes bulk traffic that is not sensitive to delays or latency.
shows how to boost priority of interactive applications like SSH and
+
 
possibly HTTP, while lowering priority for everything else.
+
Iptables also has a "DSCP" module. It's not clear which one to use for traffic shaping of SSH traffic. It seems that OpenSSH is still using the old TOS values, so it may be that the "TOS" module is the better choice at the moment.
[http://gentoo-wiki.com/HOWTO_Packet_Shaping | Gentoo Wiki] is one of the better
+
 
 +
This is a complex topic. I need to expand this with a simple setup that shows how to boost priority of interactive applications like SSH and
 +
possibly HTTP, while lowering priority for everything else. [http://gentoo-wiki.com/HOWTO_Packet_Shaping | Gentoo Wiki] is one of the better
 
documentation sources I have found.
 
documentation sources I have found.
  
 
TCNG seems interesting. I have yet to try it:
 
TCNG seems interesting. I have yet to try it:
 +
 
http://tcng.sourceforge.net/
 
http://tcng.sourceforge.net/
  
 
I tried this without much luck:
 
I tried this without much luck:
 +
 
http://lartc.org/howto/lartc.cookbook.ultimate-tc.html#AEN2210
 
http://lartc.org/howto/lartc.cookbook.ultimate-tc.html#AEN2210
  
Line 227: Line 142:
 
=== Ban -- block an annoying machine ===
 
=== Ban -- block an annoying machine ===
  
This blocks a specific IP address from reaching your server.
+
This blocks a specific IP address from reaching your server. This is useful if you are getting annoying traffic from another machine and you want to get rid of them. Replace 255.255.255.255 with the IP address you want to drop.
This is useful if you are getting annoying traffic from
 
another machine and you want to get rid of them.
 
Replace 255.255.255.255 with the IP address you want to drop.
 
  
 
<pre>
 
<pre>
Line 246: Line 158:
 
=== Show packet and byte counts ===
 
=== Show packet and byte counts ===
  
This shows the counters for each rule in a chain.
+
This shows the counters for each rule in a chain. This shows the number of packets and bytes that have gone through a specific chain. You can use this to measure traffic.
This shows the number of packets and bytes that have
 
gone through a specific chain. You can use this to
 
measure traffic.
 
  
 
<pre>
 
<pre>
 
iptables -L INPUT -v
 
iptables -L INPUT -v
 
</pre>
 
</pre>

Latest revision as of 16:34, 24 March 2014


Linux iptables Basic Examples

The following are simple iptables firewalls for Linux. I use these as starter firewalls when I setup a machine. I don't like using iptables-restore. I prefer to simply script the iptables commands that I would type at the command line.

Most of these scripts start by reinitializing iptables, so you will loose any rules, chains, or accounting information that iptables knows about. For example, this deletes any policies, chains, and rules in place.

iptables -P INPUT ACCEPT    # open up default policy on built-in chain
iptables -P OUTPUT ACCEPT   # open up default policy on built-in chain
iptables -P FORWARD ACCEPT  # open up default policy on built-in chain
iptables -F                 # delete all rules from all chains
iptables -X                 # delete all user chains (non built-in chains)

Block everything firewall

This blocks everything. You will only be able to access the machine from the console. Don't do this if you are working remotely because your connection will instantly be dropped. Another way to do this would be to disable the network interface. The advantage of blocking everything with iptables instead of shutting down a network interface is that this leaves the kernel network layer still running. Applications will not complain about the network being unavailable. This also blocks all network interfaces at once, so if you have a machine with multiple interfaces this will take care of them all.

#!/bin/sh
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -F
iptables -X
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

Allow everything firewall

This opens up everything. It's the exact opposite of Block everything. The firewall is still technically running, but every packet is allowed through. This is the safe way to open the firewall without accidentally locking yourself out.

#!/bin/sh
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -F
iptables -X

Minimal emergency firewall

I use this to shut down everything except SSH port 22. This is my panic script. If something seems suspicious then I use this script to put a machine into as safe a state as possible while still allowing remote SSH connections.

Note that a machine with these rules won't be visible on the network with ping. Nmap by default does a ping test before mapping a machine. If you want to scan it with nmap you will have to use "nmap -P0" to scan without first checking ping.

#!/bin/sh
# Minimal emergency firewall (block everything except SSH).
iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT
iptables -F
iptables -X
iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT
iptables -P INPUT DROP
iptables -A OUTPUT -p tcp -m tcp --sport 22 -j ACCEPT
iptables -P OUTPUT DROP

A practical, simple iptables firewall init.d script

For my real firewall I use an init.d script to store the configuration and to load the rules when the system boots. RedHat has a similar mechanism setup by default. Oddly, Ubuntu has no standard for restoring iptables rules on boot which is why I wrote this script to begin with. It turned out that I liked storing the rules this way better than I liked the RedHat style anyway.

To restore rules on boot, copy this script to /etc/init.d/firewall. On Ubuntu or Debian systems, run "update-rc.d firewall defaults" and the system will from then on start loading the firewall rules on boot. On RedHat systems, run "chkconfig --add firewall" and the system will run the script on boot.

This script includes options to start, stop, and show the status of iptables. The "stop" command doesn't really stop iptables (it is not a daemon). In this case, "stop" just flushes all policies and rules which opens networking to all traffic.

Click here to download: firewall <include src="http://www.noah.org/engineering/src/shell/firewall" highlight="sh" />

Funny story

At one time I had an iptables rule on all my machines that limited pings to 1 per second. By default the ping command sends 1 ICMP packet per second. Everything was fine and eventually I forgot about the rule. Months later I noticed that mtr was reporting high packet loss to a machine. A co-worker helped me investigate and the packet loss only got worse. Then the machine would intermittently stop accepting new SSH connections. All outside connections go through a load balancer. The load balancer is setup to probe each cluster and if a machine does not respond to a ping every 10 minutes then the load balancer removes that machine from rotation (even if there is only one machine in a cluster). So as we tried to debug our packet loss with ping and mtr it would cause iptables to block ICMP and if the load balancer happened to be doing a probe then it would take the machine off the network. We thought things were really bad because we couldn't even connect to the server through through the load balancer interface. Huge packet loss and dropped SSH connections -- we were thinking to check for bad cables, bad switch, or a bad load balancer. Then we checked the load balancer logs and saw that it had removed the machine because of failed ping probes. Eventually I tried shutting off iptables and the problem went away. Finally we decided to look at the iptables rules which revealed the rule that was causing all the grief. This will cause apparent packet loss if two engineers both ping at the same time:

iptables -A INPUT -p icmp --icmp-type 8 -m limit --limit 1/second -j ACCEPT

Load firewall on boot

When you shutdown your server all the iptables rules will be lost. You need to run a firewall script every time you boot. Some people use firestarter, but I prefer edit my own simple init script.

RedHat

For RedHat you need to edit:

/etc/sysconfig/iptables

Don't confuse this with /etc/sysconfig/iptables-config. Also note that RedHat has a tool called system-security-level that overwrites /etc/sysconfig/iptables, so if you run system-security-level you will loose your changes. You can edit the file manually or you can use system-security-level. Choose one or the other, not both.

You can also setup the firewall the way you want using the iptables command and then save the settings using RedHat's inti.d script:

/etc/init.d/iptables save

Ubuntu/Debian

For Ubuntu/Debian you can put an init script into /etc/init.d then link to an 'S' file in /etc/rc2.d

cp firewall /etc/init.d/firewall
chmod 755 /etc/init.d/firewall
cd /etc/rc2.d/
ln -s ../init.d/firewall S99firewall

Traffic shaping

Most iptables installs come with the "TOS" module (Type Of Service):

iptables -m tos -h

The TOS module lets you flag packets for different processing based on the IP packet header's TOS (now called Differentiated Services Code Point -- DSCP). IP packet headers contain an 8 bit field called DSCP (previously TOS) which can be used by the user application to indicate the priority of traffic. OpenSSH marks its packets depending on whether they originate from `ssh` or `scp`. The `ssh` packets are marked as "low delay" which denotes interactive traffic whereas `scp` packets are marked as "throughput" which denotes bulk traffic that is not sensitive to delays or latency.

Iptables also has a "DSCP" module. It's not clear which one to use for traffic shaping of SSH traffic. It seems that OpenSSH is still using the old TOS values, so it may be that the "TOS" module is the better choice at the moment.

This is a complex topic. I need to expand this with a simple setup that shows how to boost priority of interactive applications like SSH and possibly HTTP, while lowering priority for everything else. | Gentoo Wiki is one of the better documentation sources I have found.

TCNG seems interesting. I have yet to try it:

http://tcng.sourceforge.net/

I tried this without much luck:

http://lartc.org/howto/lartc.cookbook.ultimate-tc.html#AEN2210

This page also has some notes: http://www.void.gr/kargig/blog/2005/07/27/traffic-shaping-a-dsl-line-with-linux/

Handy commands

Ban -- block an annoying machine

This blocks a specific IP address from reaching your server. This is useful if you are getting annoying traffic from another machine and you want to get rid of them. Replace 255.255.255.255 with the IP address you want to drop.

iptables -I INPUT -j DROP -s 255.255.255.255

I set these aliases in my .bash_aliases file (sourced by .bashrc):

alias ban='iptables -I INPUT -j DROP -s'
alias unban='iptables -D INPUT -j DROP -s'

A very useful tool to do this automatically is fail2ban.

Show packet and byte counts

This shows the counters for each rule in a chain. This shows the number of packets and bytes that have gone through a specific chain. You can use this to measure traffic.

iptables -L INPUT -v