netfilter and iptables
In this laboratory, we will explore the security implications of network connected devices and how to protect them from external attacks.
You have a NanoPi device with a buildroot Linux system installed that we will modify to have the relevant tools installed. That is: netfilter and iptables.
Preparation tasks
The goal of this part of the lab is to setup your NanoPi with a newly modified configuration to that you can make use of the said tools.
For this you will need to:
-
Ensure the target has the appropriate
iptablesactivated in the mainbuildrootmenuconfig-
Start the
buildrootmenumake menuconfig -
Pick all the
libnetfiltersTarget packages -> Libraries -> Networking -> Activate libnetfilter…
-
Activate
iptablesTarget packages -> Networking applications -> iptables
-
-
Modify the
kernelconfiguration so as to enablenetfilterat Core and IP levels.-
Start the
linuxmenu and navigate toNetworking support -> Networking options -> Network packet filtering framework (Netfilter)make linux-menuconfig
-
Core
Networking support -> Networking options -> Network packet filtering framework (Netfilter) -> Core Netfilter Configuration -> SELECT ALL
-
IP
Networking support -> Networking options -> Network packet filtering framework (Netfilter) -> IP: Netfilter Configuration -> SELECT ALL
Important
In our case, we will activated all of them!. So, make sure to activate them all so as to avoid wondering why on Earth something is not working.
-
Make sure your setup works
- After having started the board, making sure it is connected to a pc, check the configuration
ip a - Ping your pc with (here it is assumed you have configured your pc with the address
192.68.0.1)ping 192.168.0.1 - Stop pinging and add the command below. Does the
pingstill work? How can you list the rules that are presently available?iptables -A OUTPUT -d 192.168.0.1 -j DROP
Success
If your pings did not go through any longer, you made it and are ready for the next step!!! Well done!!!
Just make sure you remove the rule with iptables -D OUTPUT -d 192.168.0.1 -j DROP
Warning
Make sure you add your ses_deconfig to your repository with an appropriate tag.
Understanding the commands
The general syntax is
iptables -t table -COMMAND chain … -j TARGET
-t table:
table=FILTER, MANGLE, NAT, … // FILTER is the default table
-COMMAND chain:
COMMAND: A=append, I=insert, D=delete, C=check, R=replace, L=list, F=flush, P=policy, ..
Chain: INPUT, OUTPUT, FORWARD
-j TARGET:
TARGET: ACCEPT, DROP, REJECT, NFQUEUE
For a complete list of TARGETs, have a look at
“iptables-cheatsheet.md - (courtesy of GH user mcastelino)”.
Hint
No matter what is stated here, do remember that man iptables is your friend! Do remember 3 important things:
man iptablesis not available on your target- Even though ChatGPT/Gemini/… may be (at times) helpful, they are not always available (Cloudflare outage, no Internet connection, …)
- Most important: you shall always know what you do because you may be opening up a huge security hole if
iptablesis misconfigured! So, be attentive!
Here a synthesis
-
List all existing rules in the filter table:
iptables -L -n -v -t filter //-n without reverse DNS, v=verbose, vv=more verbose or iptables -L -n -v // Filter is the default table iptables -S -
Flush tables
oriptables -F -t filteriptables –F -
Create a new chain
iptables –N dynamic -
Append (
-A) a new ruleiptables -A INPUT -s 200.200.200.1 -j DROP // everything coming from 200.200.200.1 -
Delete (
-D) a ruleoriptables -D INPUT -s 200.200.200.1 -j DROPiptables –D INPUT 1 // Delete the 1st entry
A few examples
Stateless Firewalls
-
Log and drop all
icmp(such as ping) packets (log in the file/var/log/messages)iptables -A INPUT -p icmp -j LOG iptables -A INPUT -p icmp -j DROP -
Accept the ssh service form host 10.0.0.1
iptables -A INPUT -p tcp -s 10.0.0.1 -d 0/0 --dport 22 -j ACCEPT -
Accept the ssh service form the subnet 10.0.0.x
iptables -A INPUT -p tcp -s 10.0.0.0/24 -d 0/0 --dport 22 -j ACCEPT -
Reject all incoming TCP traffic destined for ports 0 to 1023
iptables -A INPUT -p tcp -s 0/0 -d 0/0 --dport 0:1023 -j REJECT -
Reject all outgoing TCP traffic except the one destined for 10.0.0.1
iptables -A OUTPUT -p tcp -s 0/0 -d ! 10.0.0.1 -j REJECT -
Drop all SYN packets from 10.0.0.1
iptables -A INPUT -p tcp -s 10.0.0.1 -d 0/0 --syn -j DROP -
Change the FORWARD chain to an ACCEPT policy (default rule)
iptables -P FORWARD ACCEPTNote
Default policies set with -P are only applied if no rule in the chain matches. If a packet matches a rule earlier in the chain, that rule’s target is used instead of the default policy.
-
Block a incoming telnet only for the port ppp0
iptables -A INPUT -p tcp --destination-port telnet -i ppp0 -j DROP
Stateful Firewalls
iptables can use extended packet matching modules with the -m or --match
options, followed by the matching module name. Check
https://ipset.netfilter.org/iptables-extensions.man.html for a full list of modules that can be used.
-
Basic Stateful Firewall example uses the extended packet matching
conntrackiptables -F //Flush the table FILTER iptables -A OUTPUT -m conntrack --ctstate NEW,ESTABLISHED,RELATED -j ACCEPT iptables -A OUTPUT -j DROP // drop other packet iptables -A INPUT -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -j LOG iptables -A INPUT -j DROP // drop other packetInfo
Note that
iptables -A INPUT -j LOGmeans that logging happens only for packets that are notESTABLISHEDorRELATED. -
Obviously, the examples from above can be used as well.
Let’s go a bit further - a few questions to you
The following questions shall be realized on the target you hold in your hands.
Question
Warning
Before answering, make sure you add your ses_deconfig to your
repository with an appropriate tag.
-
Configure your NanoPI so that all incoming
ICMPare- logged
- dropped
Make sure you write down the commands used for executing the above.
-
Configure your NanoPI so that all incoming ‘ICMP’ messages are
- logged
- rejected
What commands did you use? What difference(s) have you observed compared to the previous configuration?
-
How can you check what services are presently activated on your NanoPI?
Hint
Check what the
netstatcommand is capable of doing. Eventually, also have a look atwatchfor continuous monitoring. -
Assuming the following situation
---- eth0 -------- | PC | ---------------->| NanoPI | ---- -------- 192.168.0.1 192.168.0.14Configure you NanoPI so that
- all new incoming
sshconnections are accepted (from PC to NanoPI) - all local connections are accepted (local means using the loopback interface
lo0) - all other communication (be that
FORWARD,OUTPUTorINPUT) is dropped
- all new incoming
-
Assuming the following situation
---- eth0 -------- | PC | ---------------->| NanoPI | ---- -------- 192.168.0.1 192.168.0.14Configure you NanoPI so that
- all new incoming and outgoing
sshconnections are accepted (from NanoPI standpoint) - all local connections are accepted (local means using the loopback interface
lo0) - all other communication (be that
FORWARD,OUTPUTorINPUT) is dropped
- all new incoming and outgoing
-
Given the following configuration
iptables –A INPUT -i lo –j ACCEPT // Local traffics are allowed between applications iptables –P INPUT DROP iptables –P OUTPUT ACCEPT iptables –P FORWARD DROP iptables -N dynamic iptables -N net2fw // New chain: Network to Firewall iptables -A INPUT -i eth0 -j net2fw iptables -A net2fw -m conntrack --ctstate NEW -j dynamic iptables -A net2fw -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT iptables -A net2fw -p tcp -m tcp --dport 62200 -j ACCEPT iptables -A net2fw -j LOG --log-prefix "net2fw:DROP:" --log-level 6 iptables -A net2fw -j DROPCan you
- explain what rules are triggered when a connection to port 62200 is attempted?
- rewrite it in a “safer” manner? (that is, more structured and less error prone)
-
Can you find how many hooks there are, and in what files, in the kernel version your NanoPI is running? Find “only” the IPv4 ones.
Hint
Check the occurrences of the hook in
output/build/linux-6.3.6/net/ipv4.
Let’s programme! Making use of NFQUEUE target
You are now about to implement a small programme that makes use of NFQUEUE
capabilities to explore what one can do with it.
To do so
-
Take the following code and save it in a
.cfile (saytest.c):#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <netinet/in.h> #include <linux/types.h> #include <linux/netfilter.h> /* for NF_ACCEPT */ #include <libnetfilter_queue/libnetfilter_queue.h> static uint32_t print_pkt(struct nfq_data *tb); static int callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data); int main(int argc, char **argv) { struct nfq_handle *h; struct nfq_q_handle *qh; int fd, rv; char buf[4096] __attribute__ ((aligned(4))); h = nfq_open(); //opening library handle nfq_unbind_pf(h, AF_INET); //unbinding existing nf_queue handler for AF_INET nfq_bind_pf(h, AF_INET); // binding nfnetlink_queue as nf_queue handler for AF_INET qh = nfq_create_queue(h, 0, &callback, NULL); // binding this socket to queue '0' nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff); // setting copy_packet mode fd = nfq_fd(h); while ((rv = recv(fd, buf, sizeof(buf), 0)) && rv >= 0) { printf("pkt received\n"); nfq_handle_packet(h, buf, rv); } nfq_destroy_queue(qh); nfq_close(h); exit(0); } static u_int32_t print_pkt (struct nfq_data *tb) { int id = 0; struct nfqnl_msg_packet_hdr *ph; ph = nfq_get_msg_packet_hdr(tb); if (ph) { id = ntohl(ph->packet_id); printf("hw_protocol=0x%04x hook=%u id=%u \n ",ntohs(ph->hw_protocol), ph->hook, id); } return id; } static int callback(struct nfq_q_handle *qh, struct nfgenmsg *nfmsg, struct nfq_data *nfa, void *data) { u_int32_t id = print_pkt(nfa); printf("entering callback\n"); return nfq_set_verdict(qh, id, NF_ACCEPT, 0, NULL); } -
Once you are ready with your file, you can compile it to generate the
nfq-icmpprogramme using the toolchain you created../output/host/bin/aarch64-buildroot-linux-gnu-gcc -Wall -o nfq-icmp test.c -Ioutput/host/aarch64-buildroot-linux-gnu/sysroot/usr/include -Loutput/host/aarch64-buildroot-linux-gnu/sysroot/usr/lib -lnetfilter_queueWarning
Note: you may have called the
cfile differently - it is calledtest.cabove - and shall make sure it aligns with your version.Info
Thanks to
-IandLwe pass explicit include/lib paths. -
Download it to your target (e.g. using
scp) and run it. Do remember to instantiate the corresponding queue prior to answering the questions below.
Question
Transfer the programme to the NanoPI target and write down
- what commands you used to transfer the file and launch it
- what results you observed when issuing
ping 192.168.0.14from your pc (assuming you have not changed the IP address of your NanoPI) - what would you need to do in case you wanted, after having printed the
packet content,
DROPall packets? What would be the effect on the recipient of theICMPresponse?
Hint
Do not forget to create the NFQUEUE prior to launching the programme.
INTERESTING USE
For those who would like to understand how iptables can be used in a way
larger scale to defend against massive attacks, have a look at Cloudflare’s
presentation titled Defending from DDoS Attacks - youtube.com.