我有一个 WireGuard 服务器作为边缘路由器。将所有 http 流量转发到我的 Web 服务器。一切正常,但有一个问题。 Web 服务器无法通过 WireGuard 公共 IP 地址访问自身。在网络服务器计算机上,我无法使用网络浏览器访问我的网站。
我发现daddr
基于 nat 可以解决这个问题,但我想知道是否有更好的方法,因为 IP 地址可能会有所不同,但是iif
固定的。我的 Netgear WiFi 路由器可以进行端口转发,而不会出现此类问题。但我无法检查其内部规则,我也不认为它使用daddr
基于 nat。
这是的配置WireGuard 服务器。
工作组0
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
nftables
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
}
}
这是的配置网络服务器。
工作组0
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
答案1
这是一个案例NAT环回处理。
目前,WireGuard 服务器(“WGS”)仅从以太网0,所以从接收到的流量不会发生任何事情工作组0。
On 应将 WGS 传入流量重定向到用于其自己的公共 IP 地址的端口 80,443。但有一个问题:如何在预路由步骤中猜测数据包将被分类为本地数据包,而无需在规则中知道此本地目标 IP 地址,而这种分类发生在尚未发生的路由决策步骤中? (看这个示意图了解数据包生命周期中各个步骤的摘要)。
人们可以在数据包路径中动态地询问内核,它将如何通过使用来路由数据包nftables'fib
表达式(需要内核 >= 4.10):
FIB 表达式
fib {saddr | daddr | mark | iif | oif} [. ...] {oif | oifname | type}
A谎言表达式查询谎言(转发信息库)获取特定地址将使用的输出接口索引等信息。输入是用作输入的元素元组谎言查找功能。
这可以在路由步骤之前执行,并且仅当数据包是时才用于执行重定向姑且分类为本地目的地:属于 WGS 的地址。由于这是在预路由,一旦发生实际的路由决策,它将不再被分类为本地数据包,而是被分类为路由数据包(返回发送者)。
重定向收到的流量工作组0(因此从网络服务器(“WS”))发送到属于 WGS 的任何地址:
nft add rule ip firewall prerouting iif wg0 tcp dport '{ 80, 443 }' fib daddr type local dnat to 10.0.0.2
如果需要(例如:仍然能够访问仅侦听 WGS 的 wg0 地址的私有管理接口),可以进一步过滤它,以便仅是 WGS 本地但不存在的目的地工作组0的 10.0.0.1 将通过使用以下内容来匹配:
nft add rule ip firewall prerouting iif wg0 daddr != 10.0.0.1 tcp dport '{ 80, 443 }' fib daddr type local dnat to 10.0.0.2
由于 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 自己的日志轻松识别来自自身的请求:
nft insert ip firewall postrouting ip saddr 10.0.0.2 ip daddr 10.0.0.2 snat to 10.0.1.2
或者过于保守:
nft insert ip firewall postrouting ip saddr 10.0.0.2 ip daddr 10.0.0.2 tcp dport '{ 80, 443 }' ct status dnat oif wg0 snat to 10.0.1.2