标题: Linux使用nftables作为防火墙
时间: 2021-11-17发布,2021-11-23修改
更多nftables使用经验,参考ArchWiki:
https://wiki.archlinux.org/title/Nftables_%28%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87%29
nftables
是Linux中新的包过滤前端命令行,用于替代经典的包过滤命令行iptables
。我个人认为它比iptables
更易学易用,而且功能比iptables
更加强大。
nftables
的命令是nft
(不是全称nftables
),如果你系统里没有,可以自己安装一下nftables
软件包,比如:
sudo apt install nftables
本文介绍使用nftables
作为防火墙的方法。nftables
和iptables
一样也可以用于网络地址转换(NAT
)和策略路由,这里不做介绍。
用nftables
作为防火墙:
创建新的防火墙规则表,名叫inet
。
nft add table inet filter
把防火墙规则表inet
绑定到网络输入(input
)、转发(forward
)、输出(output
)端口。
nftables
的视角来看,这实际上是向规则表inet
中添加了三个名为input
forward
output
的规则链,并分别绑定到三个名为input
forward
output
的挂钩点(hook
)。priority
)是0
。如果有多个链,优先级数值越小的链越先执行。可以为负数。accept
(接受),也就是说,如果防火墙规则没有匹配,就放行流量。默认规则还可以是drop
(丢弃)、reject
(拒绝)。nft add chain inet filter input \{ type filter hook input priority 0 \; policy accept \; \}
nft add chain inet filter forward \{ type filter hook forward priority 0 \; policy accept \; \}
nft add chain inet filter output \{ type filter hook output priority 0 \; policy accept \; \}
允许其他设备访问本机SSH服务。
iif wlp3s0
表示流量来自网络接口wlp3s0
,它是我机器上的WiFi网卡。你的WiFi网卡名称可能不同。iif
是 input interface(输入接口),相应的“输出接口”为oif
(output interface) 。enp2s0
。不过我不用网线,所以没写它。ifconfig
或ip addr show
命令可以显示所有网络接口名称。你可以根据需要分别允许。iif wlp3s0
删掉。nft add rule inet filter input iif wlp3s0 tcp dport 22 accept
拒绝其他设备访问本机的其他服务。
ct state new
是这个规则的关键,它表示“新建连接”。在输入(input
)方向收到新连接,那肯定就是想访问本机的其他服务了,于是我们拒绝(reject
)ct
的全称是connection tracking
(连接追踪),它同时适用于TCP、UDP、ICMP等流量。所以ct state new
规则对UDP流量也能起到防护作用,不只适用于TCP。iif xxxxxx
条件,否则会有巨大的副作用,导致本机也无法访问自身的服务,并且容器类程序(docker
、安卓模拟器等)可能会无法联网。nft add rule inet filter input iif wlp3s0 ct state new reject
阻止其他设备访问本机容器内的服务。
input
(输入)方向的连接,但是防护并不完善。docker
这样的容器会添加网络地址转换(NAT)规则,把流量直接转发到容器所在的虚拟网卡,不会经过input
链。forward
(转发)方向禁止。iif xxxxxx
不能省略,否则会有巨大副作用:本机也无法访问容器内的服务。nft add rule inet filter forward iif wlp3s0 ct state new reject
上述规则对 IPv4 和 IPv6 都能生效。
ip
和 ip6
是 iptables
和 ip6tables
创建的规则。# handle N
标记,那是规则的序号,用于删除规则。如果不想显示handle
,可以不加-a
参数。nft list ruleset -a
输出示例:
table inet filter { # handle 11
chain input { # handle 1
type filter hook input priority 0; policy accept;
iif "wlp3s0" tcp dport ssh accept # handle 4
iif "wlp3s0" ct state new reject # handle 5
}
chain forward { # handle 2
type filter hook forward priority 0; policy accept;
iif "wlp3s0" ct state new reject # handle 6
}
chain output { # handle 3
type filter hook output priority 0; policy accept;
}
}
删除刚刚添加的防火墙规则
inet
表的序号是11
,所以可以这样删除:nft delete table handle 11
删除单条防火墙规则
if "wlp3s0" tcp dport ssh accept # handle 4
input
是规则所在的链(chain
),也必须写上去。nft delete rule inet filter input handle 4
完整脚本:
这是一个每次执行都会刷新现有规则的脚本。你只需要在脚本里修改规则,然后执行一次脚本就能生效了。
#!/bin/bash
set -e
# 删除现有规则
handle="$(nft list ruleset -a | grep 'table inet filter' | awk '{print $7}')"
if [ "$handle" != "" ]; then
nft delete table handle "$handle"
echo "old inet table deleted"
fi
# 添加新规则
nft add table inet filter
nft add chain inet filter input \{ type filter hook input priority 0 \; policy accept \; \}
nft add chain inet filter forward \{ type filter hook forward priority 0 \; policy accept \; \}
nft add chain inet filter output \{ type filter hook output priority 0 \; policy accept \; \}
nft add rule inet filter input iif wlp3s0 tcp dport 22 accept
nft add rule inet filter input iif wlp3s0 ct state new reject
nft add rule inet filter forward iif wlp3s0 ct state new reject
echo "rule added"
# 显示生效规则
nft list ruleset
使用systemd
让上面的脚本开机自启动
创建文件/usr/local/bin/nftables.sh
,内容如上。
创建systemd
启动项文件/etc/systemd/system/nftables.service
,内容如下:
[Unit]
Description=my nftables firewall
After=network.target
[Service]
Type=simple
Restart=no
User=root
ExecStart=/usr/local/bin/nftables.sh
[Install]
WantedBy=multi-user.target
sudo systemctl enable nftables
systemd
启动项的更多用法详见:https://hu60.cn/q.php/bbs.topic.101984.html
『回复列表(8|隐藏机器人聊天)』
更多nftables使用经验,参考ArchWiki:
https://wiki.archlinux.org/title/Nftables_%28%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87%29
@chrome,我不知道firewalld
如何,但我知道nftables
的优点是简单直接。只要知道基本语法,编写防火墙规则就像说话一样简单。
比如我的防火墙规则最后只有这三句话:
nft add rule inet filter input iif wlp3s0 tcp dport 22 accept
nft add rule inet filter input iif wlp3s0 ct state new reject
nft add rule inet filter forward iif wlp3s0 ct state new reject
翻译成汉语:
nft添加规则,名称为inet的过滤器,输入流量,来自网卡wlp3s0,tcp目的端口为22,接受
nft添加规则,名称为inet的过滤器,输入流量,来自网卡wlp3s0,连接状态为新建,拒绝
nft添加规则,名称为inet的过滤器,转发流量,来自网卡wlp3s0,连接状态为新建,拒绝
想要更复杂的防火墙规则,只要不断往句子里追加条件就行了。这种基于语法的规则定义方法和iptables
基于参数的规则定义方法比起来易用性无疑更高。
然后目的就达到了,并且没有副作用,不会导致docker、虚拟机等无法访问互联网。
我之前的规则nft add rule inet filter forward iif wlp3s0 reject
有导致虚拟机无法访问互联网的问题,但是加上ct state new
之后就解决了。nftables对Linux连接跟踪功能的深度支持让一切都变得异常简单,再也不用担心基于端口的过滤在本机发起连接时产生各种副作用。
而且ct state new
规则同时支持TCP和UDP,nftables规则同时适用于IPv4和IPv6,也让我非常惊喜。这样只需要一条规则就能兼顾四者。