如何在网关上正确地把 DNS 请求路由到 TUN? - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
CrazyRundong
V2EX    宽带症候群

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

  •  
  •   CrazyRundong 2023-12-10 18:34:54 +08:00 6181 次点击
    这是一个创建于 677 天前的主题,其中的信息可能已经有所发展或是发生改变。

    最近把 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 设备 

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

    第 1 条附言    2023-12-10 22:36:37 +08:00

    按照 @pagxir #5, #7 的回复,将 DNS 请求 DNAT 到 TUN 对应的网段后,这些数据包就被交由 FORWARD chain 处理从而能正确转发到 TUN 设备了。具体的修改如下:

    # 1. 在 prerouting chain 标记需要被代理的 DNS 数据包 type filter hook prerouting priority mangle - 1; policy accept; iifname $lan_devices meta l4proto {tcp, udp} th dport 53 counter meta mark set $dns_mark return # 我的 TUN 地址是 172.19.0.1/24; fdfe:dcba:9876::1/126 # 为防止被路由至 INPUT chain,将地址 +1 define tun_route_ip = 172.19.0.2 define tun_route_ip6 = fdfe:dcba:9876::2 # 2. 在 nat chain 将被标记的数据包 DNAT 到 TUN 的网段上 type nat hook prerouting priority dstnat - 1; policy accept; meta mark $dns_mark dnat ip to $tun_route_ip meta mark $dns_mark dnat ip6 to $tun_route_ip6 

    感谢各位大佬~

    第 2 条附言    2023-12-11 21:56:14 +08:00

    完整的 nftables 代码在 99-sing-box.nft#L65-L83,需要配合相应的服务启动停止脚本来配置策略路由。谨供遇到同样困扰的朋友们参考~

    22 条回复    2024-05-11 16:40:47 +08:00
    CrazyRundong
        1
    CrazyRundong  
    OP
       2023-12-10 18:39:30 +08:00
    目前的临时解决方案是在网关 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
        2
    EyebrowsWhite  
       2023-12-10 18:54:30 +08:00
    应该因为你的 dnsmasq 占用了 53 端口,`ss -ulnp | grep 53`确认一下,如果不用 dnsmasq ,就把它关了,然后 sing-box 的 DNS 监听端口改为 53
    CrazyRundong
        3
    CrazyRundong  
    OP
       2023-12-10 18:58:49 +08:00
    @EyebrowsWhite 目前仍然需要 dnsmasq 监听在 53 端口来处理没被代理的设备的 DNS 请求,以及托管局域网里的一些域名映射规则。sing-box 似乎默认是没有 DNS 监听端口的,不像 Clash 。我在想能不能只开一个 TUN 、不用其他端口配置就能把 DNS 给处理好了
    lookookok
        4
    lookookok  
       2023-12-10 19:19:23 +08:00
    不是太懂内核网络处理,盲猜是不是你这个策略只应用于转发数据包,而入站数据包是不是还要单独设置策略路由?

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

    @pagxir 多谢大佬提醒,具体是指在 prerouting nat 里将 DNS 包 DNAT 到 TUN 的地址吗?我试试看
    pagxir
        7
    pagxir  
       2023-12-10 21:37:49 +08:00
    @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
        8
    CrazyRundong  
    OP
       2023-12-10 21:41:00 +08:00
    @pagxir 哈哈理解了,解释得很清楚!刚刚还在疑惑如果 DNAT 到 TUN 地址会不会又回环到 INPUT chain, 这么一说就明白了
    kingboy9525
        9
    kingboy9525  
       2023-12-11 13:36:35 +08:00
    @CrazyRundong 请问有完整的 nft 可以参考一下吗?谢谢
    Kobayashi
        11
    Kobayashi  
       2023-12-12 11:58:14 +08:00
    让 sing-box DNS 监听在非 53 口,在 dnsmasq 里配置其为上游呢?
    CrazyRundong
        12
    CrazyRundong  
    OP
       2023-12-12 21:55:31 +08:00
    @Kobayashi #11 应该也可以!就是不知道 sing-box 的哪种入站类型可以直接接收处理 DNS 请求
    jacky4231
        13
    jacky4231  
       2024-01-13 16:58:08 +08:00
    楼主,我在 openwrt23.5 上直接安装了 sing-box 1.8.0 ,自己写了 josn ,用 tun 模式,可以连通,但是不知为何下载速度测试只有 250 左右,家里是千兆的网络。本人小白,能否将自定义 nft 规则给个完整的,并且告知如何导入?多谢了!
    CrazyRundong
        14
    CrazyRundong  
    OP
       2024-01-13 17:09:57 +08:00 via iPhone
    @jacky4231 #13 在主帖的第二条附言有完整链接哈
    jacky4231
        15
    jacky4231  
       2024-01-13 19:26:24 +08:00
    @CrazyRundong 感谢回复,我再试试
    jacky4231
        16
    jacky4231  
       2024-01-23 23:12:47 +08:00 via Android
    大佬,能否帮忙写一下 tproxy 的 init.d 和 nft 配置文件?小白一个,tun 模式网速太低了,感激不尽,[email protected]
    CrazyRundong
        17
    CrazyRundong  
    OP
       2024-01-24 11:18:30 +08:00
    @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
        18
    jacky4231  
       2024-02-22 10:21:44 +08:00
    @CrazyRundong 新年快乐!能给下客户端配置文件样本吗,是不是我的配置文件有问题?多谢!
    journalist
        19
    journalist  
       2024-02-22 18:36:56 +08:00
    我的 tun 接口不是在本机应该怎样修改呢,具体来说网关是 192.168.1.1 ,tun 在 192.168.1.2
    CrazyRundong
        20
    CrazyRundong  
    OP
       2024-02-23 11:20:22 +08:00   1
    @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

    请不要做伸手党或直接留邮箱,这对社区讨论和知识共享无益,我也没有义务帮你写配置文件
    journalist
        21
    journalist  
       2024-02-24 18:35:24 +08:00
    感谢!我现在已经跑通了。
    ip route replace default via 192.168.1.2 dev br-lan table ${tun_table}

    有一个问题就是 type nat hook prerouting priority dstnat - 1; policy accept; 这里会报错 Could not process rule: Not supported 。我就把 dns dnat 去掉了,用 openwrt uci 自带的端口转发功能。
    garryforreg420
        22
    garryforreg420  
       2024-05-11 16:40:47 +08:00
    用 sing-box 的 direct 开一个端口来当 dns 服务器不就行了,干嘛搞这么复杂.
    op 的 dnsmasq 关了或者换个端口,sing-box 配置 inbound direct 53,主路由或者 op 的 dhcp 上把下发 dns 服务器指向 sing-box 开放的地址即可。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2842 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 27ms UTC 07:28 PVG 15:28 LAX 00:28 JFK 03:28
    Do have faith in what you're doing.
    ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86