我正在尝试建立一个简单的状态防火墙和nftables遵循Arch Linux nftables 指南。我在 Arch Linux 论坛上发布了这个问题,但从未收到答案。
完成指南并重新启动我的机器后,系统无法加载nftables.service。为了解决我运行的错误:
systemctl status nftables
这是相关的输出:
/etc/nftables.conf:7:17-25: Error: conflicting protocols specified: inet-service v. icmp
该错误抱怨我为在输入链中接受新 ping (icmp) 而设置的规则。这是规则,我不认为它有什么问题:
icmp type echo-request ct state new accept
如果我删除该规则,它就会起作用。但我想要规则。
这是我的规则集nftables.conf完成指南后:
table inet filter {
chain input {
type filter hook input priority 0; policy drop;
ct state established,related accept
iif "lo" accept
ct state invalid drop
icmp type echo-request ct state new accept
ip protocol udp ct state new jump UDP
tcp flags & (fin | syn | rst | ack) == syn ct state new jump TCP
ip protocol udp reject
ip protocol tcp reject with tcp reset
meta nfproto ipv4 counter packets 0 bytes 0 reject with icmp type prot-unreachable
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain output {
type filter hook output priority 0; policy accept;
}
chain TCP {
tcp dport http accept
tcp dport https accept
tcp dport ssh accept
tcp dport domain accept
}
chain UDP {
tcp dport domain accept
}
}
我缺少什么?先感谢您。
答案1
这是 nftables 0.7(或其他一些版本)的语法限制:它不认为 ICMP 和 ICMPv6 可直接在双 IPv4/IPv6 表中使用,inet
而无需明确说明首先使用哪个 IP 协议:
所以规则是:
icmp type echo-request ct state new accept
要同时在 IPv4 和 IPv6 上工作,必须像这样编写两次:
更新:实际上,人们不应该依赖 IPv6 指向nexthdr
上层协议:可以有扩展头固定报头和上层报头(最后一个)之间。添加正确的语法(使用已经提供协议信息的元信息),并保留我原来的答案,因为我不知道“正确”语法对于 nftables 0.7 是否有效:
meta nfproto ipv4 meta l4proto icmp icmp type echo-request ct state new accept
meta nfproto ipv6 meta l4proto icmpv6 icmpv6 type echo-request ct state new accept
ip protocol icmp icmp type echo-request ct state new accept
ip6 nexthdr icmpv6 icmpv6 type echo-request ct state new accept
给出相应的字节码(使用显示nft --debug=netlink list ruleset -a
):
inet filter input 9 8
[ meta load nfproto => reg 1 ]
[ cmp eq reg 1 0x00000002 ]
[ payload load 1b @ network header + 9 => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
[ payload load 1b @ transport header + 0 => reg 1 ]
[ cmp eq reg 1 0x00000008 ]
[ ct load state => reg 1 ]
[ bitwise reg 1 = (reg=1 & 0x00000008 ) ^ 0x00000000 ]
[ cmp neq reg 1 0x00000000 ]
[ immediate reg 0 accept ]
inet filter input 10 9
[ meta load nfproto => reg 1 ]
[ cmp eq reg 1 0x0000000a ]
[ payload load 1b @ network header + 6 => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
[ payload load 1b @ transport header + 0 => reg 1 ]
[ cmp eq reg 1 0x00000080 ]
[ ct load state => reg 1 ]
[ bitwise reg 1 = (reg=1 & 0x00000008 ) ^ 0x00000000 ]
[ cmp neq reg 1 0x00000000 ]
[ immediate reg 0 accept ]
ICMP 是 IP 协议 1,回显请求值 8。ICMPv6
是 IPv6 协议 58 (0x3a),其回显请求值 128 (0x80)。
较新的 nftables 0.9 直接接受规则icmp type echo-request ct state new accept
,但其相应的字节码只是:
inet filter input 9 8
[ meta load nfproto => reg 1 ]
[ cmp eq reg 1 0x00000002 ]
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x00000001 ]
[ payload load 1b @ transport header + 0 => reg 1 ]
[ cmp eq reg 1 0x00000008 ]
[ ct load state => reg 1 ]
[ bitwise reg 1 = (reg=1 & 0x00000008 ) ^ 0x00000000 ]
[ cmp neq reg 1 0x00000000 ]
[ immediate reg 0 accept ]
这意味着它只处理 ICMP,而不是 ICMPv6,仍应添加一条附加规则,简单如下:
icmpv6 type echo-request ct state new accept
返回先前版本的等效字节码:
inet filter input 10 9
[ meta load nfproto => reg 1 ]
[ cmp eq reg 1 0x0000000a ]
[ meta load l4proto => reg 1 ]
[ cmp eq reg 1 0x0000003a ]
[ payload load 1b @ transport header + 0 => reg 1 ]
[ cmp eq reg 1 0x00000080 ]
[ ct load state => reg 1 ]
[ bitwise reg 1 = (reg=1 & 0x00000008 ) ^ 0x00000000 ]
[ cmp neq reg 1 0x00000000 ]
[ immediate reg 0 accept ]