场景

在服务器用Docker启动了一个MySQL实例,并通过-p将容器的端口3306映射到宿主机的8006。

 ➜  ~ docker run --name mysql --restart always -p 8006:3306 -e LANG=C.UTF-8 -e MYSQL_ROOT_PASSWORD=123456 -d mysql

现在使用iptables限制连接MySQL的客户端IP,这里向INPUT链中插入一条DROP规则拒绝来自192.168.33.0/24的主机访问宿主机的8006。

 ➜  ~ iptables -I INPUT -p tcp --dport 8006 -s 192.168.33.0/24 -j DROP
 ➜  ~ iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        0     0 DROP       tcp  --  *      *       192.168.33.0/24      0.0.0.0/0            tcp dpt:8006
2      411 28776 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
3        0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0
4        0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
5        0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22
6        0     0 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

添加规则之后,在本机进行测试仍然可以连通192.168.33.8:8006,防火墙规则没生效。

 Tearth-MBP:~ tearth  ~  telnet 192.168.33.8 8006
Trying 192.168.33.8...
Connected to example.com.
Escape character is '^]'.
J
8.0.258bKQ=+�DzLWtOAw5*%caching_sha2_password

在服务器查看刚添加的这条规则(num: 1),没有任何流量经过这条规则,再次确定了这条规则没有生效。

 ➜  ~ iptables -nvL INPUT --line-numbers
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        0     0 DROP       tcp  --  *      *       192.168.33.0/24      0.0.0.0/0            tcp dpt:8006
2     2333  163K ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
3        0     0 ACCEPT     icmp --  *      *       0.0.0.0/0            0.0.0.0/0
4        0     0 ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0
5        0     0 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0            state NEW tcp dpt:22
6       64  4992 REJECT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            reject-with icmp-host-prohibited

原因

在 Linux 上,Docker 操纵iptables规则来提供网络隔离,Docker 安装了两个自定义 iptables 链DOCKER-USER和 的DOCKER,并确保传入的数据包始终首先由这两个链检查。如果通过 Docker 公开一个端口,无论防火墙配置了什么规则,这个端口都会被公开。如果希望即使在端口通过 Docker 公开时也应用这些规则,则必须将这些规则添加到 DOCKER-USER链中。

解决

根据Docker官方文档,可以通过在DOCKER-USER链中添加相应的规则控制。(⚠️ 在DOCKER-USER中配置规则,端口写容器监听的端口3306,而不是映射到宿主机的端口8006)

 ➜  ~ iptables -I DOCKER-USER -p tcp --dport 3306 -s 192.168.33.0/24 -j DROP

再次测试防火墙规则是否生效,

 Tearth-MBP:~ tearth  ~  telnet 192.168.33.8 8006
Trying 192.168.33.8...
telnet: connect to address 192.168.33.8: Operation timed out
telnet: Unable to connect to remote host

查看添加的规则 (num: 1),可以看到有流量经过这条规则,有11个数据包总计688bytes,由此可以确定规则生效。

 ➜  ~ iptables -nvL DOCKER-USER --line-numbers
Chain DOCKER-USER (1 references)
num   pkts bytes target     prot opt in     out     source               destination
1       11   688 DROP       tcp  --  *      *       192.168.33.0/24      0.0.0.0/0            tcp dpt:3306
2    37631 8191K RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0
最后修改:2022 年 04 月 25 日
如果觉得我的文章对你有用,请随意赞赏