iptables
iptables is the userspace command line program used to configure the Linux 2.4.x and later IPv4 packet filtering ruleset. It is targeted towards system administrators. Since Network Address Translation is also configured from the packet filter ruleset, iptables is used for this, too.
iptables is the tables provided by the Linux kernel firewall (implemented as different Netfilter modules) and the chains and rules it stores. Different kernel modules and programs are currently used for different protocols
- iptables applies to IPv4
- ip6tables to IPv6
- arptables to ARP
- ebtables to Ethernet frames.
- iptables
- List the rules in the chain(s)
- Accept inbound traffic
- Add rules
- Deleting Rules
- Inserting rules
- Flushing
- Relaying HTTP Port 80 Connections to 8080
- Blocking Incoming Traffic Based on Networks
- IP Range Match
- Whitelisting Incoming Traffic From specific IP addresses / Netetworks
- State Match
- conntrack match
- Filtering DNS
- Example iptables rules
- Reference
List the rules in the chain(s)
iptables -L iptables -L -vn
Accept inbound traffic
Set default policy for INPUT (inbound traffic) to DROP (deny by default)
iptables -P INPUT DROP
Add rules
Allows HTTP and HTTPS connections from anywhere (the normal ports for websites)
iptables -A INPUT -p tcp --dport 80 -j ACCEPT iptables -A INPUT -p tcp --dport 443 -j ACCEPT
NOTE: ALL -m tcp is OPTIONAL.
OR do the above at once (plus specify the interface => eth0)
iptables -A INPUT -i eth0 -p tcp -m multiport --dport 80,443 -j ACCEPT
Allow PPTP VPN on port 1723
iptables -A INPUT -p tcp --dport 1723 -j ACCEPT
Allow ping (ICMP)
iptables -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT
Allow outbound traffic
The example allows all outbound traffic, change it if needed
iptables -A OUTPUT -j ACCEPT
Accepts all established inbound and outbound connections
IMPORTANT: add rules to the INPUT / OUTPUT chain which allows ESTABLISHED and RELATED packets
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
Reject all other inbound - default deny unless explicitly allowed policy
iptables -A INPUT -j REJECT iptables -A FORWARD -j REJECT
Deleting Rules
Use
- -D
- --delete
Examples:
iptables --delete INPUT -p tcp --dport 80 -j ACCEPT iptables -D INPUT -p tcp --dport 443 -j ACCEPT
Inserting rules
The loopback port is blocked. We could have written the drop rule for just eth0 by specifying -i eth0, but we could also add a rule for the loopback. If we append this rule, it will come too late - after all the traffic has been dropped. We need to insert this rule before that. Since this is a lot of traffic, we'll insert it as the first rule so it's processed first.
iptables -I INPUT 1 -i lo -j ACCEPT
Flushing
Flush the selected chain.
iptables -F chain iptables --flush chain
Flush the selected chain (all the chains in the table if none is given). This is equivalent to deleting all the rules one by one.
IMPORTANT: remember to change INPUT chain policy to ACCEPT before flushing if you are doing it via SSH!!!
List rules in a specified chain
iptables -S INPUT iptables -S OUTPUT iptables -S FORWARD
Relaying HTTP Port 80 Connections to 8080
Check if both ports - 8080 and 80 are open in your iptables script.
Add a NAT rule on your iptables to redirect the default port 8080 to the destination port 80.
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080 iptables -t nat -A OUTPUT -p tcp --dport 80 -j REDIRECT --to-port 8080
Tomcat example
Relay port 80 TCP connections to Tomcat port 8080
iptables -t nat -I PREROUTING -p tcp --dport 80 -j REDIRECT --to-ports 8080 iptables -t nat -I OUTPUT -p tcp --dport 80 -j REDIRECT --to-ports 8080
NOTE: By default Tomcat listens on port 8080. To have the Tomcat server itself listen on HTTP port 80, Tomcat would have to run as root since only root can listen on ports below 1024 on *NIX. However, for security reasons this is NOT recommended.
Solutions:
- Relay port 80 TCP connections to port 8080 using Netfilter / iptables
- Use Apache or Nginx as reverse proxy in front of Tomcat
Blocking Incoming Traffic Based on Networks
source
- -s
- --src
- --source
Used to match package coming from specific IP or network
# specific IP iptables -A INPUT -s 192.168.1.1 -j DROP # network / netmask iptables -A INPUT -s 192.168.1.1/255.255.255.0 -j DROP # network / CIDR iptables -A INPUT -s 192.168.1.1/24 - j DROP
NOTE: This is the source match, which is used to match packets, based on their source IP address. The main form can be used to match single IP addresses, such as 192.168.1.1. It could also be used with a netmask in a CIDR "bit" form, by specifying the number of ones (1's) on the left side of the network mask. This means that we could for example add /24 to use a 255.255.255.0 netmask. We could then match whole IP ranges, such as our local networks or network segments behind the firewall. The line would then look something like 192.168.0.0/24. This would match all packets in the 192.168.0.x range. Another way is to do it with a regular netmask in the 255.255.255.255 form (i.e., 192.168.0.0/255.255.255.0). We could also invert the match with an ! just as before. If we were, in other words, to use a match in the form of --source ! 192.168.0.0/24, we would match all packets with a source address not coming from within the 192.168.0.x range. The default is to match all IP addresses.
Example
- 255.255.255.0 => 11111111.11111111.11111111.00000000 => /24
- 255.255.255.255 => 11111111.11111111.11111111.11111111 => /32
- 255.255.0.0 => 11111111.11111111.00000000.00000000 => /16
- 255.0.0.0 => 11111111.00000000.00000000.00000000 => /8
- 255.255.252.0 => 11111111.11111111.11111100.00000000 /22
- 255.255.255.128 => 11111111.11111111.11111111.10000000 => /25
destination
- -d
- --dst
- --destination
Use to match package going to specific IP or network
# specific IP iptables -A INPUT -d 192.168.1.1 -j DROP # network / netmask iptables -A INPUT -d 192.168.1.0/255.255.255.0 -j DROP # network / CIDR iptables -A INPUT -d 192.168.1.0/24 -j DROP
NOTE: The --destination match is used for packets based on their destination address or addresses. It works pretty much the same as the --source match and has the same syntax, except that the match is based on where the packets are going to. To match an IP range, we can add a netmask either in the exact netmask form, or in the number of ones (1's) counted from the left side of the netmask bits. Examples are: 192.168.0.0/255.255.255.0 and 192.168.0.0/24. Both of these are equivalent. We could also invert the whole match with an ! sign, just as before. --destination ! 192.168.0.1 would in other words match all packets except those destined to the 192.168.0.1 IP address.
IP Range Match
-m iprange
The IP range match is used to match IP ranges, just as the --source and --destination matches are able to do as well. However, this match adds a different kind of matching in the sense that it is able to match in the manner of from IP - to IP, which the --source and --destination matches are unable to. This may be needed in some specific network setups, and it is rather a bit more flexible. The IP range match is loaded by using the -m iprange keyword.
Source --src-range
Block IP range 192.168.1.13-192.168.2.19
iptables -A INPUT -p tcp -m iprange --src-range 192.168.1.13-192.168.2.19
NOTE: This matches a range of source IP addresses. The range includes every single IP address from the first to the last, so the example above includes everything from 192.168.1.13 to 192.168.2.19. The match may also be inverted by adding an !.
Invert by using !
iptables -A INPUT -p tcp -m iprange ! --src-range 192.168.1.13-192.168.2.19
The above example would then look like -m iprange ! --src-range 192.168.1.13-192.168.2.19, which would match every single IP address, except the ones specified.
Destination --dst-range
Matches packets destined to IP range.
iptables -A INPUT -p tcp -m iprange --dst-range 192.168.1.13-192.168.2.19
NOTE: The --dst-range works exactly the same as the --src-range match, except that it matches destination IP's instead of source IP's.
Whitelisting Incoming Traffic From specific IP addresses / Netetworks
Add rules to INPUT chain and then change the default policy to DROP
iptables -A INPUT -s 12.34.56.78 -j ACCEPT iptables -A INPUT -s 192.168.0.0/24 -j ACCEPT iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -P INPUT DROP
NOTE: State match rule is very IMPORTANT!!! See below.
State Match
The state match extension is used in conjunction with the connection tracking code in the kernel. The state match accesses the connection tracking state of the packets from the conntracking machine. This allows us to know in what state the connection is, and works for pretty much all protocols, including stateless protocols such as ICMP and UDP. In all cases, there will be a default timeout for the connection and it will then be dropped from the connection tracking database. This match needs to be loaded explicitly by adding a -m state statement to the rule. You will then have access to one new match called state. The concept of state matching is covered more fully in the The state machine chapter, since it is such a large topic.
What does it mean!?
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
NOTE: This match option tells the state match what states the packets must be in to be matched.
There are currently 4 states that can be used
- INVALID - means that the packet is associated with no known stream or connection and that it may contain faulty data or headers.
- ESTABLISHED - means that the packet is part of an already established connection that has seen packets in both directions and is fully valid.
- NEW - means that the packet has or will start a new connection, or that it is associated with a connection that has not seen packets in both directions.
- RELATED - means that the packet is starting a new connection and is associated with an already established connection.
This could for example mean an FTP data transfer, or an ICMP error associated with a TCP or UDP connection. Note that the NEW state does not look for SYN bits in TCP packets trying to start a new connection and should, hence, not be used unmodified in cases where we have only one firewall and no load balancing between different firewalls. However, there may be times where this could be useful. For more information on how this could be used, read the The state machine chapter.
conntrack match
The conntrack match is an extended version of the state match, which makes it possible to match packets in a much more granular way. It let's you look at information directly available in the connection tracking system, without any "frontend" systems, such as in the state match. For more information about the connection tracking system, take a look at the The state machine chapter.
iptables -A INPUT -p tcp -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
This match is used to match the state of a packet, according to the conntrack state. It is used to match pretty much the same states as in the original state match.
The valid entries for this match are
- INVALID
- ESTABLISHED
- NEW
- RELATED
- SNAT
- DNAT
NOTE: The entries can be used together with each other separated by a comma. For example, -m conntrack --ctstate ESTABLISHED,RELATED. It can also be inverted by putting a ! in front of --ctstate. For example: -m conntrack ! --ctstate ESTABLISHED,RELATED, which matches all but the ESTABLISHED and RELATED states.
Filtering DNS
Filtering GFW DNS pollution
iptables -A INPUT --source 8.8.8.8,8.8.4.4 -p udp --source-port 53 -m ttl --ttl-gt 48 -j DROP
Example iptables rules
Example iptables rules on a Ubuntu Server
*filter -P INPUT DROP -P FORWARD ACCEPT -P OUTPUT ACCEPT -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT -A INPUT -i lo -j ACCEPT -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT -A INPUT -p icmp -m icmp --icmp-type 8 -j ACCEPT -A INPUT -p tcp -m tcp --dport 8080 -j ACCEPT COMMIT
Example 2 (with comments)
*filter # Allow all loopback (lo) traffic and drop all traffic to 127.0.0.0/8 that doesn't use lo -A INPUT -i lo -j ACCEPT -A INPUT -d 127.0.0.0/8 -j REJECT # Accept all established inbound connections -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT # conntrack match is recommended # -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT # Allow all outbound traffic # It can be modified to allow ONLY certain traffic -A OUTPUT -j ACCEPT # Allow SSH connections # The -dport number should be the same port number set in sshd_config -A INPUT -p tcp -m state --state NEW --dport 22 -j ACCEPT # Allow HTTP and HTTPS connections from anywhere (the normal ports for websites and SSL). -A INPUT -p tcp --dport 80 -j ACCEPT -A INPUT -p tcp --dport 443 -j ACCEPT # Allow ping -A INPUT -p icmp -j ACCEPT # Log iptables denied calls -A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7 # Drop all other inbound - default deny unless explicitly allowed policy # -A INPUT -j DROP -P INPUT DROP # -A FORWARD -j DROP -P FORWARD DROP COMMIT
Example 3 - clearing - iptables rules
cat >/usr/local/bin/flush_iptables.sh <<EOF #!/bin/sh iptables -P INPUT ACCEPT iptables -P FORWARD ACCEPT iptables -P OUTPUT ACCEPT iptables -t nat -P PREROUTING ACCEPT iptables -t nat -P POSTROUTING ACCEPT iptables -t nat -P OUTPUT ACCEPT iptables -F iptables -X iptables -t nat -F iptables -t nat -X iptables -t mangle -F iptables -t mangle -X EOF chmod +x /usr/local/bin/flush_iptables.sh
Example 4 - script to start/reload/stop iptables rules
#! /bin/sh ### BEGIN INIT INFO # Provides: Firewall # Required-Start: $network # Required-Stop: # Default-Start: # Default-Stop: # Short-Description: Start/stop iptables ### END INIT INFO test -r ~/DevOps/scripts/iptables.rules || exit 0 case "$1" in start) echo -n "Starting firewall" /sbin/iptables-restore < ~/DevOps/scripts/iptables.rules ;; stop) echo -n "Stopping firewall and clearing iptables rules" /sbin/iptables -P INPUT ACCEPT /sbin/iptables -P FORWARD ACCEPT /sbin/iptables -P OUTPUT ACCEPT /sbin/iptables -t nat -P PREROUTING ACCEPT /sbin/iptables -t nat -P POSTROUTING ACCEPT /sbin/iptables -t nat -P OUTPUT ACCEPT /sbin/iptables -F /sbin/iptables -X /sbin/iptables -t nat -F /sbin/iptables -t nat -X /sbin/iptables -t mangle -F /sbin/iptables -t mangle -X ;; restart|reload) echo -n "Restarting firewall" /sbin/iptables-restore < ~/DevOps/scripts/iptables.rules ;; *) echo "Usage: firewall {start|stop|restart|reload}" exit 1 esac
Load iptables rules on boot
Dump iptables rules - backup
iptables-save > /path/to/file
Restore iptables rules from file
iptables-restore < /path/to/file
Write a script named iptables in /etc/network/if-pre-up.d instead of /etc/network/if-up.d
IMPORTANT: The pre-up configuration activates the iptables rules before the public interface (e.g. eth0) comes up. For security reasons (best practice) it's important that firewall rules are established before the network interfaces come up.
#!/bin/sh iptables-restore < /path/to/file
Make it executable
chmod +x /etc/network/if-pre-up.d/iptables
Done!
OR it can be done directly in /etc/network/interfaces - the network interface configuration for ifup and ifdown
# The primary network interface auto eth0 iface eth0 inet static address 10.187.65.71 netmask 255.255.255.0 network 10.187.65.0 broadcast 10.187.65.255 gateway 10.187.65.1 pre-up iptables-restore < /path/to/iptables.rules # dns-* options are implemented by the resolvconf package, if installed dns-nameservers 10.187.64.12 10.187.82.13 192.135.82.76 dns-search au.oracle.com
NOTE: There exists for each of the above mentioned options a directory /etc/network/if-<option>.d/ the scripts in which are run (with no arguments) using run-parts after the option itself has been processed. Please note that as post-up and pre-down are aliases, NO files in the corresponding directories are processed. Use if-up.d and if-down.d directories instead.