nftables 怎么写基于 set 的转发规则

2023-01-14 14:47:37 +08:00
 lifanxi

以前我在 OpenWrt 上是用 dnsmasq-full 配合 ipset 加上 iptables 规则指定域名的解析结果做转发,比如:

ipset -N test iphash
iptables -t nat -A PREROUTING -p tcp -m set --match-set test dst -j REDIRECT --to-port 1080

现在新版本的 OpenWrt 里默认用 fw4 了,用 nftables 取代了 iptables ,研究了一天,前面把 ipset 换成 nftables 里的 set 的动作都搞定,就差最后一步这个 iptables 转发规则要改写成 nftables 的没搞定,试来试去都不对,用 iptables-translate 转换也转换不出来。

求教上面这条 iptables 的规则应该如何改写成 nft 的规则?

1924 次点击
所在节点    问与答
12 条回复
rshun
2023-01-15 09:46:38 +08:00
ip daddr {180.97.34.94,180.97.34.96} redirect to :1080

试试呢
lifanxi
2023-01-15 14:23:34 +08:00
@rshun 这个没有用到 set ,不过就算是写死 IP 好像也不行,我是这么尝试的:
```
root@OpenWrt:~# nft ip daddr 111.111.111.111 redirect to :1080
Error: transport protocol mapping is only valid after transport protocol match
ip daddr 104.244.42.65 redirect to :1080
~~~~~~~~ ^^^^
```
貌似匹配 IP 不能重定向去端口。
rshun
2023-01-15 16:26:15 +08:00
@lifanxi 我是放在配置文件里面的,你把 IP 写在一个文件里面
```
define test_list={
111.111.111.111,
222.222.222.222
}
```

然后在 nft 的配置文件里面
```
include "/etc/nftables.d/test.nft"

table inet clash {
chain prerouting {
type nat hook prerouting priority 0; policy accept;
ip daddr $test_list redirect to :1080
}
}
```
lifanxi
2023-01-15 16:59:04 +08:00
试了一下,一模一样照抄还是不行,还是报一样的错。在 OpenWrt 22.02.2 上和 Debian 11 上都是这样,nftables 的版本是 0.9.8 ,内核是 5.10 。
```
/tmp/1.nft:8:34-37: Error: transport protocol mapping is only valid after transport protocol match
ip daddr $test_list redirect to :1080
~~~~~~~~ ^^^^
```
lifanxi
2023-01-15 16:59:33 +08:00
@rshun 继续求教。

试了一下,一模一样照抄还是不行,还是报一样的错。在 OpenWrt 22.02.2 上和 Debian 11 上都是这样,nftables 的版本是 0.9.8 ,内核是 5.10 。
```
/tmp/1.nft:8:34-37: Error: transport protocol mapping is only valid after transport protocol match
ip daddr $test_list redirect to :1080
~~~~~~~~ ^^^^
```
rshun
2023-01-15 17:48:00 +08:00
@lifanxi

ip daddr $test_list meta l4proto {tcp,udp} redirect to :1080
lifanxi
2023-01-15 20:39:01 +08:00
@rshun
多谢指点,虽然还是没有完全搞明白,不过我照猫画虎把我要的功能搞定了。

方法是在 /usr/share/nftables.d/ruleset-post 下加一个.nft 文件,内容如下:
table inet sometable {
set test {
type ipv4_addr
size 65536
}

chain prerouting {
type nat hook prerouting priority 0; policy accept;
ip daddr @test meta l4proto {tcp,udp} redirect to :1080
}
}

然后重启 firewall 就可以了。

不能直接写在 /etc/nftables.d 中是因为那下面的文件会被 include 在 fw4 这个 table 里。即使我去掉外层的 table 也不行,原因我还没搞清楚。

dnsmasq 的配置类似于这样( dnsmasq 版本必须手工更新到 2.87 或以上):

server=/somedomain.com/127.0.0.1#5300
nftset=/somedomain.com/4#inet#sometable#test

这么写只支持 IPv4 ,如果要支持 IPv6 方法类似。
rshun
2023-01-15 21:01:06 +08:00
#!/usr/sbin/nft -f

flush ruleset

include "/etc/nftables.d/test.nft"

table inet clash {
chain prerouting {
type nat hook prerouting priority 0; policy accept;
ip daddr $test_list redirect to :1080
}
}
nbweb
2023-02-09 15:17:34 +08:00
@lifanxi 楼主,你好,我遇到你一样的问题了。想在 debian 11 上面搞透明,也是想用 ipset 来管理 gfw list ,可否留下电报,我请教一下?
目前用 nftables 透明是通了,但是不能智能分流,国内国外是分开的。我之前搞的 iptables 是只走 list 的那种。

谢谢!
sxttwyf
237 天前
@lifanxi 去掉 table 后 include 在 fw4 这个 table 里工作也正常,我今天刚由 iptable 转到 nftable 。
sxttwyf
237 天前
@nbweb 我的透明方案是 mosdns+nftables+v2ray
nbweb
150 天前
@sxttwyf
@lifanxi

两位大佬,帮看下这个问题: https://v2ex.com/t/996702
感谢!

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/908897

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX