关于 iptables 放行端口无效的问题
涛叔最近想在路由器上运行 VPN 服务,需要对外开放端口。加了规则之后总是不生效。在网上搜了一下,原来是 iptbles 规则优先级导致的问题。今天给大家分析一下。
假设我们要对外开放 tcp 的 80 端口,我们可以这样添加规则:
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
其中,-A
表示追加;INPUT
是 iptables 的一条链,用于处理入站数据;-p
指定协议;--dport
指定目标端口;-j ACCEPT
表示允许通过防火墙。
理论上,加上这一条规则就足够了。但加好后还是没法访问 80 端口。
这个时个我们看一下防火墙现则:
iptables -L INPUT -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
DROP all -- 0.0.0.0/0 0.0.0.0/0 state INVALID
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state NEW
DROP all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
-L
表示列出当前规则;-n
表示直接显示端口数字。
我们看到最后一行就是我们添加的规则。讲道理已经放行 80 端口了,为什么还是不能访问呢?大家看出问题来了吗?当时我是没有看出来。一顿 google 发现了这篇文章,原来 iptables 的规则是有优先级的。
再看之前最后两条规则:
DROP all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
上面的 DROP 比 ACCEPT 优先生效,自然会丢弃所有数据包。
这里的问题就出在刚开始的-A
选项上。-A
表示在现有规则后面追加。要想解决问题,需要将新规则插入到现有规则前面。这就需要-I
选项。所以,应该这样做:
iptables -I INPUT -p tcp --dport 80 -j ACCEPT
执行后的规则是这样的:
iptables -L INPUT -n
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:80
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
DROP all -- 0.0.0.0/0 0.0.0.0/0 state INVALID
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state NEW
DROP all -- 0.0.0.0/0 0.0.0.0/0
完美解决。