现状

  • 主路由 192.168.2.1 关闭 DHCP
  • OpenWrt 软路由 (192.168.2.2) 提供 DHCP 服务,DHCP 下发的网关为 192.168.2.2, 下发的 DNS 为 192.168.2.2
  • OpenWrt 软路由 (192.168.2.2) 安装 Tailscale,已设置 Exit Node + Subnet Route 192.168.2.0/24
  • 网络 -> 防火墙 -> 区域:已存在 tailscale -> lan 的 IP 动伪装(Masquerading)
  • 网络 -> 接口:只有 lan 和 tailscale 两个接口

问题

  • 从公网连上 Tailscale 并指定 OpenWrt 为 Exit Node 后,只能访问 192.168.2.2,192.168.2.0/24 网段下的其他主机和公网全部超时

解决

使用 tcpdump 抓包发现是回程的包没有正确返回,确定是 SNAT 的问题。
手动加入 iptables -t nat -I POSTROUTING -s 100.64.0.0/10 -o br-lan -j MASQUERADE 之后问题解决, LAN 和公网均可借助 OpenWrt 访问

但是我使用的 openwrt 比较新,已经不再推荐使用 iptables 管理防火墙,所以还要寻找一下替代方案。

在 o3 的帮助下,终于找到可行的做法,操作步骤如下

  1. 登录 LuCI → 「网络 ▸ 防火墙」
    这里会看到 概览 / 端口转发 / 流量规则 / NAT 规则 四个标签。
    “NAT 规则”正是专门用来写 SNAT/MASQUERADE 的页面。
  2. 切到 「NAT 规则」 标签页,点页面底部 「添加」。
    会弹出一个带 3 个子标签的表单:常规设置 / 高级设置 / 时间限制。
    这些字段的名字与含义可在官方手册中对应到 UCI 配置项,
    其中“出口设备”“动作”等就是我们需要填的要素。
  3. 常规设置 里填写

    字段选择 / 填写值说明
    名称CGNAT-masq任意易辨识的名字
    限制地址族IPv4只处理 IPv4
    协议任意与 iptables 命令里的“全部协议”一致
    出口区域未指定(或保持默认)MASQUERADE 不要求指定 zone
    源地址100.64.0.0/10对应 -s 参数
    动作MASQUERADE – 自动改写为出口接口 IP与 iptables 目标一致
  4. 点击 高级设置 子标签,再设置

    字段选择值
    出口设备br-lan对应 -o br-lan;这个字段只在高级设置里出现

    其他保持默认即可。
    (如果你的接口名字不同,请按实际桥接口名选取。)

    config nat
     option name   'CGNAT-masq'
     option family 'ipv4'
     option hook   'postrouting'
     list   match  'ip saddr 100.64.0.0/10'
     list   match  'oifname "br-lan"'
     option target 'MASQUERADE'

    firewall4 随后会把它转译为 nft 规则
    ip saddr 100.64.0.0/10 oifname "br-lan" masquerade
    写入 table inet fw4 chain srcnat,效果与原 iptables 指令完全一致。

生效检查

SSH 到路由器执行:

nft list table inet fw4 | grep 100.64

应能看到:

ip saddr 100.64.0.0/10 oifname "br-lan" masquerade

标签: openwrt, tailscale

添加新评论