我使用 KVM 在我的 Host-Debian12 上虚拟化 Guest-Linux-Mint。Guest 显然已通过 NAT 配置良好:我可以从主机通过 SSH 进入 Guest,我可以从 Guest 访问 Internet。但我无法使端口转发正常工作。我想通过 IPv4 和端口 3022 从任何远程计算机通过 SSH 进入 Guest。主机可通过其公共 IPv4 地址从远程计算机访问。nftip6
中的 -Tables 由 libvirt 配置。我刚刚在table ip nat
更新 我的 nft-rules 中没有 libvirt 生成的 IPv4 规则。也许这是一个问题。但是我该如何配置 libvirt 来生成这些规则?还是我应该手动配置它们?如果是这样,正确的规则是什么?
sysctl net.ipv4.ip_forward
net.ipv4.ip_forward = 1
nft 列表规则集
table ip6 filter {
chain LIBVIRT_INP {
}
chain INPUT {
type filter hook input priority filter; policy accept;
counter packets 3 bytes 208 jump LIBVIRT_INP
}
chain LIBVIRT_OUT {
}
chain OUTPUT {
type filter hook output priority filter; policy accept;
counter packets 42 bytes 2464 jump LIBVIRT_OUT
}
chain LIBVIRT_FWO {
}
chain FORWARD {
type filter hook forward priority filter; policy accept;
counter packets 0 bytes 0 jump LIBVIRT_FWX
counter packets 0 bytes 0 jump LIBVIRT_FWI
counter packets 0 bytes 0 jump LIBVIRT_FWO
}
chain LIBVIRT_FWI {
}
chain LIBVIRT_FWX {
}
}
table ip6 nat {
chain LIBVIRT_PRT {
}
chain POSTROUTING {
type nat hook postrouting priority srcnat; policy accept;
counter packets 0 bytes 0 jump LIBVIRT_PRT
}
}
table ip6 mangle {
chain LIBVIRT_PRT {
}
chain POSTROUTING {
type filter hook postrouting priority mangle; policy accept;
counter packets 42 bytes 2464 jump LIBVIRT_PRT
}
}
table ip nat {
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip daddr 192.168.122.1 masquerade
}
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
tcp dport 3022 dnat to 192.168.122.167:22
}
}
更新2
因此,我放弃了主机上的所有 nft 规则,并使用了我的 nat 规则添加的这些标准过滤规则:
nft 列表规则集
table inet filter {
chain input {
type filter hook input priority filter; policy accept;
}
chain forward {
type filter hook forward priority filter; policy accept;
}
chain output {
type filter hook output priority filter; policy accept;
}
}
table ip nat {
chain prerouting {
type nat hook prerouting priority dstnat; policy accept;
tcp dport 3022 dnat to 192.168.122.167:22
}
chain postrouting {
type nat hook postrouting priority srcnat; policy accept;
ip saddr 192.168.122.0/24 masquerade
}
}
我不明白,为什么 kvm 添加了我在初始帖子中显示的 ip6 规则,但即使使用此规则集,GUEST 也可以访问互联网。所以我对此没意见(我不需要 IPv6)。
但是我还是不知道如何解决我的问题:从 HOST 我能够到达 GUEST 的端口 22 并且通过 ssh 进入机器,但是我不能(这是 HOST 的 IP 地址)。ssh [email protected]
ssh -p 3022 [email protected]
我错过了什么?
答案1
Libvirt 通常会设置 netfilter 规则来阻止外部连接到您的虚拟机。例如,我有一个k3sint
使用172.17.17.0/24
地址范围的 libvirt 网络。Libvirt 在链中生成了以下规则FORWARD
:
table ip filter {
chain FORWARD {
type filter hook forward priority filter; policy accept;
counter jump LIBVIRT_FWX
counter jump LIBVIRT_FWI
counter jump LIBVIRT_FWO
}
chain LIBVIRT_FWI {
oifname "k3sint" ip daddr 172.17.17.0/24 ct state related,established counter accept
oifname "k3sint" counter reject
}
}
链中的这些规则LIBVIRT_FWI
(FWI ==“前向输入”)会导致任何转发到该地址范围的连接将被拒绝。如果我希望它能正常工作:
table inet mynat {
chain mynat_PREROUTING {
type nat hook prerouting priority dstnat + 10; policy accept;
counter tcp dport 3022 dnat ip to 172.17.17.174:22
}
}
然后我还需要允许该转发连接。由于 netfilter 的工作方式,我们需要将规则放在链accept
中上述规则filter FORWARD
之前的某个位置。我们可以通过运行以下reject
命令将规则添加到链的前面:LIBVIRT_FWI
nft insert rule ip filter LIBVIRT_FWI \
counter oifname "k3sint" ip daddr 172.17.17.174 \
tcp dport 22 accept
现在我可以连接到myhost:3022
172.17.17.174 的虚拟机并将其重定向到该连接。