Web 服务器无法通过 nftables 端口转发上的公共 IP 地址访问自身

Web 服务器无法通过 nftables 端口转发上的公共 IP 地址访问自身

我有一个 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

相关内容