A firewall filters network traffic, which is transmitted in packets.
The network packet filter is configured with rules.
The basics of these filter rules are explained here.
On Debian, iptables-restore
is called on boot by installing the following package:
apt install iptables-persistent
We set the default policy of the INPUT
chain to DROP
and
specify some rules, which are applied from top to bottom:
lo
are accepted.ESTABLISHED
connections or RELATED
packets are accepted.ping
requests) is allowed./etc/iptables/rules.v4
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 8 --rttl --name SSH -j DROP
-A INPUT -p tcp --dport 22 -j ACCEPT
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT
COMMIT
Load the IPv4 rules from file:
iptables-restore < /etc/iptables/rules.v4
Verify the loaded IPv4 rules:
iptables -L
The PREROUTING
chain is used for port forwarding.
The rule in the POSTROUTING
chain translates the source address of outgoing packets.
The reply will be forwarded by translating the destination address of incoming packets.
This is what ordinary IPv4 routers do.
Rules for the nat
table are part of the iptables rules:
/etc/iptables/rules.v4
*filter
#...
COMMIT
*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A PREROUTING -p tcp --dport 80 -j DNAT --to-destination 192.168.0.100:80
-A POSTROUTING -s 192.168.0.0/255.255.255.0 -o ppp0 -j MASQUERADE
COMMIT
Forwarding of IPv4 packets needs to be enabled in the kernel.
An interface for modifying kernel parameters is the proc file system.
echo 1 > /proc/sys/net/ipv4/ip_forward
A simplified command line tool for the proc file system is sysctl
.
To make the change persistent over reboots, edit the following file:
/etc/sysctl.conf
#...
# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1
#...
For IPv6, the following rules need to be added:
/etc/iptables/rules.v6
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
-A INPUT -p icmpv6 -j ACCEPT
-A INPUT -p udp -s fe80::/10 --dport 546 -j ACCEPT
-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
-A INPUT -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 8 --rttl --name SSH -j DROP
-A INPUT -p tcp --dport 22 -j ACCEPT
-A INPUT -p tcp --dport 80 -j ACCEPT
-A INPUT -p tcp --dport 443 -j ACCEPT
COMMIT
Load the IPv6 rules from file:
ip6tables-restore < /etc/iptables/rules.v6
Verify the loaded IPv6 rules:
ip6tables -L
nftables is the successor of {ip,ip6,arp,eb}tables.
There is only one ruleset needed to cover IPv4 and IPv6.
The table ip
contains chains with rules for IPv4.
The contained chain input
filters incoming packets.
All accepted IPv4 packets are marked with 0x34414343
("4ACC"):
The table ip6
contains chains with rules for IPv6.
The contained chain input
filters incoming packets.
All accepted IPv6 packets are marked with 0x36414343
("6ACC"):
The table inet
contains chains with rules for IPv4 and IPv6.
The contained chain input
accepts the following incoming packets:
0x34414343
(from table ip
) are accepted.0x36414343
(from table ip6
) are accepted./etc/nftables.conf
#!/usr/sbin/nft -f
flush ruleset
table ip filter {
set ipv4_ssh_meter {
type ipv4_addr
flags dynamic,timeout
timeout 10m
}
chain input {
type filter hook input priority -10;
meta l4proto icmp counter meta mark set 0x34414343 accept
tcp dport 22 ct state new update @ipv4_ssh_meter { ip saddr limit rate 12/minute } counter meta mark set 0x34414343 accept
}
}
table ip6 filter {
set ipv6_ssh_meter {
type ipv6_addr
flags dynamic,timeout
timeout 10m
}
chain input {
type filter hook input priority -10;
meta l4proto ipv6-icmp counter meta mark set 0x36414343 accept
ip6 saddr fe80::/10 udp dport 546 counter meta mark set 0x36414343 accept
tcp dport 22 ct state new update @ipv6_ssh_meter { ip6 saddr limit rate 12/minute } counter meta mark set 0x36414343 accept
}
}
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
iifname "lo" counter accept
ct state established,related counter accept
meta mark 0x34414343 counter accept
meta mark 0x36414343 counter accept
tcp dport 80 counter accept
tcp dport 443 counter accept
}
}
Load the ruleset from file:
nft -f /etc/nftables.conf
Verify the loaded ruleset:
nft list ruleset
systemctl enable nftables.service