How to create your iptables firewall
What is iptables?
From Wikipedia, the free encyclopedia: „iptables is a user-space application program that allows a system administrator to configure the tables provided by the Linux kernel firewall (implemented as different Netfilter modules) and the chains and rules it stores.”
- table – iptables contains some pre-defined tables. We will be investigating 2 of them:
- filter – the default table
- nat – a table used for address translation rules
- chain – tables contain chains, where rules are defined after another. You may picture it as a real chain. When a packet goes through the chain it’s like a drop of water rolling down on a hanging chain. If that drop is “matched” on one of the links, it stops there.
- The filter table has 3 built-in chains: INPUT, OUTPUT and FORWARD. Each for the corresponding traffic travelling to, from and through the server
- The nat table has 2 built-in chains: PREROUTING and POSTROUTING. They are used before and after the packet has been routed. PREROUTING is mostly used for DNAT (destination address translation, we change the destination in the IP packet) and POSTROUTING for SNAT (source address translation, the originating IP is being changed)
- action – what happens with the drop on the link of the chain
- policy – the default action at the end of the chain – what happens with falling down drops leaving the last link
The basic firewall configuration
The following example suits most of the cases, and can provide a good basis for further rules.
- We need some variables to be set
echo “1” > /proc/sys/net/ipv4/ip_forward #needed for forwarding packets
echo “1” > /proc/sys/net/ipv4/ip_dynaddr #needed for masquerading (snat)
- Let’s set the policy of the 3 chains in the filter table. You may also define –t filter.
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP
- We delete all rules that may present in these chains, and also all in the nat table:
iptables -F INPUT
iptables -F OUTPUT
iptables -F FORWARD
iptables -t nat –F
- All packets that are related to previous communication should be enabled in the INPUT and FORWARD chains as well.
iptables -A INPUT -m state –state ESTABLISHED,RELATED -j ACCEPT
iptables -A FORWARD -m state –state ESTABLISHED,RELATED -j ACCEPT
- Usually I like to have ping enabled, but with a limited rate:
iptables -A INPUT -p icmp -m limit –limit 10/sec -j ACCEPT
- We’d like to enable all packets coming in to the local loopback interface:
iptables -A INPUT -i lo -j ACCEPT
- SSH should also be enabled:
iptables -A INPUT -p tcp –dport 22 -j ACCEPT
Please note that no INPUT communication will be enabled, for which we have not created a rule. The best is to put the rules above to a script, and execute it in one run.
Some common rules
The following (sets of) commands provide examples for some common cases. They can be included at the end of your basic firewall, thus enabling some more communications, and doing smaller “tricks”.
DNAT aka. port-forwarding
If You have a VM or router that functions as a firewall for your LAN, you may need some ports on the public interface to be forwarded to internal ports.
Some examples when they are needed:
- You have a torrent client which needs a public port for active mode
- You have a windows machine on your LAN, and You’d like to access it’s RDP (3389) port from the internet.
For DNAT we have to use the nat table and especially the PREROUTING chain, since we’d like to change the packet before it’s being routed. So a packet that comes from the internet will be forwarded to the LAN. We’ll also have to enable input and forwarding of this package.
Let’s see an example of forwarding a high port to the LAN IP of our Windows workstation:
iptables –A INPUT –i eth0 –p tcp –dport 45678 –j ACCEPT
iptables –t nat –A PREROUTING –i eth0 –p tcp –dport 45678 –j DNAT –-to 192.168.1.3:3389
iptables –A FORWARD –i eth0 –o eth1 –p tcp –dport 3389 –j ACCPET
#eth0 is the connection to the Internet with the public IP
#eth1 is the connection to the LAN
#tcp45678 is the public high port we’re using
#192.168.1.3 is the IP address of the Windows workstation on the LAN
#tcp3389 is the default port for RDP
MASQUERADE – “Internet sharing”
The other most common scenario is when want your Internet connection to be shared for your LAN
Besides the following rules, the ip_dynaddr variable must be set. (check your basic firewall configuration for this)
- The traffic will originate from the computers on your LAN, so we have to enable forwarding of these packages.
iptables –A FORWARD –i eth1 –o eth0 –j ACCEPT
#eth0 is the Internet interface
#eth1 is the LAN interface of your firewall
- As computers on the Internet will not know where to send their replies to the requests of your LAN computers (they include a private IP in their requests), we have to hide the LAN IPs, and replace them with our public IP as the source when they leave our firewall toward the Internet. This is MASQUERADING. We could also use SNAT (source network address translation) but for that we must specify the IP address that we’d like to use. Since usually our public IP changes occasionally, it’s easier to have this IP-replacement dynamically with MASQUERADE.
iptables –t nat –A POSTROUTING –o eth0 –j MASQUERADE
The above basic firewall with the 2 extra “extensions” are suitable in 90% of the cases, and simple SOHO routers include also only port forwarding (some only symmetrical) and “Internet sharing”
For more complex needs please refer to the manual of iptables and for offline reading I strongly recommend: Gregor N. Purdy’s Linux iptables Pocket Reference http://shop.oreilly.com/product/9780596005696.do
Some hints on using iptables
- -A adds rules to the end of the chain, while –I inserts rules to the beginning of it. Better not to mix them, so your firewall can stay well-readable
- You may save your running firewall with iptables-save and restore with iptables-restore
- if You’d like to run your firewall script on boot
- You may need proper headers for it:
### BEGIN INIT INFO
# Provides: firewall
# Required-Start: $ local_fs $ network
# Required-Stop: $ local_fs
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: firewall
# Description: iptables-based firewall service
### END INIT INFO
- and include it to the default runlevels
update-rc.d myfirewall.sh defaults