网络是这样的,两台电脑分别在两个不同的环境中,A电脑上级是 OpenWrt,OpenWrt 网口1负责拨号上网,网口2连接到Wi-Fi路由器(仅仅是AP作用,有线中继),A连接这个Wi-Fi。
同样电脑B也是这样的网络拓扑。而且它们都有 OpenWrt 下发的 ipv6 地址。
我测试过,A电脑使用 server python3 -m http.server 8080 --bind ::
开一个 server,在 B 电脑使用 ipv6 地址+端口,是无法访问的。因为请求到达 A电脑上级 OpenWrt 时候,防火墙的 FORWARD 链默认是 DROP 的。 在防火墙将其转发打开,那么 B 电脑就可以正常访问了。
但是,双方电脑都使用 tailscale 组网的情况下,双方是可以通过 ipv6 直连的。通过 tailscale ping 就可以看到 pong from b (100.64.0.4) via [2408:xxxx:xxx:xxx::9c8]:35973 in 8ms
。
所以我不理解,tailscale(WireGuard)是怎么做到突破防火墙限制的?
WireGuard 虽然在电脑端开一个虚拟网卡和其他设备组内网,但这只是在内网环境中的。最终数据包是要经过 OpenWrt 的。比如 A 向 B 发一个数据包,经过互联网,先是到达 B 的上级 OpenWrt 的网口1,数据包的目标地址是 B 的 ipv6 地址,那么经过 OpenWrt 的路由表指示这个包要转发到网口2,于是在 OpenWrt 中网口1转发到网口2是要经过防火墙的 FORWARD 链的,默认是 DROP。但实际情况是可以正常连接,那它是怎么做到的?
19 个赞
简单一句话,这就是打洞哇。
原理我记得tailscale 博客有篇很详细的解释。
关注一下,一样想了解。
但是我觉得佬给的信息不太够,最好列出 openwrt 上的 iptables FORWARD 链配置的所有规则出来。
我按照上面的描述,我觉得问题应该是,Openwrt 路由器的 iptables FORWARD Chain 配置的是规则是 DROP,为什么还能转发到 WIFI 设备。
我觉得其实是 iptables FORWARD Chain 还配置了允许 Wireguard 的通过的规则,例如满足 UDP + Port 是 51820。
tonie
9
两边都在内网的话,流量会通过tailscale的服务器中转吧。。。
楼主的疑问是:
- 内网设备发起外部连接时, iptables 会创建连接跟踪(conntrack)条目
- 防火墙会自动允许这个连接的相关回包通过
- 这是打洞利用的原理
[OpenWrt Wiki] 如何配置防火墙
如上图:
OpenWRT 默认丢弃任何没有匹配到已有连接的包,言下之意,是允许已经建立连接的包通过的,并非一概丢弃,这也是任何防火墙的职责所在。
也就是说 OpenWRT 默认还配置了类似:
iptables -A FORWARD -m state --state RELATED,ESTABLISHED -j ACCEPT
的规则。
3 个赞
我现在更倾向于我这 OpenWrt 的问题,昨天防火墙的 FORWARD 默认是 DROP ,经过开一个 server 测试,确实是这样的。但是 tailscale 能用 v6 直连。但今天再测,就不能用 v6 直连了,而且我现在把 FORWARD 规则改成默认 ACCEPT 也不行。
由于是办公室的网络环境,不太方便 flush 掉所有规则做测试,具体是这样的:
$ ip6tables -L FORWARD -vn
Chain FORWARD (policy DROP 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
257K 161M forwarding_rule all * * ::/0 ::/0 /* !fw3: Custom forwarding rule chain */
226K 153M ACCEPT all * * ::/0 ::/0 ctstate RELATED,ESTABLISHED /* !fw3 */
16675 2716K zone_lan_forward all br-lan * ::/0 ::/0 /* !fw3 */
14322 5367K zone_wan_forward all pppoe-ppp * ::/0 ::/0 /* !fw3 */
0 0 zone_docker_forward all docker0 * ::/0 ::/0 /* !fw3 */
0 0 zone_ipsecserver_forward all ipsec0 * ::/0 ::/0 /* !fw3 */
0 0 reject all * * ::/0 ::/0 /* !fw3 */
# root @ OpenWrt in ~ [20:32:49]
$ iptables -L forwarding_rule -v -n
Chain forwarding_rule (1 references)
pkts bytes target prot opt in out source destination
1314K 1142M RETURN all -- pppoe+ * 0.0.0.0/0 0.0.0.0/0
886K 333M RETURN all -- * pppoe+ 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- ppp+ * 0.0.0.0/0 0.0.0.0/0 ctstate NEW
0 0 ACCEPT all -- * ppp+ 0.0.0.0/0 0.0.0.0/0 ctstate NEW
数据包是这样走的,数据包来到网口 1 后,经过 forward 链,然后第一条是自建的 forwarding_rule
(我也不知道谁建的这条 rule ),这个 rule 表示,如果是从 pppoe
开头的网口,那么数据包会 RETURN ,RETURN 代表向下一条规则过滤,也就是走到 ACCEPT 这一条,这一条后面是 ctstate RELATED,ESTABLISHED
,代表如果是出站过的流量,那么返回的响应是正常接收的。
然后就是下面这些 OpenWrt 自定义的规则了。能够看到数据包也小,数据量都是在 forwarding_rule 上,估计使用 tailscale 连接是被这条链捕获记录。
1 个赞
应该不是,WireGuard 是客户端装的,对于流经 OpenWrt 的数据包来讲,op 根本不知道是什么类型的数据包,它仅仅是符合 tcpip 模型的,有 IP 和 端口,ip 发现不是自己的,就转发到另一个网口。
1 个赞