1
Netfilter
Lab handout
0. Introduction
This work requires several changes to the configuration of the host used as server. In order to ensure the
host safety during the working period, only connections to trusted networks or virtual machines hosted by
trusted operating systems should be used.
To allow restoring the firewall configuration after work, save a copy of actual iptables configuration:
iptables-save > iptables.dump
Since all the implemented changes will be temporary, it is possible to safely abort the work at any time by
rebooting the involved machines or by issuing the command:
iptables-restore < iptables.dump
Register the names and the IP addresses of machines allocated to be used as server and clients. Only the
server will have its configuration changed. Clients will only be used for testing proposes.
Host Name IP Address
Server
Client1
Client2
Client3
Client4
2
To allow different connection tests, the server host must provide HTTP and SSH services on the traditional
TCP ports (80 and 22).
Verify the availability of the provided HTTP and SSH services from each of the clients.
ping ip_server
wget http://ip_server/
ssh ip_server -l my_test_user
Register the obtained results on the following table.
Client ICMP HTTP SSH
Client1
Client2
Client3
Client4
1. Netfilter / iptables
Netfilter is a framework to implement packet filtering and address and port translations. It is commonly
integrated in the Linux kernel. The configuration of netfilter can be done from the command line using the
iptables utility. Any specific behavior can be implemented by defining chains of rules. Chains are located
into tables. In this work, only the filter table will be used.
Basic iptables operation:
iptables -L Lists all rules in chains
iptables -F Flushes (cleans) all chains
iptables -X Deletes all chains iptables -A chain rule Adds a new rule to a chain
iptables -D chain rule Deletes a rule
iptables -P chain DROP|ACCEPT Sets the policy (DROP/ACCEPT) for the chain
2. Simple Rule
On your server, clear the netfilter state.
iptables -F
iptables -X
Block all incoming traffic:
iptables -P INPUT DROP
3
Test the communication to your loopback interface.
ping -c 1 127.0.0.1
Create new rules in the INPUT chain to allow all traffic from the localhost.
iptables -A INPUT -s 127.0.0.0/8 -j ACCEPT
iptables -A INPUT -s ip_server -j ACCEPT
Verify that these new rules are now part of the INPUT chain.
iptables -L -v -n
Test again the communication to your loopback interface.
ping -c 1 127.0.0.1
Allow all the ICMP traffic, no matter its origin.
iptables -A INPUT -p icmp -j ACCEPT
Test the communication from each client to your server.
ping -c 1 ip_server
Allow clients 1 and 2 to access the SSH service in the server.
iptables -A INPUT -p tcp -m tcp -s ip_client1 --dport 22 -j ACCEPT
iptables -A INPUT -p tcp -m tcp -s ip_client2 --dport 22 -j ACCEPT
Allow clients 1 and 3 to access the HTTP service in the server.
iptables -A INPUT -p tcp -m tcp -s ip_client1 --dport 80 -j ACCEPT
iptables -A INPUT -p tcp -m tcp -s ip_client3 --dport 80 -j ACCEPT
Confirm the accessibility to the HTTP and SSH services in the server from each client. Register the results in
the following table.
Client ICMP HTTP SSH
Client1
Client2 Client3
Client4
This example applied a distinct rule for every combination of origin host and destination port. The use of
such rules to give access to p services from n hosts requires specifying a set of n x p rules.
4
3. Additional chains The total amount of rules may be reduced if it is possible to group a set of rules so they can be frequently
re-used. When two services (on different ports) should be available to a limited but identical list of IP
addresses, an additional chain can be used to enclose the IP address test. First, the packet is checked for
the destination port. If it matches, it is sent to the new chain, where a list of IP addresses is checked.
Delete all rules and all extra chains:
iptables -F ; iptables -X
Create new chain named admin_IP, that will be used to check the source IP address.
iptables -N admin_IP
iptables -L
Add rules to chain admin_IP to accept packets originated from the trusted IPs and reject all other traffic.
iptables -A admin_IP -s ip_client1 -j ACCEPT
iptables -A admin_IP -s ip_client2 -j ACCEPT
iptables -A admin_IP -s ip_client3 -j ACCEPT
// drop all packets that are not matched by previous rules
iptables -A admin_IP -j DROP
Add rules to the INPUT chain in order to implement the desired port filter. Packets directed to the accepted
destination ports will be redirected to the admin_IP chain.
iptables -A INPUT -p tcp -m tcp --dport 22 -j admin_IP
iptables -A INPUT -p tcp -m tcp --dport 80 -j admin_IP
Verify that the protection system is working as required. Register the obtained results in the following
table.
Client ICMP HTTP SSH
Client1 Client2
Client3
Client4
4. State Most processing of rules can be avoided with the use of state. Traffic related to previously established
connections can be summarily accepted in one of the first rules.
5
Delete all existent rules and chains.
iptables -F ; iptables -X
iptables -L -n
Allow all traffic incoming related to already established connections
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
Allow incoming traffic on the default SSH port (22) and the default HTTP port (80).
iptables -A INPUT -p tcp --dport ssh -m state --state NEW -j ACCEPT
iptables -A INPUT -p tcp --dport 80 -m state --state NEW -j ACCEPT
iptables -L -n
Block all other incoming traffic:
iptables -P INPUT DROP
iptables -L -n -v
This setup blocks all traffic that has not been explicitly allowed. So, the traffic to the loopback interface is
also blocked. To allow the traffic to the loopback (lo) interface, insert a new rule in top of the chain.
iptables -I INPUT 2 -i lo -j ACCEPT
iptables -L -v -n
To further allow incoming traffic directed to other services, new rules can be created.
iptables -A INPUT -p tcp --dport xxxx -j ACCEPT
iptables -L -v -n
Verify that the protection system is working as required. Register the obtained results in the following
table.
Client ICMP HTTP SSH
Client1
Client2
Client3
Client4
5. Port knocking Port knocking is a stealth method to externally open ports that, by default, the firewall keeps closed. It
works by requiring connection attempts to a series of predefined closed ports. When the correct sequence
of port "knocks" (connection attempts) is received, the firewall opens certain port(s) to allow a connection.
The benefit is that, for a regular port scan, it may appear as the service of the port is just not available.
6
This exercise will show how to implement the port knocking mechanism with iptables.
The goal is to create a port knocking system only with iptables that will open up port 22 (SSH) when the
remote host “knocks” on ports 2222, 3333, 4444 within 30 seconds, without sending non-sequence traffic
in between.
Four different states will be defined to classify hosts trying to access.
• Initial state: This is the state that all IP addresses are in until they successfully send a packet to the
first knock target.
• Auth1 state: Addresses that have successfully knocked on the first knock target are flagged as
Auth1.
• Auth2 state: Addresses are flagged with this state if they have successfully knocked on the first and
second targets in sequence. The next packet from the same host determines whether the host will
be set back to the initial state or set to the Auth3 state.
• Auth3 state: Addresses that have been flagged as Auth3 have successfully knocked on all three
ports, in order, in the allotted amount of time. If an address flagged as Auth3 attempts to access
the service now (in window that is provided), the connection will be accepted. If any other traffic is
received, the address will be thrown back to the initial state.
States Auth1, Auth2 and Auth3 will be recorded by flags with the same name (AUTH1, AUTH2 and AUTH3).
The initial state will be signaled by unsetting all these three flags.
5.1. Chains framework Before starting to build the knocking system, flush the existing firewall rules to get a clean state.
iptables -F ; iptables -X
Required additional chains can be created using:
iptables -N KNOCKING
iptables -N GATE1
iptables -N GATE2
iptables -N GATE3
iptables -N PASSED
iptables -L -n
Eight different chains should be listed!
• KNOCKING: This chain will distribute traffic to other sub-chains according to current state.
• GATE1: Will be used to determine whether an address in the initial state should be flagged as
Auth1.
7
• GATE2: Will be used to determine whether an address in the Auth1 state should be processed to
Auth2 or reset to the initial state.
• GATE3: Will be used to determine whether an address in the Auth2 state should be flagged as
Auth3 to allow an SSH connection or reset to the Initial state.
• PASSED: This chain will be used to briefly open the port for the SSH daemon for clients that have
knocked successfully. Any traffic from clients in this chain that is not destined for the SSH daemon
is dropped and the state is reset to Initial.
5.2. Input chain The knocking mechanism will be used only to control the creation of new external connections to the SSH
service. All traffic belonging to any already established connection will be immediately accepted as usual:
iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
Connections from the local machine will also be accepted:
iptables -A INPUT -i lo -j ACCEPT
Services that should remain externally and publicly accessible, like a Web server, can be configured now.
Allow all traffic directed to a Web server running on the default port 80:
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
All traffic that was not handled in the above rules is directed to the KNOCKING chain to implement the
actual knocking logic:
iptables -A INPUT -j KNOCKING
Verify that the server keeps its services available as usually.
5.3. Knocking Chain All incoming traffic not yet accepted will redirect into the chain called KNOCKING, presented on next
figure. In this chain, the packet will be directed to a specific test chain, depending on the sender state.
Packets from hosts in the Initial state will be handled by the GATE1 chain where they will be tested for the
first knocking target.
Packets from hosts in the Auth1 state will be directed to the GATE2 chain to test the second knocking
target.
Packets from hosts in the Auth2 state will be directed to the GATE3 chain to test the third knocking target.
Packets from hosts in the Auth3 state will be directed to the PASSED chain where the access to the port 22
can be accepted.
8
The general KNOCKING chain will pass traffic from clients that have successfully completed all the knocks
directly into the PASSED chain. This gate will be open only for the first packet from the successful client and
only for a 30 second window. After that, the rule will no longer match successfully.
iptables -A KNOCKING -m recent --rcheck --seconds 30 --name AUTH3 -j PASSED
While being in the AUTH2 state, traffic will be processed by the GATE3 chain. A 10 second time limit is
imposed before the previous knock expires.
iptables -A KNOCKING -m recent --rcheck --seconds 10 --name AUTH2 -j GATE3
While being in the Auth1 state, traffic will be processed by the GATE2 chain. A 10 second time limit is
imposed before the previous knock expires.
iptables -A KNOCKING -m recent --rcheck --seconds 10 --name AUTH1 -j GATE2
This will require clients to complete each next stage of the knocking within 10 seconds, and then connect
to the SSH daemon in another 30 seconds
All traffic that has not matched so far is sent back to GATE1, as usual. This will catch any attempt for the
first knock:
9
iptables -A KNOCKING -j GATE1
Verify that the server keeps its services available as usually.
5.4. GATE1 Chain
The KNOCKING chain will call this gate only if none of AUTH1, AUTH2 or AUTH3 flags is set.
When a client connects, this gate will see if it is sending a packet to our first knocking target. If it is, the
client will be flagged in state Auth1 and the connection is dropped.
iptables -A GATE1 -p tcp --dport 2222 -m recent --name AUTH1 --set \
-j LOG --log-prefix "Enter Auth1 "
This rule will match when the protocol being used is TCP and when the port it is trying to access is "2222",
the first knock target. If it matches, the recent module (called with -m recent) flags the requesting IP
address with the name AUTH1 (with the "--name AUTH1 –set" rule). This is the flag used to register the
successfully first knock. A logging target is added to allow further analysis of the gate behavior. The packet
is dropped after the flag is set, so that the client does not know if anything happened.
If it not a valid first knock, the connection is simply dropped.
iptables -A GATE1 -j DROP
Every kind of traffic in the KNOCKING sub-chains should be dropped (except the traffic for the SSH daemon
from successful knock clients), regardless of whether it matched the correct port. This is necessary for the
port knocking implementation to be valid. Persons attempting to connect should receive no feedback as to
what stage of the process they are in or even if such a mechanism is in place.
Confirm the produced implementation of the chains INPUT, KNOCKING and GATE1.
10
iptables -L -n
Test the implemented gate by issuing TCP requests to port 2222.
nping -tcp-connect -p 2222 ip_server
Observe the produced output in the system log.
dmesg -w
5.5. GATE2 Chain The second gate is configured in much the same way as the first. It is slightly more complex though.
The KNOCKING chain will call this second gate chain only if the AUTH1 flag is already set. This chain will
clear the AUTH1 flag and will set the AUTH2 flag if the port 3333 is being addressed.
The recent module will be used again, this time just to clear the named flag:
iptables -A GATE2 -m recent --name AUTH1 --remove
This is a processing rule, so it does not include any decisions or jumps. Execution continues in the second
rule.
Now the origin address is in a clean state with no flags set. At this point, the connection attempt is tested
for a correct match with next port target:
iptables -A GATE2 -p tcp --dport 3333 -m recent --name AUTH2 --set -j DROP
11
This is handled in much the same way as the first gate. If the correct port was knocked on, the AUTH2 flag
is set, indicating that the requesting address passed the second test. The packet is again dropped, giving
the client no indication of their progress.
Traffic that does not fit in this rule is not a valid second knock, but it can be a valid first knock. So, it will be
sent to GATE1 in order to provide its evaluation.
iptables -A GATE2 -j GATE1
To allow further debugging of the knocking system, some logging rules can be added to this chain.
iptables -I GATE2 3 -j LOG --log-prefix "State Auth0 "
iptables -I GATE2 1 -j LOG --log-prefix "Gate 2 "
Confirm the produced implementation of the chain GATE2. Test the implemented gates by issuing TCP
requests to ports 2222 and 3333 and analyzing the output in the system log.
5.6. GATE3 Chain The second gate can be used as an example to implement the third gate.
First, the AUTH2 flag that have been given to the requesting address is cleared.
iptables -A GATE3 -m recent --name AUTH2 --remove
Next, the third knock target is tested. If it matches, the AUTH3 flag is set, which indicates that the client
successfully completed all required knocks. As usual, the packet if dropped afterwards.
iptables -A GATE3 -p tcp --dport 4444 -m recent --name AUTH3 --set -j DROP
12
The traffic that did not match the third knock target is sent back to the first gate to see if it should count as
a successful first knock to restart the sequence:
iptables -A GATE3 -j GATE1
At this point, clients who've completed the correct knocking sequence should be flagged with AUTH3,
which will allow opening the service for them in the PASSED chain.
To allow further debugging of the knocking system, some logging rules can be added to this chain.
iptables -I GATE3 3 -j LOG --log-prefix "State Auth0 "
iptables -I GATE3 1 -j LOG --log-prefix "Gate 3 "
Confirm the produced implementation of the chains INPUT, KNOCKING, GATE1 and GATE2. Test the
implemented gates by issuing TCP requests to ports 2222 and 3333 and analyzing the system log.
5.7. PASSED Chain This chain is executed if a correct knocking sequence was previously detected. Here, the requested service
and the requester identification can be tested.
First, the usual flag reset is performed:
iptables -A PASSED -m recent --name AUTH3 --remove
Next, SSH connections from the users who have made it into the knocking chain are accepted:
iptables -A PASSED -p tcp --dport 22 -j ACCEPT
All other traffic that does not match the allowed services is sent back to the first chain to see if it matches
the first port knock target:
iptables -A PASSED -j GATE1
To allow further debugging of the knocking system, some logging rules can be added to this chain.
iptables -I PASSED 3 -j LOG --log-prefix "State Auth0 "
iptables -I PASSED 1 -j LOG --log-prefix "Passed chain "
At this point, all knocking chains are ready. It's time to test it out.
5.8. Test the Port Knocking There are several utilities that can be used to generate the TCP packets required to knock this service. The
following command sequence can be used to establish an SSH session.
nping --quiet -tcp-connect -p 2222 -c 1 ip_server
nping --quiet -tcp-connect -p 3333 -c 1 ip_server
13
nping --quiet -tcp-connect -p 4444 -c 1 ip_server
ssh -l my_test_user ip_server
For an UDP port knocking configuration the hping3 command could be used:
hping3 ip_server --udp -c 1 -p 2222
hping3 ip_server --udp -c 1 -p 3333
hping3 ip_server --udp -c 1 -p 4444
ssh -l my_test_user ip_server
To verify that the protection system is working as required, try access the SSH service after several
knocking sequences. Register the obtained results in the following table.
Port Knocking Sequence SSH
2222, 3333, 4444
2222, 3333
2222, 4444, 3333 1111, 2222, 3333, 4444
2222, 3333, 4444, 5555
Store the whole netfilter database in a file named ingre-lab13.ipt
iptables-save > ingre-lab13.ipt
Send this file together with the lab work report to your Lab teacher by eMail. Use a Subject header with the
format:
INGRE:2020:LAB13:StudentNumber
6. More information An alternative to the proposed iptables implementation is to use the knockd daemon, which is a dedicated
and highly configurable port-knock server. The configuration file that it uses is considerably simpler and
more readable than the equivalent for iptables. This can be a significant advantage for large and traditional
configurations.
More information about netfilter and iptables can be found at www.netfilter.org
Versions Versão 0.1, jml, Setembro 2017
Versão 0.2, jml, 24 Novembro 2017
Versão 0.9, jml, 24 Novembro 2017
Versão 1.0, crc, jml, 12 Dezembro 2018
Versão 1.1, jml, 6 Janeiro 2021
14