Terry : iptables

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.

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:

  1. Relay port 80 TCP connections to port 8080 using Netfilter / iptables
  2. 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.

netmask in CIDR bit form

Icon

Netmask in CIDR bit form - use the number of ones (1's) on the left side of the network mask.

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.

Reference

Linux Firewalls Using iptables

iptables How To

iptables Tutorial