Adventures in Rolling Your Own Router: Part V
In my previous post, I set up NAT using
nftables
. In this post, I’ll use nftables
to set up a firewall.
In my current router, I have disabled IPv6 entirely, so no IPv6 packets can enter or leave my network. I do want to start experimenting with IPv6, so I will not want to take this strategy for the new firewall.
Looking again at the netfilter
diagram, we can see we are mostly interested
in the forward
and input
chains of the filter
table. The former will
allow us to filter packets destined for the LAN, and the latter packets
destined for the router itself.
Instead of building the rules using the nft
CLI, we can just modify
/etc/nftables.conf
. I’ve added comments in the file to explain what each
rule is for.
jmp@debrouter:~$ cat /etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
table ip filter {
# applies to packets which are traveling through this machine
chain forward {
type filter hook forward priority 0; policy drop;
# allow packets leaving the network
oifname extern0 accept
# allow replies
iifname extern0 ct state related,established accept
}
chain input {
type filter hook input priority 0; policy drop;
# drop invalid packets early
ct state invalid drop
# accept replies
ct state related,established accept
# open loopback interface
iif lo accept
# accept ICMP and IGMP
ip protocol icmp accept
ip protocol igmp accept
# allow SSH from all interfaces
tcp dport ssh accept
# allow Mosh from all interfaces
udp dport { 60000-61000 } accept
# allow DNS queries from the LAN
iifname intern0 tcp dport 53 accept
iifname intern0 udp dport 53 accept
# allow traceroute
udp dport { 33434-33524 } accept
}
}
table ip6 filter {
chain forward {
type filter hook forward priority 0; policy drop;
# for now, we will not forward IPv6 traffic.
}
chain input {
type filter hook forward priority 0; policy drop;
# drop invalid packets early
ct state invalid drop
# accept replies
ct state related,established accept
# accept ICMPv6
ip6 nexthdr icmpv6 accept
}
}
table ip nat {
chain postrouting {
type nat hook postrouting priority 100; policy accept;
# perform NAT for packets coming from the LAN and going to the Internet
ip saddr 192.168.77.0/24 oifname extern0 masquerade
}
}
Now, I can mosh
to and ping6
the router from the external interface:
jmp@archimedes ~ % mosh 192.168.10.17
[email protected]'s password:
jmp@archimedes ~ % ping6 -I en0 fe80::5054:ff:fec7:caa6
PING6(56=40+8+8 bytes) fe80::874:cee0:e328:8115%en0 --> fe80::5054:ff:fec7:caa6
16 bytes from fe80::5054:ff:fec7:caa6%en0, icmp_seq=0 hlim=64 time=0.820 ms
16 bytes from fe80::5054:ff:fec7:caa6%en0, icmp_seq=1 hlim=64 time=0.504 ms
16 bytes from fe80::5054:ff:fec7:caa6%en0, icmp_seq=2 hlim=64 time=0.544 ms
16 bytes from fe80::5054:ff:fec7:caa6%en0, icmp_seq=3 hlim=64 time=0.442 ms
In the next post, I’ll install PiHole for DNS and DHCP service.