我有一个 Linux 服务器,它是一个 OpenVPN 端点,但也托管一个网络服务器。当我的客户端连接到网络服务器的服务器地址时,数据包会在 VPN 之外传输。确实如此,因为 OpenVPN 设置的到服务器的路由比进入 VPN 的默认路由更具体。但我认为这是一个“泄漏”。
因此,我尝试设置与 Wireguard 类似的设置(Wireguard 很棒,但我需要 OpenVPN,因为它需要是 TCP)。
我的设置基于 Wireguard 页面以及其他问题: Prevent Routing Loop with FwMark in Wireguard (向那里举行的讲座致敬!) Routing fwmark to VPN gateway using nftables mark
尽管进行了设置,Wireshark 显示 http/https 请求仍然通过物理接口而不是通过 vpn tun0 接口。当我使用 nft 监视器跟踪查看数据包标记时,似乎元标记已正确设置,并且仅出现适当的数据包(发往/来自端口 1194)。
所以我怀疑这是:
- PBR 规则未按预期工作。
- 数据包标记没有尽早发生。
我尝试更改链以将传出数据包标记为:
- 输入路由钩子输出
- 类型过滤钩输出
- --> 没有更多的运气
这些命令返回以下内容:
- ip rule:
0: from all lookup local
32764: from all lookup main suppress_prefixlength 0
32765: not from all fwmark 0x4 lookup vpn
32766: from all lookup main
32767: from all lookup default
- ip route show table vpn:
default dev tun0 scope link
- ip route:
default via 10.8.0.1 dev tun0 proto static metric 50
default via 192.168.1.1 dev wlp4s0 proto dhcp src 192.168.1.10 metric 600
10.8.0.0/24 dev tun0 proto kernel scope link src 10.8.0.2 metric 50
END.POINT.IP.ADDRESS via 192.168.1.1 dev wlp4s0 proto static metric 50
192.168.1.0/24 dev wlp4s0 proto kernel scope link src 192.168.1.10 metric 600
-nft list ruleset:
table inet vpn {
chain premangle {
type filter hook prerouting priority mangle; policy accept;
ip saddr END.POINT.IP.ADDRESS tcp sport 1194 meta nftrace set 1
meta mark set ct mark
}
chain postmangle {
type filter hook postrouting priority mangle; policy accept;
ip daddr END.POINT.IP.ADDRESS tcp dport 1194 meta nftrace set 1
ip daddr END.POINT.IP.ADDRESS tcp dport 1194 meta mark set 0x00000004
meta mark 0x00000004 ct mark set meta mark
}
}
- traceroute -n --fwmark=0x4 END.POINT.IP.ADDRESS
shows it goes via the physical interface out of the vpn (as expected)
- traceroute -n END.POINT.IP.ADDRESS
shows it goes via the physical interface out of the vpn (UNWANTED)
非常感谢您提前!
如果不使用严格反向路径转发(“SRPF”),则根本不应使用nftables 。
虽然在iptables或nftables中处理标记时,路由(转发)流量通常工作正常,但由于标记(在链中)而本地启动的重新路由流量通常会出现问题:链中发生的重新路由检查不会神奇地更改本地源已在客户端套接字上选择的 IP 地址。通常是 IP 地址错误。因此,它通常需要 NAT bandaid(在 中需要),并且可能会使 UDP 处理比多宿主环境中的情况更加困难。应尽可能避免为此使用nftables 。
type route hook output
type route hook output
type nat hook output
正如 WireGuard 一样,OpenVPN可以在其信封传出流量上充分设置防火墙标记,这将在本地传出流量发生任何路由查找之前发生:
这与 WireGuard 的工作原理相同:在真实接口上传出的信封数据包可能会通过让客户端
SO_MARK
在连接到服务器之前使用其套接字来获得标记:当然,如果重新路由或直接使用策略路由(包括直接标记(使用
SO_MARK
或等效方法))都没有到位,那么它很可能根本不起作用。因此删除所有nftables规则:
并在客户端配置中添加:
保留路由规则和表(它们可能应该集成在 VPN 挂钩中):
注意:本答案末尾的部分仅适用于 SRPF 情况,应在添加上面的路由表条目之前添加,以避免暂时中断。
不要添加通过 VPN 的默认路由,也不要添加到远程端点的显式路由。不要让服务器推送此配置。或者让客户忽略它:
或者:
为了不出现这些路线:
但只有这个被添加:
相反,策略路由规则将
vpn
仅在足够时通过选择路由表来处理默认路由。正如我对第一个链接的 Q/A 的回答中所解释的, WireGuard +的大多数nftables规则集都是处理回复流量的SRPF。有以下几种情况:
Table = auto
AllowedIPs = 0.0.0.0
rp_filter=0
到处包括
net.ipv4.conf.default.rp_filter
和net.ipv4.conf.all.rp_filter
。没有 RPF 检查:无事可做。不需要nftables。rp_filter=1
现在信封回复流量可能会导致 SRPF 失败
要么在主界面上选择Loose RPF:
并完成它。不需要nftables,
或实现所有逻辑来标记返回信封流量,就像在 WireGuard 中所做的那样
让 fwmark 也可用于反向路径查找
通过
src_valid_mark
在主界面上启用(也可以改为启用all
),从而允许 SRPF 通过:转置(此处仅限 IPv4)WireGuard 的设置
如链接的 Q/A中所示,末尾描述的其他极端情况也被考虑在内,因此回复流量获得 fwmark
链条
preraw
是可选的,如果需要可以拆除。它可以防止远程(LAN)尝试访问内部 VPN 本地地址。该标记由 OpenVPN 在传出信封数据包上创建,在钩子后路由处复制到 connmark 中,并在钩子预路由处重新注入到回复信封数据包中。任何地方都没有出现端点地址或端口。
没有重新路由(没有
type route hook output
也不type nat hook output
存在)。注意:上面的 sysctl 命令和nftables规则集都应该在路由表中添加默认路由之前执行
vpn
,否则会发生暂时的连接丢失,直到 VPN TCP 套接字恢复(仍然只有在两者都添加后)。客户端系统现在可以从隧道内到达服务器。
连接测试可以这样完成:
OP
tcpdump
应通过 VPN 单跳到达 END.POINT.IP.ADDRESS。至少在 amd64 (x86-64) 架构上,可以通过以下方式绕过 VPN(以 root 身份):
其中
setsockopt-listen
表示:SO_MARK
在连接之前使用(在本例中不是监听)。其中的4与L4
OpenVPN使用的标记值相同。注意:客户端通过隧道使用服务器的公共 IP 地址查询服务器上的 UDP 服务的具体情况可能会遇到一个与 VPN 无关的常见问题,而是与使用 UDP 和多宿主相关。这要求 UDP 服务具有多宿主感知能力:通常通过使用多个 UDP 套接字,为每个本地地址绑定一次(因此通常每个接口至少
IP_PKTINFO
绑定一次),或者通过使用附加处理代码来使用单个未绑定的 UDP 套接字。首先非常感谢您的及时回复。
噢,好吧。据我了解,由于请求过程中的初始路由决策已经发生,如果没有 NAT,重新路由将发送源错误的数据包,从而失败。
所以我做了以下事情:
关于 rp_filter,我的发行版默认值为 2,我不会再增加复杂性。因此,请按照建议将所有这些都排除在外。我暂时将这些都设置为 0。
我保留 nftables 只是为了跟踪数据包并确保 openvpn 确实按照以下方式标记数据包)。
但是现在,我无法再访问网络服务器:
我这么做
ip route flush cache
只是为了以防万一。没有成功,虽然一切似乎都井然有序:Wirehshark 不会显示与请求相关的任何数据包,甚至不会显示错误的地址或没有答案。
请问有什么可能妨碍的线索吗?!抱歉,如果我误解了任何一点,坦率地说,您提出的设置对我来说很有意义。谢谢 !