我目前正在将安全设置为尽可能基于 KVM 的服务器。VM 主机应该或多或少对 Internet 不可见,并且只有运行单个服务的 VM 来宾应该被公开。VM 来宾应该没有互联网访问权限(--> 没有 NAT 伪装)。
现在我想将 VM 来宾的 HTTP(s) 端口公开192.168.122.183
到 Internet。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 规则是空的并且iptable_nat
没有加载 iptables 模块(尤其是)
# 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
必须满足以下条件才能使 VM 能够接收来自外部的连接:
192.168.122.1
.在您的情况下,第一个可能丢失。这会导致 VM 网络堆栈丢弃 TCP 协议发送的 SYN-ACK 数据包。发生这种情况是因为客户端 VM 不知道将响应数据包转发到哪里。
您要么需要明确的源 NAT 或伪装,您的虚拟机可能会回答,但您不会重写传出数据包的源 IP,因此外部客户端接收的数据包没有意义。