Linux IPTables: Incoming and Outgoing Rule Examples
Default Chain Policy
As you notice below, it says “(policy ACCEPT)” next to all the three chain names (INPUT, OUTPUT, and FORWARD). This indicates that the default chain policy is ACCEPT.
# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp — anywhere anywhere tcp dpt:ssh
DROP all — anywhere anywhere
Chain FORWARD (policy ACCEPT)
target prot opt source destination
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
So, you have two options here.
Option 1: Add drop rules
At the end, add the following three drop rules that will drop all incoming, outgoing, and forward packets (except those that are defined above these three rules). If you do this, the default chain policy is still ACCEPT, which shouldn’t matter, as you are dropping all the packets at the end anyway.
iptables -A INPUT -j DROP
iptables -A OUTPUT -j DROP
iptables -A FORWARD -j DROP
Option 2: Change the default chain policy to DROP
At the beginning, execute the following three commands that will change the chain’s default policy to DROP.
iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP
Now, if you add the allow ssh rule: “iptables -A INPUT -i eth0 -p tcp –dport 22 -j ACCEPT”, and do iptables -L, you’ll notice that it says “(policy DROP)” next to all the three chains.
# iptables -L
Chain INPUT (policy DROP)
target prot opt source destination
ACCEPT tcp — anywhere anywhere tcp dpt:ssh
DROP all — anywhere anywhere
Chain FORWARD (policy DROP)
target prot opt source destination
Chain OUTPUT (policy DROP)
target prot opt source destination
But there is a problem here. The allow ssh incoming connection rule will not work anymore, because all the outgoing packets are dropped.
Allow Basic Operations
Example 1: Allow ping from Outside to Inside
This is to allow ping from outside to your server.You can ping to your server from anywhere.
This involves two steps,First,we need to allow incoming echo-request.Once the echo-request is allowed,we also need to allow the echo-reply.
First,Allow incoming ping(echo-request) request,as shown below.
iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT
Next, Allow outgoing echo-reply response (for the corresponding incoming echo-request).
iptables -A OUTPUT -p icmp --icmp-type echo-reply -j ACCEPT
Example 2: Allow ping from Inside to Outside
This is to allow ping from inside to Internet.You can ping from your server to anywhere.
This involves two steps,First,we need to allow outgoing echo-request.Once the echo-request is allowed,we also need to allow the echo-reply.
iptables -A OUTPUT -p icmp --icmp-type echo-request -j ACCEPT iptables -A INPUT -p icmp --icmp-type echo-reply -j ACCEPT
Example 3 : Allow outbound DNS
iptables -A OUTPUT -p udp -o eth0 --dport 53 -j ACCEPT iptables -A INPUT -p udp -i eth0 --sport 53 -j ACCEPT
Example 4 : Allow outbound NTP
iptables -A OUTPUT -p udp -o eth0 --dport 123 -j ACCEPT iptables -A INPUT -p udp -i eth0 --sport 123 -j ACCEPT
Allow Incoming Connections
When the default policy is DROP for INPUT and OUTPUT chains, for every incoming firewall rule, you need to specify the following two rules.
Request rule: This is the request that comes from the client to the server for the incoming connection.
Response rule: This is for the response that goes out from the server to the client (for the corresponding incoming request).
Example 1: Allow incoming SSH connection
This is to allow SSH connection from outside to your server. i.e You can ssh to your server from outside.
This involves two steps. First, we need to allow incoming new SSH connections. Once the incoming ssh connection is allowed, we also need to allow the response back for that incoming ssh connection.
First, Allow incoming SSH connection request, as shown below.
iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
In the above example:
iptables -A INPUT: Append the new rule to the INPUT chain. For incoming connection request, this always has to be INPUT.
-i eth0: This refers to the input interface. For incoming connections, this always has to be ‘-i’.
-p tcp: Indicates that this is for TCP protocol.
–dport 22: This refers to the destination port for the incoming connection. Port 22 is for ssh.
-m state: This indicates that the “state” matching module is used. We’ll discuss more about “-m” option (and all available matching modules for iptables) in future article.
–state NEW, ESTABLISHED: Options for the “state” matching module. In this example, only NEW and ESTABLISHED states are allowed. The 1st time when a SSH connection request is initiated from the client to the server, NEW state is used. ESTABLISHED state is used for all further request from the client to the server.
Next, Allow outgoing (ESTABLISHED state only) SSH connection response (for the corresponding incoming SSH connection request).
iptables -A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
In the above example:
iptables -A OUTPUT: Append the new rule to the OUTPUT chain. Since this is for the response rule (for the corresponding incoming request) that goes out from the server, this should be OUTPUT.
-o eth0: This refers the output interface. For outgoing connections, this always has to be ‘-o’.
-p tcp: Indicates that this is for TCP protocol.
–sport 22: This refers to the source port for the outgoing connection. Port 22 is for ssh. Since the incoming request (from the previous rule) came to the “destination” port, the outgoing response will go through the “source” port.
-m state: This indicates that the “state” matching module is used.
–state ESTABLISHED: Since this is a response rule, we allow only ESTABLISHED connection (and not any NEW connection).
Example 2: Allow incoming HTTP connection
This is to allow HTTP connection from outside to your server. i.e You can view your website running on the server from outside.
Just like the above SSH incoming rules, this also involves two steps. First, we need to allow incoming new HTTP connection. Once the incoming HTTP connection is allowed, we need to allow the response back for that incoming HTTP connection.
First, Allow incoming HTTP connection request, as shown below.
iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
Next, Allow outgoing (ESTABLISHED only) HTTP connection response (for the corrresponding incoming SSH connection request).
iptables -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT
Note: In the above HTTP request and response rule, everything is same as the SSH example except the port number.
Allow Outgoing Connections
When the default policy is DROP for the INPUT and OUTPUT chains, for every outgoing firewall rule, you need to specify the following two rules.
Request rule: This is the request that goes out from the server to outside for the outgoing connection.
Response rule: This is for the response that comes back from the outside to the server (for the corresponding outgoing request).
Example 3: Allow outgoing SSH connection
This is to allow SSH connection from your server to the outside. i.e You can ssh to outside server from your server.
This involves two steps. First, we need to allow outgoing new SSH connection. Once the outgoing ssh connection is allowed, we also need to allow the response back for that outgoing ssh connection.
First, Allow outgoing SSH connection request, as shown below.
iptables -A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT
In the above example:
iptables -A OUTPUT: Append the new rule to the OUTPUT chain. For outgoing connection request, this always has to be OUTPUT.
-o eth0: This refers the output interface. For outgoing connections, this always has to be ‘-o’.
-p tcp: Indicates that this is for TCP protocol.
–dport 22: This refers to the destination port for the outgoing connection.
-m state: This indicates that “state” matching module is used.
–state NEW, ESTABLISHED: Options for the “state” matching module. In this example, only NEW and ESTABLISHED states are allowed. The 1st time when a SSH connection request is initiated from the server to the outside, NEW state is used. ESTABLISHED state is used for all further request from the server to the outside.
Next, Allow outgoing (ESTABLISHED only) SSH connection response (for the corresponding incoming SSH connection request).
iptables -A INPUT -i eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
In the above example:
iptables -A INPUT: Append the new rule to the INPUT chain. Since this is for the response rule (for the corresponding outgoing request) that comes from the outside to the server, this should be INPUT.
-i eth0: This refers the input interface. For incoming connections, this always has to be ‘-i’.
-p tcp: Indicates that this is for TCP protocol.
–sport 22: This refers to the source port for the incoming connection. Since the outgoing request (from the previous rule) went to the “destination” port, the incoming response will come from the “source” port.
-m state: This indicates that the “state” matching module is used.
–state ESTABLISHED: Since this is a response rule, we allow only ESTABLISHED connection (and not any NEW connection).
Putting it all together
Create rules.sh shell script which does the following:
Delete all existing rules
Set default chain policies
Allow inbound SSH
Allow inbound HTTP
Allow outbound SSH
First, create the rules.sh
$ vi rules.sh # 1. Delete all existing rules iptables -F # 2. Set default chain policies iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT DROP # 3. Allow incoming SSH iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT # 4. Allow incoming HTTP iptables -A INPUT -i eth0 -p tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A OUTPUT -o eth0 -p tcp --sport 80 -m state --state ESTABLISHED -j ACCEPT # 5. Allow outgoing SSH iptables -A OUTPUT -o eth0 -p tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT iptables -A INPUT -i eth0 -p tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
Next, execute the rules.sh and view the rules.
# chmod u+x rules.sh
# ./rules.sh
# iptables -L