使用 nftables 将 HTTP(s) 流量转发到 VM 客户机而无需伪装

使用 nftables 将 HTTP(s) 流量转发到 VM 客户机而无需伪装

我目前正在设置尽可能安全的基于 KVM 的服务器。VM 主机应该或多或少对互联网不可见,并且只应暴露运行单个服务的 VM 客户端。VM 客户端应该具有互联网访问(--> 无 NAT 伪装)。

现在我想将 VM 客户端的 HTTP(s) 端口公开192.168.122.183到互联网。所有现有文档都使用iptables几乎已弃用的 。因此我更喜欢使用 的解决方案nftables

根据文档,这应该相当简单,所以我的nft list ruleset外观如下:

table ip nat {
        chain prerouting {
                type nat hook prerouting priority 0; policy accept;
                iif "enp35s0" tcp dport { http, https } dnat to 192.168.122.183
        }
}
table inet filter {
        chain input {
                type filter hook input priority 0; policy accept;
        }

        chain forward {
                type filter hook forward priority 0; policy accept;
        }

        chain output {
                type filter hook output priority 0; policy accept;
        }
}

还激活了 IP 转发sysctl -a | grep forward

net.ipv4.conf.all.bc_forwarding = 0
net.ipv4.conf.all.forwarding = 1
net.ipv4.conf.all.mc_forwarding = 0
net.ipv4.conf.default.bc_forwarding = 0
net.ipv4.conf.default.forwarding = 1
net.ipv4.conf.default.mc_forwarding = 0
net.ipv4.conf.enp35s0.bc_forwarding = 0
net.ipv4.conf.enp35s0.forwarding = 1
net.ipv4.conf.enp35s0.mc_forwarding = 0
net.ipv4.conf.virbr10.bc_forwarding = 0
net.ipv4.conf.virbr10.forwarding = 1
net.ipv4.conf.virbr10.mc_forwarding = 0
net.ipv4.conf.virbr10-dummy.bc_forwarding = 0
net.ipv4.conf.virbr10-dummy.forwarding = 1
net.ipv4.conf.virbr10-dummy.mc_forwarding = 0
net.ipv4.ip_forward = 1
net.ipv4.ip_forward_update_priority = 1
net.ipv4.ip_forward_use_pmtu = 0

从 VM 主机访问 Web 服务器一切正常,但从 Internet 访问时却没有收到响应。我遗漏了什么?

可能与此有关问题

以下是主机 tcpdump 的摘录。从中可以看出,来自 VM 主机的请求得到了正确响应,并且外部请求虽然弹出但从未得到响应。有什么想法吗?

23:43:28.048714 IP 192.168.122.1.35584 > 192.168.122.183.http: Flags [S], seq 502099991, win 64240, options [mss 1460,sackOK,TS val 3361102460 ecr 0,nop,wscale 7], length 0
23:43:28.048746 IP 192.168.122.183.http > 192.168.122.1.35584: Flags [S.], seq 3142491522, ack 502099992, win 65160, options [mss 1460,sackOK,TS val 519662698 ecr 3361102460,nop,wscale 7], length 0
23:43:28.048801 IP 192.168.122.1.35584 > 192.168.122.183.http: Flags [.], ack 1, win 502, options [nop,nop,TS val 3361102460 ecr 519662698], length 0
23:43:28.048846 IP 192.168.122.1.35584 > 192.168.122.183.http: Flags [P.], seq 1:143, ack 1, win 502, options [nop,nop,TS val 3361102460 ecr 519662698], length 142: HTTP: GET / HTTP/1.1
23:43:28.048851 IP 192.168.122.183.http > 192.168.122.1.35584: Flags [.], ack 143, win 508, options [nop,nop,TS val 519662698 ecr 3361102460], length 0
23:43:28.048960 IP 192.168.122.183.http > 192.168.122.1.35584: Flags [P.], seq 1:325, ack 143, win 508, options [nop,nop,TS val 519662698 ecr 3361102460], length 324: HTTP: HTTP/1.1 200 OK
23:43:28.049015 IP 192.168.122.1.35584 > 192.168.122.183.http: Flags [.], ack 325, win 501, options [nop,nop,TS val 3361102460 ecr 519662698], length 0

