The next on my “RHCE” merry-go-round is iptables – a fairly understandable component on the face of it, but a bit of a pain in the *** if you get it wrong as it can make your life a misery.

What is iptables?

Iptables is a stateless firewall (unless using a specific module), and allows users to analyse packets and decide what to do with them based upon a series of ‘rules’. (Thats a very simplistic view, but this isnt really a ‘how does iptables work?’, more of a ‘How can i make it work’ blog).

Iptables is mainly used to prevent access to linux/unix systems by certain networks or servers, or to allow only certain servers/networks access to certain ports and protocols.

For example, you may have an internal web server, you want to allow only internal users access to, and only allow them ‘access’ to Port 8080 which is the web server port in apache on it. This prevent people SSH’ing into the server, or poking around etc.

Commands

To view iptables rules on your system, as root / sudo run “iptables -L” for a basic view, or “iptables -nL –line-numbers” for a more advanced view, with line numbers, as below:

[root@Server1 ec2-user]# iptables -nL --line-numbers
Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
2 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
3 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0
4 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
5 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
6 DROP all -- 0.0.0.0/0 0.0.0.0/0
Chain FORWARD (policy ACCEPT)
num target prot opt source destination
1 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT)
num target prot opt source destination

We can see above we have a few sample rules, including all SSH (line 5) to all network devices, or allow HTTP to all users (line 1).

To insert these rules, we run a command similar to below:

iptables -A INPUT -s 192.168.0.0/24 -p tcp –dport 1022 -j ACCEPT

This says, “allow anyone on the 192.168.0.0/24 range, access to my box, if they are connecting via TCP port 1022”. *IMPORTANT NOTE*: The -A is important – this means we are APPENDING a rule – i.e. we are adding a new rule at line number 7, with the information we provided above.

Why do i stress this? Well – take a look at line 6 – DROP ALL. Iptables will work from top down until it finds a rule match, so if you add your “allow” rule after a “drop/reject” rule, then the new rule will never be ‘hit’.

There are 2 ways around this. 1) We can delete the DROP ALL rule, and re-append that after our changes:

iptables -D INPUT 6
iptables -A INPUT -j REJECT

Then if we do an “iptables -nL –line-numbers” again, we can see the rules are in the ‘correct’ order:

Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
2 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
3 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0
4 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
5 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
6 ACCEPT tcp -- 192.168.0.0/24 0.0.0.0/0 tcp dpt:1022
7 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable

One of the other things we can do, is use “-I” which inserts the new rule at the top of the stack (we’ll bump #1 to #2, and add a new rules at #1 that allows localhost access to port 8080, for example):

Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT tcp -- 192.168.0.0/24 0.0.0.0/0 tcp dpt:8080
2 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
3 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
4 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0
5 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
6 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
7 ACCEPT tcp -- 192.168.0.0/24 0.0.0.0/0 tcp dpt:1022
8 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable

Here we can see our new rule at #1 – this means that we dont have the REJECT ALL issue. There are other things we can do – such as insert at a specific point in the iptables chain:

iptables -I INPUT 4 -s 192.168.0.0/24 -p tcp --dport 9090 -j ACCEPT

The above command will add the rule for port 9090, to line 4:

Chain INPUT (policy ACCEPT)
num target prot opt source destination
1 ACCEPT tcp -- 192.168.0.0/24 0.0.0.0/0 tcp dpt:8080
2 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
3 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
4 ACCEPT tcp -- 192.168.0.0/24 0.0.0.0/0 tcp dpt:9090
5 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0
6 ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
7 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
8 ACCEPT tcp -- 192.168.0.0/24 0.0.0.0/0 tcp dpt:1022
9 REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable

Here we can see the we’ve added our iptables rule at 4, and bumped the others down – again avoiding any “REJECT” issues.

Closing thoughts

Without getting into too much detail (Setting up NAT with iptables (dont forward ipv4.forward in sysctl!)), that is a brief example of iptables.

Remember, for your RHCE to do 2 things with each question

1. Does it need iptables configuring? (Often yes). Make sure you restrict access to only those who need it, and remember to make your changes persistent! ‘service iptables save’ will save the rules so they survive a reboot.

2. Test and make sure the packets get through if at all possible – from a desktop machine, etc. “iptables -nL –line-numbers” will make your life a lot easier, than the standard “-L”.

Bon chance`!