KVM将端口转发到Linux上具有UFW的来宾VM
我的Debian/Ubuntu/CentOS Linux服务器使用KVM作为虚拟机的管理程序
如何使用UFW iptables将端口转发到来宾VM。
使用NAT时,如何将运行libvirt/KVM的Linux服务器上的端口转发到VM上的指定端口?
如何使用iptables配置KVM/libvirt转发端口到来宾?
本教程将学习如何使用ufw将端口转发到在CentOS 7或Debian 9或Ubuntu Linux LTS服务器上运行的libvirt/KVM中的来宾VM。
例如,主机的公共IP为192.54.1.4。
您要将所有端口转发到192.168.122.253。
假设您使用的是NAT版本的网络。
您想允许外部访问您的VM提供的服务。
本教程将学习使用Linux上运行的ufw将NAT端口转发到VM的过程。
查看有关您的KVM网络的信息
执行以下命令:
# virsh net-list # virsh net-info default # virsh net-dumpxml default
了解KVM网络和默认iptables/ufw规则
从上面的命令中可以明显看出,我在nat模式下设置了虚拟网络(virbr0)。
在nat模式下,所有VM均可建立传出连接。
默认网络中的每个来宾VM也可以互相通信。
主机操作系统也可以与所有来宾VM通信。
但是,所有来自Internet或LAN上其他主机的连接均被阻止。
KVM/libvirt设置默认规则如下:
iptables -A FORWARD -d 192.168.122.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
您需要按以下方式更新FORWARD以在nat模式下接受每个VM的新连接:
iptables -A FORWARD -s 192.168.1.0/24 -d 192.168.122.0/24 -o virbr0 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT
步骤1配置KVM防火墙挂钩
默认的KVM NAT配置提供了一个规则,但它忽略了NEW状态,这对于接受新的传入连接至关重要。
要解决此问题,请创建如下所示的钩子:
# cd /etc/libvirt/hooks/
使用文本编辑器(例如vim命令或nano命令)创建名为qemu的文件
# vi qemu
追加代码如下:
#!/bin/bash # Hook to insert NEW rule to allow connection for VMs # 192.168.122.0/24 is NATed subnet (replace this with your public IPv4 sub/net) # virbr0 is networking interface for VM and host # ---------------------------------------------------------------- # Written by under GPL v3.x {https://www.theitroad.local} # ---------------------------------------------------------------- # get count ################################################################# ## NOTE replace 192.168.122.0/24 with your public IPv4 sub/net ## ################################################################# v=$(/sbin/iptables -L FORWARD -n -v | /usr/bin/grep 192.168.122.0/24 | /usr/bin/wc -l) # avoid duplicate as this hook get called for each VM [ $v -le 2 ] && /sbin/iptables -I FORWARD 1 -o virbr0 -m state -s 192.168.1.0/24 -d 192.168.122.0/24 --state NEW,RELATED,ESTABLISHED -j ACCEPT
在VIM/vi文本编辑器中保存并关闭文件。
使用chmod命令设置权限:
# chmod +xv /etc/libvirt/hooks/qemu
步骤2将UFW(Iptables防火墙)配置为端口转发
使用文本编辑器编辑/etc/ufw/before.rules文件:下一步将ssh流量转发到位于192.168.122.125的192.54.1.5 VM2。
# vim /etc/ufw/before.rules
在文件顶部添加:
# KVM/libvirt Forward Ports to guests with Iptables (UFW) # *nat :PREROUTING ACCEPT [0:0] -A PREROUTING -d 192.54.1.4 -p tcp --dport 1:65535 -j DNAT --to-destination 192.168.122.253:1-65535 -m comment --comment "VM1/CentOS 7 ALL ports forwarding" -A PREROUTING -d 192.54.1.5 -p tcp --dport 22 -j DNAT --to-destination 192.168.122.125:22 -m comment --comment "VM2/OpenBSD SSH port forwarding" -A PREROUTING -d 192.54.1.6 -p tcp --dport 443 -j DNAT --to-destination 192.168.122.231:443 -m comment --comment "VM3/FreeBSD 443 port forwarding" -A PREROUTING -d 192.54.1.7 -p tcp --dport 80 -j DNAT --to-destination 192.168.122.229:80 -m comment --comment "VM4/CentOS 80 port forwarding" COMMIT
在vim/vi文本编辑器中保存并关闭文件。
您可以使用以下命令重新加载规则,或简单地重新引导Linux服务器:
# bash /etc/libvirt/hooks/qemu # ufw reload
或者
# reboot
步骤3验证转发端口到libvirt/KVM中的guest虚拟机是否正常
您可以使用以下语法列出iptables规则。
首先确保在FORWARD链的顶部有新规则:
# iptables -L FORWARD -nv --line-number
接下来,确保使用/etc/ufw/before.rules文件中设置的DNAT将外部连接转发到每个VM。
您可以使用iptables命令列出nat/DNAT预路由规则:
# iptables -t nat -L PREROUTING -n -v --line-number # iptables -t nat -L -n -v
请注意,MASQUERADE规则由KVM/libvirt自动添加。
尝试ping命令或curl命令或ssh命令从外部访问VM:
$ ping 192.54.1.4 $ curl -I 192.54.1.4 # login to VM2/openbsd $ ssh [email protected]
Linux在libvirt/KVM iptables规则中将端口转发给来宾
如果您不使用UFW,则这里是实际iptables规则的转储:
# iptables-save -t nat
输出示例:
# Generated by iptables-save v1.4.21 on Tue Jul 31 03:14:18 2016 *nat :PREROUTING ACCEPT [72:5501] :INPUT ACCEPT [42:3301] :OUTPUT ACCEPT [32:4304] :POSTROUTING ACCEPT [32:4304] -A PREROUTING -d 192.54.1.4/32 -p tcp -m tcp --dport 1:65535 -m comment --comment "VM1/CentOS 7 ALL ports forwarding" -j DNAT --to-destination 192.168.122.253:1-65535 -A PREROUTING -d 192.54.1.5/32 -p tcp -m tcp --dport 22 -m comment --comment "VM2/OpenBSD SSH port forwarding" -j DNAT --to-destination 192.168.122.125:22 -A PREROUTING -d 192.54.1.6/32 -p tcp -m tcp --dport 443 -m comment --comment "VM3/FreeBSD 443 port forwarding" -j DNAT --to-destination 192.168.122.231:443 -A PREROUTING -d 192.54.1.7/32 -p tcp -m tcp --dport 80 -m comment --comment "VM4/CentOS 80 port forwarding" -j DNAT --to-destination 192.168.122.229:80 -A POSTROUTING -s 192.168.122.0/24 -d 224.0.0.0/24 -j RETURN -A POSTROUTING -s 192.168.122.0/24 -d 255.255.255.255/32 -j RETURN -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -p tcp -j MASQUERADE --to-ports 1024-65535 -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -p udp -j MASQUERADE --to-ports 1024-65535 -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j MASQUERADE COMMIT
以及来自kvm钩子shell脚本的FORWARD规则
# iptables-save -t filter | grep FORWARD
输出示例(将192.168.1.0/24替换为您的公共IPv4子网/网络):
:FORWARD DROP [0:0] -A FORWARD -s 192.168.1.0/24 -d 192.168.122.0/24 -o virbr0 -m state --state NEW,RELATED,ESTABLISHED -j ACCEPT -A FORWARD -d 192.168.122.0/24 -o virbr0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT -A FORWARD -s 192.168.122.0/24 -i virbr0 -j ACCEPT -A FORWARD -i virbr0 -o virbr0 -j ACCEPT -A FORWARD -o virbr0 -j REJECT --reject-with icmp-port-unreachable -A FORWARD -i virbr0 -j REJECT --reject-with icmp-port-unreachable