关于 iptables 放行端口无效的问题

2021-05-23

最近想在路由器上运行 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

完美解决。