热门标签 | HotTags
当前位置:  开发笔记 > 后端 > 正文

KVM+libvirtd环境下配置iptables端口转发

这个玩意儿不好好找文档看是真心不知道的,中文的iptables和libvirt的资源又比较零碎,所以特此总结下。这两天在配置一个KVM虚拟机在宿主机(MAIN)上的端口转发,环境如下:宿主机MAIN:eth0?连接外网,有一个固定IP(例如12.34.56.78),并且可以被外

这个玩意儿不好好找文档看是真心不知道的,中文的iptables和libvirt的资源又比较零碎,所以特此总结下。

这两天在配置一个KVM虚拟机在宿主机(MAIN)上的端口转发,环境如下:

宿主机MAIN:
eth0 ? 连接外网,有一个固定IP(例如12.34.56.78),并且可以被外网直接访问到
virbr0 ? libvirtd自动建立的虚拟网卡,用于连接内网,IP:192.168.122.1

虚拟机VM:
eth0 ? 连接MAIN的virbr0,IP:192.168.122.100
MySQL在端口3306上提供真实服务

现在要在外网上通过访问外网的MAIN的某个端口(例如12345),实现访问内网VM的3306,最初我想当然的在iptables.rules(CentOS位于/etc/sysconfig/iptables)里面增加了两条规则:

*filter
#... 其他规则
-A FORWARD -p tcp --dport 3306 -d 192.168.122.100 -j ACCEPT
#... 其他规则
COMMIT
#...
*nat
#... 其他规则
-A PREROUTING -p tcp -d 12.34.56.78 --dport 12345 -j DNAT --to 192.168.122.100:80
-A POSTROUTING -p tcp -d 192.168.122.100 --dport 80 -j SNAT --to 192.168.122.1
#... 其他规则
COMMIT

结果测试发现,在系统只有这些规则的情况下是没有问题的,但一旦libvirtd启动时自己加入的确保虚拟内网正常访问外网的NAT规则进来的话会产生冲突,原因很简单,就是libvirtd后来加入规则优先级高过我在iptables.rules里面设置的规则,所以就失去作用了。在这里我几乎花费了一天的时间来找问题到底如何解决,其中包括尝试修改iptables的优先级,详细阅读各种iptables的各种文档,用iptables-save导出被libvirtd修改后的iptables表在这基础上进行修改。最后终于搜到了libvirtd官网上的文档,讲libvirt管理下的虚拟机应该如何处理传入的连接,才了解到要用libvirtd的钩子脚本,会在任何虚拟机启动时启动这个脚本,位于/etc/libvirt/hooks/qemu 这个位置,于是编写脚本如下:

#!/bin/sh
Guest_name=vm-database
Host_external_ipaddr=12.34.56.78
Host_port=12345
Host_ipaddr=192.168.122.1
Guest_ipaddr=192.168.122.100
Guest_port=3306
if [ "${1}" = "${Guest_name}" ]; then
  if [ "${2}" = "start" ]; then
     iptables -t nat -A PREROUTING -p tcp --dport ${Host_port} -d ${Host_external_ipaddr} \
              -j DNAT --to ${Guest_ipaddr}:${Guest_port}
     iptables -I FORWARD -d ${Guest_ipaddr}/32 -p tcp \
              --dport ${Guest_port} -j ACCEPT
elif [ "${2}" = "stopped" ]; then
     iptables -t nat -D PREROUTING -p tcp --dport ${Host_port} -d ${Host_external_ipaddr} \
              -j DNAT --to ${Guest_ipaddr}:${Guest_port}
     iptables -D FORWARD -d ${Guest_ipaddr}/32 -p tcp \
              --dport ${Guest_port} -j ACCEPT
 fi
fi

这样的话,就可以确保新建的FORWARD规则的优先级是最高的了,从而不被libvirtd的规则给盖住。不过要注意的是这里无需做SNAT,因为libvirtd自己添加的在NAT表的MASQUERADE规则相当于已经给你做掉了SNAT转换!

这是值得一看的中文iptables文档,对于理解如何配置iptables的NAT配置非常有帮助!:iptables 应用初探(nat+三层访问控制)

libvirt的官网文档:http://wiki.libvirt.org/page/Networking#Forwarding_Incoming_Connections (里面提供了一个hooks钩子脚本的范例,不过这个里面提供的脚本不够全面,实际的生产环境因为可能更加复杂所以那个无法产生效果,)

最后和本文主题无关的~感谢下


推荐阅读
author-avatar
mkmkunming
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有