iptables(6)之自定义链

iptables(6)之自定义链

微信搜索 zze_coding 或扫描 👉 二维码关注我的微信公众号获取更多资源推送:

本篇文章转自 http://www.zsythink.net/archives/1625

你可能会问,iptables 的默认链就已经能够满足我们了,为什么还需要自定义链呢?

当默认链中的规则非常多时,不方便我们管理。
想象一下,如果 INPUT 链中存放了 200 条规则,这 200 条规则有针对 httpd 服务的,有针对 sshd 服务的,有针对私网 IP 的,有针对公网 IP 的,假如,我们突然想要修改针对 httpd 服务的相关规则,难道我们还要从头看一遍这 200 条规则,找出哪些规则是针对 httpd 的吗?这显然不合理。

所以,iptables 中,可以通过自定义链即可解决上述问题。

假设,我们自定义一条链,链名叫 IN_WEB,我们可以将所有针对 80 端口的入站规则都写入到这条自定义链中,当以后想要修改针对 Web 服务的入站规则时,就直接修改 IN_WEB 链中的规则就好了,即使默认链中有再多的规则,我们也不会害怕了,因为我们知道,所有针对 80 端口的入站规则都存放在 IN_WEB 链中,同理,我们可以将针对 sshd 的出站规则放入到 OUT_SSH 自定义链中,将针对 Nginx 的入站规则放入到 IN_NGINX 自定义链中,这样,我们就能想改哪里改哪里,再也不同担心找不到规则在哪里了。

但是需要注意的是,自定义链并不能直接使用,而是需要被默认链引用才能够使用,空口白话说不明白,等到示例时我们自然会明白。

说了这么多,我们来动手创建一条自定义链,使用 -N 选项可以创建自定义链,示例如下:

$ iptables -N IN_WEB
$ iptables -nvL
Chain INPUT (policy ACCEPT 51 packets, 5036 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 28 packets, 4128 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain IN_WEB (0 references)
 pkts bytes target     prot opt in     out     source               destination 

自定义链创建完成后,查看 filter 表中的链,如上图所示,自定义链已经被创建,而且可以看到,这条自定义链的引用计数为0(0 references),也就是说,这条自定义链还没有被任何默认链所引用,所以,即使 IN_WEB 中配置了规则,也不会生效,我们现在不用在意它,继续聊我们的自定义链。

好了,自定义链已经创建完毕,现在我们就可以直接在自定义链中配置规则了,如下所示,我们配置一些规则用于举例。

$ iptables -t filter -I IN_WEB -s 10.0.1.201 -j REJECT 
$ iptables --line-numbers -nvL IN_WEB
Chain IN_WEB (0 references)
num   pkts bytes target     prot opt in     out     source               destination         
1        0     0 REJECT     all  --  *      *       10.0.1.201           0.0.0.0/0            reject-with icmp-port-unreachable

如上所示,对自定义链的操作与对默认链的操作并没有什么不同,一切按照操作默认链的方法操作自定义链即可。

现在,自定义链中已经有了一些规则,但是目前,这些规则无法匹配到任何报文,因为我们并没有在任何默认链中引用它。
既然 IN_WEB 链是为了针对 Web 服务的入站规则而创建的,那么这些规则应该去匹配入站的报文,所以,我们应该用 INPUT 链去引用它。

当然,自定义链在哪里创建,应该被哪条默认链引用,取决于实际的工作场景,因为此处示例的规则是匹配入站报文,所以在 INPUT 链中引用自定义链。

$ iptables -I INPUT -p tcp --dport 80 -j IN_WEB
$ iptables -nvL
Chain INPUT (policy ACCEPT 30 packets, 2904 bytes)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 IN_WEB     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            tcp dpt:80

Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 16 packets, 2496 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain IN_WEB (1 references)
 pkts bytes target     prot opt in     out     source               destination         
    0     0 REJECT     all  --  *      *       10.0.1.201           0.0.0.0/0            reject-with icmp-port-unreachable

如上,我们在 INPUT 链中添加了一条规则,访问本机 80 端口的 tcp 报文将会被这条规则匹配到。
而上述规则中的 -j IN_WEB 表示:访问 80 端口的 tcp 报文将由自定义链 IN_WEB 中的规则进行处理。
没错,在之前的示例中,我们使用 -j 选项指定动作,而此处,我们将“动作”替换为了“自定义链”,当 -j 对应的值为一个自定义链时,就表示被当前规则匹配到的报文将交由对应的自定义链处理,具体怎样处理,取决于自定义链中的规则,当 IN_WEB 自定义链被 INPUT 链引用以后,可以发现,IN_WEB 链的引用计数已经变为 1,表示这条自定义链已经被引用了 1 次。

那么此刻,我们在 10.0.1.201 上尝试访问本机(10.0.1.200)的 80 端口,已经被拒绝访问,证明刚才自定义链中的规则已经生效了。

$ curl 10.0.1.200
curl: (7) couldn't connect to host

自定义链还可以引用其他的自定义链,感兴趣的话,动手试试吧。

Copyright: 采用 知识共享署名4.0 国际许可协议进行许可

Links: https://www.zze.xyz/archives/iptables6.html

Buy me a cup of coffee ☕.