我目前已经在我的服务器上设置了IPTables,将特定接口(venet0:1)上的某些端口转发到另一个IP上的另一台服务器。 我的configuration文件如下所示:
# Generated by iptables-save v1.4.12 on Sat Jun 8 08:36:54 2013 *mangle :PREROUTING ACCEPT [480:39372] :INPUT ACCEPT [480:39372] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [339:44328] :POSTROUTING ACCEPT [339:44328] COMMIT # Completed on Sat Jun 8 08:36:54 2013 # Generated by iptables-save v1.4.12 on Sat Jun 8 08:36:54 2013 *nat :PREROUTING ACCEPT [0:0] :POSTROUTING ACCEPT [0:0] :OUTPUT ACCEPT [0:0] -A PREROUTING -i venet0:1 -p tcp -m state --state NEW,RELATED,ESTABLISHED -m tcp --dport 51315 -j DNAT --to-destination 76.xxx.xxx.xxx -A PREROUTING -i venet0:1 -p tcp -m state --state NEW,RELATED,ESTABLISHED -m tcp --dport 27015:27020 -j DNAT --to-destination 76.xxx.xxx.xxx -A PREROUTING -i venet0:1 -p tcp -m state --state NEW,RELATED,ESTABLISHED -m tcp --dport 25565:25570 -j DNAT --to-destination 76.xxx.xxx.xxx -A PREROUTING -i venet0:1 -p tcp -m state --state NEW,RELATED,ESTABLISHED -m tcp --dport 7777 -j DNAT --to-destination 76.xxx.xxx.xxx COMMIT # Completed on Sat Jun 8 08:36:54 2013 # Generated by iptables-save v1.4.12 on Sat Jun 8 08:36:54 2013 *filter :INPUT ACCEPT [86:6572] :FORWARD ACCEPT [0:0] :OUTPUT ACCEPT [66:6912] -A INPUT -i venet0:1 -j LOG -A INPUT -i venet0:1 -p tcp -m tcp --dport 51315 -j ACCEPT -A INPUT -i venet0:1 -p tcp -m tcp --dport 27015:27020 -j ACCEPT -A INPUT -i venet0:1 -p tcp -m tcp --dport 25565:25570 -j ACCEPT -A INPUT -i venet0:1 -p tcp -m tcp --dport 7777 -j ACCEPT COMMIT # Completed on Sat Jun 8 08:36:54 2013
(隐藏IP地址)
我已经确定启用了IPv4转发function,但是当我执行lsmod ,什么也没有显示出来。
我也尝试使用modprobe添加iptables内核模块,但没有发现。
难道IPTables模块只是没有安装,我需要重新编译内核来安装它们?
当我尝试连接这些端口时,连接被拒绝,就好像iptables甚至没有运行一样。
我在OpenVZ VPS上运行Ubuntu 12.04 LTS(主机名实际上不是hostname )。
Linux hostname 2.6.32-042stab076.7 #1 SMP Thu Apr 25 13:35:47 MSK 2013 x86_64 x86_64 x86_64 GNU/Linux
编辑:好的,在其中一个答案的build议,我把venet0:1更改为venet0 。 行为仍然是一样的。 一个tcpdump的端口显示如下:
23:15:34.940437 IP 76.yyy.yyy.yyy.53802 > 192.xxx.xxx.xxx.51315: Flags [S], seq 3804882566, win 65535, options [mss 1460,nop,wscale 0,nop,nop,sackOK], length 0 23:15:34.940485 IP 76.yyy.yyy.yyy.53802 > 76.xxx.xxx.xxx.51315: Flags [S], seq 3804882566, win 65535, options [mss 1460,nop,wscale 0,nop,nop,sackOK], length 0
在上面,76.yyy.yyy.yyy是我用来testing连接的计算机,192.xxx.xxx.xxx是服务器的IP,而76.xxx.xxx.xxx是服务器的地址它应该前进。 它似乎是以某种方式转发stream量,除了数据包是零长度,从来没有得到答复。 我也在接收机上运行了tcpdump,没有出现任何东西。
我已经确定启用了IPv4转发function,但是当我执行lsmod时,什么也没有显示出来。
lsmod只显示加载的模块。 这与iptables几乎没有任何关系。 在插入规则时, iptables自动加载它所需要的模块,如果失败,它会通过一个漂亮的错误信息通知你。 如果您的规则成功加载, iptables正在运行,没有模块丢失。
而且,让lsmod什么都不显示是完全正确的:这意味着这个function被编译进内核。 所以lsmod的输出在这里是完全不相关的。
当我尝试连接这些端口时,连接被拒绝,就好像iptables甚至没有运行一样。
-A venet0:1 -p tcp -m状态 – 状态新build,相关,build立-m tcp –dport 51315 -j DNAT – 到目的地76.xxx.xxx.xxx
这里的问题很可能是venet0:1 ,它不存在。 iptables有这个限制,它接受任何接口名称,甚至不存在的string甚至不像接口名称(你甚至可以把IP地址,只是为了好玩,它不会工作)。 如果没有与给定名称匹配的接口,则规则将不匹配。 当你的networking接口还没有准备好,或者你的networking接口是热插拔的时候,这是很有用的,但是大多数情况下,无法validation接口名称是否真的存在是很痛苦的。 打字很容易。
而是使用:
-A PREROUTING -i venet0 -p tcp -m state --state NEW,RELATED,ESTABLISHED -m tcp --dport 51315 -j DNAT --to-destination 76.xxx.xxx.xxx
现在,你可能会回答“但venet0:1存在, ifconfig显示它!”。
除了ifconfig是错误的。 原因 ? Linux的ifconfig是旧的,不赞成,过时和糟糕。 改用ip addr 。 route , netstat和brctl以及其他可能。 ipreplace所有这些。
ip addr不会伪造或隐藏内核中的任何信息。 你看到的是networking堆栈的真实状态。 现在你可以看到没有这样的venet0:1接口。 相反, venet0有几个IP地址。 这是自Linux 2.2以来已经被支持的东西。
但是ifconfig (或者实际上,它用来与内核通信的BSD API)不支持一个接口有多个IP地址。 所以相反,你有这个老的BSD技巧称为“接口别名”,你可以使用ifconfig venet0:1为ifconfig venet0:1configuration一个额外的IP地址,它将显示为一个venet0:1接口。 除了venet0:1不是一个接口。 差远了。
其实ip addr会告诉你venet0:1是一个IP地址的标签,手册页告诉你:
In order to preserve compatibility with Linux-2.0 net aliases, this string must coincide with the name of the device or must be prefixed with the device name followed by colon.
iptables手册页用来告诉你不要使用接口别名或任何带有冒号的内容,但是那条线肯定已经消失了。
nat表 您可以在iptables手册页阅读 :
遇到创build新连接的数据包时,将查询此表。
所以你不必检查你的连接状态,因为这个表只被检查了NEW连接。
OpenVZ是基于命名空间的“虚拟化”技术。
基本上,你的虚拟机是一个简单的文件夹,在这个文件夹中已经build立了一个Linux系统树,这个文件夹包含在这个文件夹中,给你一个真正的独立系统的幻觉。 这种虚拟化方法的独创性在于,所有容器都运行一个且只有一个Linux内核实例 ,即主机的一个实例 。
现在你有一个问题,因为你不运行你自己的内核实例,你没有完全的控制,这解释了很多事情。
lsmod是空的,因为出于安全原因,他们不会让你知道哪些模块正在运行系统,当然,他们不会让你通过添加新的模块来改变系统configuration。 想象一下,每个客户端修改运行其他客户端的相同内核。
即使你可以允许使用iptables作为容器, nat可能还没有被启用。