如何在网关上正确地把 DNS 请求路由到 TUN?

150 天前
 CrazyRundong

最近把 OpenWRT 网关上的分流工具从 Clash 切换到了 sing-box ,顺带开始了解基于 TUN 的透明代理配置。目前遇到的一个问题是,局域网内的 DNS 请求并没有被正确地路由/转发进 sing-box 的 DNS 模块。

具体的情况有点复杂。因为需要让家里运行着 PT 的 NAS 这类的设备不被透明代理,所以在配置 TUN 时并没有使用 auto route,而是自己编写了 nftables 规则和对应的 ip rule/ip route 策略路由,将需要代理的设备的流量标上一个特定的 fwmark ,再将标记的流量策略路由到 sing-box 的 TUN 网卡 tun0 。简化后的设置类似这样:

# 在 nftables 的 prerouting 阶段标记需要被代理的流量:
type filter hook prerouting priority mangle - 1; policy accept;
# 1. 需要直连的设备 MAC 被提前存在 direct_macs set 中,不做额外处理直接放行
ether saddr @direct_macs counter return
# 2. 剩余的来自 LAN 的流量均需要代理,标记为 $tun_mark (0x02)
iifname $lan_devices counter meta mark set $tun_mark

之后配置策略路由:

# 将被标记了 tun_mark 的流量查 tun_table 表路由至 tun_dev
ip route replace default dev ${tun_dev} table ${tun_table}
ip rule add fwmark ${tun_mark} table ${tun_table}

至此整个系统可以正常工作了。但奇怪的是,只有指定了 DNS 服务器为非网关地址 (≠ 192.168.50.1) 的局域网内 DNS 请求才会被转发进 TUN ,而默认的、DNS 服务器地址为 192.168.50.1 的 DNS 请求并没有被 sing-box 看到,而是仍由监听在网关 53 端口的 dnsmasq 处理:

# 在局域网内的任一台被透明代理的设备上:
nslookup google.com         # 这条查询会被 dnsmasq 接收
nslookup google.com 1.1.1.1 # 这条查询才会被正确地路由进 sing-box 的 TUN 设备

请问大家是不是我配置的策略路由在哪里出问题?多谢

3019 次点击
所在节点    宽带症候群
21 条回复
CrazyRundong
150 天前
目前的临时解决方案是在网关 sing-box 上再开一个 TProxy 端口,借助 TProxy 可以处理 UDP 请求的特性,把来自 LAN 的 TCP/UDP 53 流量通过 nftables 规则 TProxy 到这个端口。但感觉还是搞得太繁琐了,应该没必要这么麻烦
```
# 增加了一条 nftables 规则来 TProxy 来自局域网的 DNS 请求
iifname $lan_devices meta l4proto {tcp, udp} th dport 53 counter meta mark set $tproxy_mark tproxy to :$tproxy_port
```
(需要配置对应的额外策略路由)
```
ip route replace local default dev lo table ${tproxy_table}
ip rule add fwmark ${tproxy_mark} table ${tproxy_table}
```
EyebrowsWhite
150 天前
应该因为你的 dnsmasq 占用了 53 端口,`ss -ulnp | grep 53`确认一下,如果不用 dnsmasq ,就把它关了,然后 sing-box 的 DNS 监听端口改为 53
CrazyRundong
150 天前
@EyebrowsWhite 目前仍然需要 dnsmasq 监听在 53 端口来处理没被代理的设备的 DNS 请求,以及托管局域网里的一些域名映射规则。sing-box 似乎默认是没有 DNS 监听端口的,不像 Clash 。我在想能不能只开一个 TUN 、不用其他端口配置就能把 DNS 给处理好了
lookookok
150 天前
不是太懂内核网络处理,盲猜是不是你这个策略只应用于转发数据包,而入站数据包是不是还要单独设置策略路由?

还有个折中的办法是可在 op web 设置中,指定的 dnsmasq 作为客户端源查询端口,给这个端口出站做策略走 tun ,比再来个 TProxy 简单些。
pagxir
150 天前
走 tun 前提需要 forward ,很明显,你这个并不需要 forward ,而是走 input 链的。所以你需要要执行以下 DNAT ,使得报文走 forward 链。
CrazyRundong
150 天前
@lookookok 我的理解是 prerouting 发生在路由之前,也就是说 prerouting mangle 里打的 fwmark 是能够同时覆盖入站和转发的,参考 https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg

@pagxir 多谢大佬提醒,具体是指在 prerouting nat 里将 DNS 包 DNAT 到 TUN 的地址吗?我试试看
pagxir
150 天前
@CrazyRundong 假设你 tun 的 IP 是 10.111.9.11/24, 那么你可以-j DNAT --to 10.111.9.222, 那样很自然就需要 forward 到 tun 出去了。(注意不能 -j DNAT --to 10.111.9.11, 那样还是会走 input 的)
CrazyRundong
150 天前
@pagxir 哈哈理解了,解释得很清楚!刚刚还在疑惑如果 DNAT 到 TUN 地址会不会又回环到 INPUT chain, 这么一说就明白了
kingboy9525
149 天前
@CrazyRundong 请问有完整的 nft 可以参考一下吗?谢谢
CrazyRundong
149 天前
Kobayashi
148 天前
让 sing-box DNS 监听在非 53 口,在 dnsmasq 里配置其为上游呢?
CrazyRundong
148 天前
@Kobayashi #11 应该也可以!就是不知道 sing-box 的哪种入站类型可以直接接收处理 DNS 请求
jacky4231
116 天前
楼主,我在 openwrt23.5 上直接安装了 sing-box 1.8.0 ,自己写了 josn ,用 tun 模式,可以连通,但是不知为何下载速度测试只有 250 左右,家里是千兆的网络。本人小白,能否将自定义 nft 规则给个完整的,并且告知如何导入?多谢了!
CrazyRundong
116 天前
@jacky4231 #13 在主帖的第二条附言有完整链接哈
jacky4231
116 天前
@CrazyRundong 感谢回复,我再试试
jacky4231
106 天前
大佬,能否帮忙写一下 tproxy 的 init.d 和 nft 配置文件?小白一个,tun 模式网速太低了,感激不尽,📭413400425@qq.com
CrazyRundong
105 天前
@jacky4231 #16 我没有使用 sing-box + TProxy 的计划。但是我之前的 Clash 分流是通过 TProxy 实现的,你可以参考一下 https://github.com/lirundong/homelab-infra/blob/master/openwrt-builder/files/etc/init.d/clash.skip

另外,我这边观察到的 sing-box TUN 的网速足够跑满千兆下行 + 200M 上行,所以你观察到的网速低不一定是 sing-box TUN 的锅
jacky4231
77 天前
@CrazyRundong 新年快乐!能给下客户端配置文件样本吗,是不是我的配置文件有问题?多谢!
journalist
76 天前
我的 tun 接口不是在本机应该怎样修改呢,具体来说网关是 192.168.1.1 ,tun 在 192.168.1.2
CrazyRundong
75 天前
@jacky4231 #18 sing-box 配置文件可以通过 https://github.com/lirundong/homelab-infra/blob/master/conf-gen/generate.py 脚本自动生成,其源文件是 https://github.com/lirundong/homelab-infra/blob/93352db/conf-gen/source.yaml#L532-L617

请不要做伸手党或直接留邮箱,这对社区讨论和知识共享无益,我也没有义务帮你写配置文件

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

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

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

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

© 2021 V2EX