Mechanics of firewall construction using iptables

In this exercise you will observe the effect of individual firewall rules created with the iptables command. A firewall is a cumulative collection of multiple rules like these. Perform this exercise on two computers on the same network.

Clearing and examining any existing firewall

On both computers, first make sure there are no firewall rules by flushing any that may exist:

iptables -F

Then list any rules, to confirm the flush:

iptables -nL

Notice that there are no rules, also notice the policies shown. Make sure the policies are all ACCEPT. If not, set them to ACCEPT:

iptables -P INPUT ACCEPT
iptables -P OUTPUT ACCEPT
iptables -P FORWARD ACCEPT


We're going to start with an open system, then make a point of stopping client3/server3. Later, we'll have a closed system and make a point of allowing client3/server3.

Prepare a test conversation to control with the firewall

We will use the client3/server3 pair of programs. client3 sends a letter of the alphabet to server3, which sends back the next letter. Let's choose a port number. Use 2345. We'll set server3 to listen on that port and client3 to talk to it. Make the 3 needed edits in client3.c and server3.c to accomplish that (server's IP in client3 program, and port number 2345 in both programs). Compile them both, on their respective machines:

gcc client3.c -o client3
gcc server3.c -o server3

Test the programs. "Test" means open 2 terminals on each machine, one for running the program and one for running tcpdump. On the tcpdump terminal of each machine, run:

tcpdump -nnti eth0 host <machine's IP> and port 2345

Then switch to the other terminal. There, on the server machine, launch server3; thereafter on the client machine run client3. The client will see the letter returned from the server. On both machines, switch to the tcpdump terminal to check the recorded packet traffic. Look closely at it to notice the addresses, ports, and data traffic directions depicted.

We're going to want an independent "second opinion" program, so that when we block client3/server3 we can see whether other things also get blocked or not. For that, just try to ping from one machine to the other.


Blocking client3/server3 with iptables

We will obstruct the client3/server3 conversation 4 different ways. The conversation consists of 2 packet journeys. First, the client request travels from client to server. Thereafter, the server response travels from server to client. (You saw this in tcpdump.) So, there are 4 ways we could interfere: 

block request from leaving client
block request from entering server
block reply from leaving server
block reply from entering client

First, let's block the request from leaving the client. On the client machine please execute:

iptables -A OUTPUT -o eth0 -p tcp --sport 1024:65535 --dport 2345 -s <client's IP> -d <server's IP> -j DROP

Examine the result:

iptables -nL

Test the programs as detailed above, including the simultaneous tcpdump runs. The conversation is blocked. Run ping. Is it blocked too?

Undo the blockage by deleting the blocking rule. Do so by executing:

iptables -D OUTPUT -o eth0 -p tcp --sport 1024:65535 --dport 2345 -s <client's IP> -d <server's IP> -j DROP

Check that the blocking rule is gone:

iptables -nL

Second, let's block the request from entering the server. On the server machine:

iptables -A INPUT -i eth0 -p tcp --sport 1024:65535 --dport 2345 -s <client's IP> -d <server's IP> -j DROP

Test. The client3/server3 conversation is blocked again. But the tcpdump story is a little different. How? What about ping-- blocked or working?

Undo the blockage:

iptables -D INPUT -i eth0 -p tcp --sport 1024:65535 --dport 2345 -s <client's IP> -d <server's IP> -j DROP

Third, let's block the reply from leaving the server

iptables -A OUTPUT -o eth0 -p tcp --sport 2345 --dport 1024:65535 -s <server's IP> -d <client's IP> -j DROP

Test. The client3/server3 conversation is blocked again. But the tcpdump story is again somewhat different than before. How? What about ping-- blocked or working?

Undo the blockage:

iptables -D OUTPUT -o eth0 -p tcp --sport 2345 --dport 1024:65535 -s <server's IP> -d <client's IP> -j DROP

Fourth, let's block the reply from entering the client:

iptables -A INPUT -i eth0 -p tcp --sport 2345 --dport 1024:65535 -s <server's IP> -d <client's IP> -j DROP

Test. And what about ping?

Undo the blockage:

iptables -D INPUT -i eth0 -p tcp --sport 2345 --dport 1024:65535 -s <server's IP> -d <client's IP> -j DROP

Doing the opposite-- pessimistic instead of optimistic approach

Now we will largely repeat the exercise. Except, instead of using an open policy and selectively blocking our test program, we'll use a closed policy and selectively allow it. Change the policies on both machines:

iptables -P INPUT DROP
iptables -P OUTPUT DROP
iptables -P FORWARD DROP

At this point they are in a state of total lock-down. None of the 4 necessary components of the client3/server3 conversation is possible. That is, the request can neither depart nor arrive, and same for the (hypothetical) reply. Fix each one of these issues and try running client3 after each command (of course server3 still runs continuously on the server machine, so if everything eventually does get through the client will display the new letter). The conversation won't fully and finally succeed until after the 4th command since each blockage individually is sufficient to stop the whole show. Here are the commands:

On client:

iptables -A OUTPUT -o eth0 -p tcp --sport 1024:65535 --dport 2345 -s <client's IP> -d <server's IP> -j ACCEPT

On server:

iptables -A INPUT -i eth0 -p tcp --sport 1024:65535 --dport 2345 -s <client's IP> -d <server's IP> -j ACCEPT
iptables -A OUTPUT -o eth0 -p tcp --sport 2345 --dport 1024:65535 -s <server's IP> -d <client's IP> -j ACCEPT

on client again:

iptables -A INPUT -i eth0 -p tcp --sport 2345 --dport 1024:65535 -s <server's IP> -d <client's IP> -j ACCEPT

After running all these, client3/server3 should work as intended.