我已经在我的服务器上设置了 nftables,我想将所有进入某些受保护端口(例如 80)的流量重定向到无需 root 权限即可使用的更高端口(例如 13080)。我希望只能远程访问 80,但可以在本地访问这两个端口。这是我想出的设置:
#!/usr/bin/nft -f
flush ruleset
table inet firewall {
chain inbound {
type filter hook input priority filter; policy drop;
ct status dnat counter accept # accept everything that came through destination nat (port 80)
iifname lo counter accept
oifname lo counter accept
ct state { established, related } counter accept
ct state invalid counter drop
tcp dport 22 ct state new counter accept
counter reject with icmpx type port-unreachable # reject everything else
}
chain destination-nat {
type nat hook prerouting priority dstnat; policy accept
tcp dport 80 counter redirect to 13080 # redirect 80 to 13080
}
chain forward {
type filter hook forward priority 0; policy drop;
}
chain outbound {
type filter hook output priority 0; policy accept;
}
}
但是,由于某种原因,这会阻止对端口 80 的本地访问(尽管 13080 仍然可以访问)。有人可以告诉我我做错了什么吗?
答案1
这是一个示例Netfilter 和通用网络中的数据包流其有效期为nftables:
里面写了一个重要的细节:* 仅针对“新”连接参考“nat”表。
对于本地启动的连接,新连接的第一个数据包在输出期间创建新的 conntrack 状态(输出的 conntrack 框)。当此连接环回时(几乎所有情况下都通过罗接口)这个相同的当数据包通过预路由(另一个 conntrack 框)返回时,conntrack 状态会匹配:本地环回连接不存在两个 conntrack 状态。
对于其他情况,新连接的第一个数据包通过预路由(预路由的 conntrack 框)到达,并导致创建新的 conntrack 状态。
因此,当发送连接的第一个环回数据包时,会创建一个新的 conntrack 条目输出期间当这个数据包通过预路由返回时,它与现有的 conntrack 条目匹配:不再是新状态。 NAT 挂钩(这意味着 nat/prerouting 链destination-nat
)不会被遍历,因此不会影响此连接:在输出步骤期间错过了机会。
相反,使用脱氧核糖核酸nat/output 中将出现新的 conntrack 状态的语句将解决这种情况。由于默认情况下它会影响任何本地发起的连接(即甚至到互联网),因此必须注意仅将其用于本地连接:通过罗界面。这个链和规则将做到这一点:
nft add chain inet firewall loopback-nat '{ type nat hook output priority -100; policy accept; }'
nft add rule inet firewall loopback-nat oif lo tcp dport 80 counter redirect to :13080
您只需在其他地方运行即可跟踪该行为conntrack
事件模式下的命令:
conntrack -E -p tcp --dport 80
并查看从外部发起的连接和本地发起的环回连接(有或没有此附加链)的区别。请记住,纳特钩子将只看到与状态一起显示的条目[NEW]
(并且已经相应地更改了命令显示的条目)。