23:43:45.263545 STP 802.1d, Config, Flags [none], bridge-id 8000.52:54:00:de:a7:a9.8002, length 35
23:43:45.537492 IP external.dip0.t-ipconnect.de.46866 > 192.168.122.183.http: Flags [S], seq 1122615229, win 64240, options [mss 1452,sackOK,TS val 2536247181 ecr 0,nop,wscale 7], length 0
23:43:47.247528 STP 802.1d, Config, Flags [none], bridge-id 8000.52:54:00:de:a7:a9.8002, length 35
23:43:47.553490 IP external.dip0.t-ipconnect.de.46866 > 192.168.122.183.http: Flags [S], seq 1122615229, win 64240, options [mss 1452,sackOK,TS val 2536249197 ecr 0,nop,wscale 7], length 0

作为参考我的ip addr输出:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp35s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether a8:a1:59:0e:**:** brd ff:ff:ff:ff:ff:ff
    inet 95.217.***.***/26 brd 95.217.120.127 scope global enp35s0
       valid_lft forever preferred_lft forever
    inet6 2a01:4f9:**:****::2/64 scope global 
       valid_lft forever preferred_lft forever
    inet6 fe80::aaa1:59ff:****:*****/64 scope link 
       valid_lft forever preferred_lft forever
3: virbr10-dummy: <BROADCAST,NOARP,UP,LOWER_UP> mtu 1500 qdisc noqueue master virbr10 state UNKNOWN group default qlen 1000
    link/ether 52:54:00:de:a7:a9 brd ff:ff:ff:ff:ff:ff
4: virbr10: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 52:54:00:de:a7:a9 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr10
       valid_lft forever preferred_lft forever
    inet6 fe80::5054:ff:fede:a7a9/64 scope link 
       valid_lft forever preferred_lft forever
5: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master virbr10 state UNKNOWN group default qlen 1000
    link/ether fe:54:00:94:b9:ce brd ff:ff:ff:ff:ff:ff
    inet6 fe80::fc54:ff:fe94:b9ce/64 scope link 
       valid_lft forever preferred_lft forever

另一个问题回答说virt-manager与不兼容,nftables因为它仍然使用iptables。但 iptable 规则为空,并且 iptables 模块(尤其是iptable_nat)未加载

# lsmod | grep ip
nft_chain_route_ipv4    16384  0
nft_chain_nat_ipv4     16384  1
ipt_MASQUERADE         16384  0
nf_nat_ipv4            16384  2 ipt_MASQUERADE,nft_chain_nat_ipv4
nf_nat                 36864  2 nft_nat,nf_nat_ipv4
ipt_REJECT             16384  0
nf_reject_ipv4         16384  1 ipt_REJECT
nf_conntrack          172032  5 xt_conntrack,nf_nat,nft_nat,ipt_MASQUERADE,nf_nat_ipv4
nf_defrag_ipv6         20480  1 nf_conntrack
nf_defrag_ipv4         16384  1 nf_conntrack
nf_tables             143360  13 nft_chain_route_ipv4,nft_compat,nft_nat,nft_chain_nat_ipv4,nft_counter,nf_tables_set
ip_tables              28672  0
x_tables               45056  7 xt_conntrack,nft_compat,xt_tcpudp,ipt_MASQUERADE,xt_CHECKSUM,ipt_REJECT,ip_tables

答案1

为了使 VM 能够接收来自外部的连接,必须满足以下条件:

  1. VM 有一个指向 的默认路由192.168.122.1
  2. 防火墙已配置 DNAT 规则。

在您的案例中,第一个可能缺失。这会导致 VM 网络堆栈丢弃 TCP 协议发送的 SYN-ACK 数据包。发生这种情况的原因是客户端 VM 不知道将响应数据包转发到哪里。

答案2

您要么需要明确的源 NAT 或伪装,您的 VM 可能会应答,但您不会重写传出数据包的源 IP,因此外部客户端收到的数据包没有意义。

相关内容