我有一个 WireGuard 服务器作为边缘路由器。将所有 http 流量转发到我的网络服务器。一切正常,但有一个问题。Web 服务器无法通过 WireGuard 公共 IP 地址访问自身。在网络服务器计算机上,我无法使用网络浏览器访问我的网站。
我发现daddr
基于 nat 可以解决这个问题,但我想知道是否有更好的方法,因为 IP 地址可能会有所不同但iif
已修复。我的 Netgear WiFi 路由器可以进行端口转发,而不会出现这种问题。但我无法检查它的内部规则,我也不认为它使用daddr
基于 nat。
这是WireGuard 服务器的配置。
wg0
interface: wg0
Address = 10.0.0.1/24
public key: (hidden)
private key: (hidden)
listening port: 51820
peer: (hidden)
endpoint: (hidden):51820
allowed ips: 10.0.0.2/32
latest handshake: 56 seconds ago
transfer: 20.69 MiB received, 115.85 MiB sent
表格
table ip firewall {
chain input {
type filter hook input priority filter; policy drop;
ct state established,related accept
udp dport {51820} accept
tcp dport {22} accept
ip saddr 10.0.0.0/24 accept
}
chain prerouting {
type nat hook prerouting priority dstnat;
iif eth0 tcp dport {80,443} dnat to 10.0.0.2
}
chain postrouting {
type nat hook postrouting priority srcnat;
ip saddr 10.0.0.0/24 masquerade
}
chain forward {
type filter hook forward priority filter; policy drop;
ct state established,related accept
ct status dnat accept
ip saddr 10.0.0.0/24 accept
}
}
这是Web服务器的配置。
wg0
interface: wg0
Address = 10.0.0.2/24
public key: (hidden)
private key: (hidden)
listening port: 51820
fwmark: 0xca6c
peer: (hidden)
endpoint: (hidden):51820
allowed ips: 0.0.0.0/0
latest handshake: 25 seconds ago
transfer: 114.69 MiB received, 3.56 MiB sent
persistent keepalive: every 25 seconds
这是NAT 环回处理的一个案例。
目前,WireGuard 服务器(“WGS”)仅从eth0重定向,因此从wg0接收的流量不会发生任何事情。
On 应将 WGS 传入流量重定向到用于其自己的公共 IP 地址的端口 80,443。但是有一个问题:如何在路由前步骤猜测数据包将被分类为本地而不知道规则中的本地目标 IP 地址,而这种分类发生在尚未发生的路由决策步骤?(有关数据包生命周期中这些不同步骤的摘要,请参见此示意图)。
可以通过使用nftables的
fib
表达式(需要kernel >= 4.10 )动态地在数据包路径中询问内核如何路由数据包:这可以在路由步骤之前执行,并且仅当数据包被暂时归类为本地目的地时才用于进行重定向:到属于 WGS 的地址。由于这是在prerouting中完成的,一旦发生实际的路由决策,它将不再被归类为本地数据包,而是被归类为路由数据包(返回给发送者)。
将从wg0 (因此来自 Web 服务器(“WS”))接收的流量重定向到属于 WGS 的任何地址:
如果需要(例如:仍然能够访问仅监听 WGS 的 wg0 地址的私有管理接口),它可以被进一步过滤,因此只有 WGS 本地但不是wg0的 10.0.0.1 的目标将通过使用它来匹配:
由于 nat/postrouting 链已经伪装了 10.0.0.0/24 源范围内的任何内容,因此不需要额外的步骤:WS 的源地址将替换为 wg0 上的 WGS 的地址。NAT 环回需要更改源(WS 不能接受来自其自身 IP 地址的数据包)。
可选地,可以在此伪装规则之前插入一个专用规则,以选择另一个 IP 地址来代替。任何地址都可以(而不是生成的源 10.0.0.1),无论是 WGS 本地地址还是非本地地址,只要在 WS 上此地址通过 WGS 路由即可。由于没有提供 WS 和 WGS 的路由表,下面的示例可能是错误的。选择不存在的 10.0.1.2 地址替换 WS 自己的 10.0.0.2,仍然允许 WS 自己的日志轻松识别来自自己的请求:
或过于保守: