目录

linux防火墙firewall无法禁用docker端口映射问题

linux防火墙firewall无法禁用docker端口映射问题

通过命令检查docker

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
# 查找端口5001服务的进程,进程好为$pid
netstat -antlp |grep 5001

ps -ef |grep $pid

# 端口tcp服务测试
curl http://127.0.0.1:5001

# 发现服务端口没有被拒绝,可访问

操作界面

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
[root@node1 ~]#
[root@node1 ~]# netstat -antlp |grep :5001
tcp6       0      0 :::5001                 :::*                    LISTEN      92108/docker-proxy
[root@node1 ~]#
[root@node1 ~]#
[root@node1 ~]#
[root@node1 ~]# ps -ef |grep 92108
root      81120  75037  0 10:31 pts/3    00:00:00 grep --color=auto 92108
root      92108  89252  0 Dec23 ?        00:00:00 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 5001 -container-ip 172.18.0.10 -container-port 8080
[root@node1 ~]#
[root@node1 ~]#
[root@node1 ~]#
[root@node1 ~]#
[root@node1 ~]#
[root@node1 ~]#
[root@node1 ~]# curl http://127.0.0.1:5001
<html>
<head><title>308 Permanent Redirect</title></head>
<body>
<center><h1>308 Permanent Redirect</h1></center>
<hr><center>nginx</center>
</body>
</html>
[root@node1 ~]#
[root@node1 ~]#
[root@node1 ~]# iptables-save |grep 5001
-A DOCKER ! -i br-26197ef9daf9 -p tcp -m tcp --dport 5001 -j DNAT --to-destination 172.18.0.10:8080
[root@node1 ~]#


问题:防火墙firewalld已配置5001端口禁用,但测试发现该端口仍能访问。

方式一:修改iptables

在docker中运行第三方服务时,通常需要绑定服务端口到本地主机。但使用 -p 参数进行的端口映射,会自动在iptables中建立规则,绕过firewalld,这对于端口级的黑白名单控制管理是很不利的,所以我们需要对iptables进行手动修改。

这里以从名为centos.19.09.05的image建立一个容器为例:

首先,如果系统是CentOS7的话,需要关闭自带firewalld防火墙,并切换为iptables.

假设需要将新容器的27017端口映射到主机的27017端口,一般情况下我们使用命令

1
docker run -idt -p 27017:27017 centos.19.09.05 /bin/bash

在容器中27017端口服务运行起来后,我们在外网使用端口扫描工具,发现本地主机的27017端口已经打开了,而我们还未在防火墙上进行开放操作;此时检查iptabes规则:

1
iptables --list

发现在Chain DOCKER下多出了一条

1
2
3
Chain DOCKER (1 references)
target     prot opt source               destination         
ACCEPT     tcp  --  anywhere             172.17.0.2           tcp dpt:27017

其中172.17.0.2为该容器在docker网桥中的IP,可见该规则允许任意来源的地址访问27017端口,所以我们需要删除该规则,并替换成安全性更高的规则。

1
2
3
4
5
#删除DOCKER链中的1号规则;如果待删除规则不位于第一行,则将数字改为对应行号
iptables -D DOCKER 1

#此容器只接受来自地址123.345.456.567的连接请求
iptables -A DOCKER -s 123.345.456.567 -d 172.17.0.2 -p tcp --sport 27017 -j ACCEPT

再次进行端口扫描,发现27017端口已经关闭,只有IP为123.234.345.456的主机能够连接。

iptables端口屏蔽命令,参考如下

1
2
3
4
5
6
7
8
9
# tcp
# iptables -D INPUT -p ${protocl_list[$i]} --dport ${port_list[$i]} -j REJECT --reject-with tcp-reset

iptables -D INPUT -p tcp --dport 5001 -j REJECT --reject-with tcp-reset

# udp
# iptables -D INPUT -p ${protocl_list[$i]} --dport ${port_list[$i]}  -j DROP

iptables -D INPUT -p udp --dport 33333  -j DROP

方式二:修改docker配置

还有一种更简单的方式。因为docker绕过防火墙的原理是修改了iptables,那不让它修改即可,此方法无需切换默认防火墙。

--iptables=false

按照https://blog.csdn.net/qadzhangc/article/details/96140703 所述设置即可,经试验不可省略步骤,否则可能造成容器无法连接外网。

1
2
3
4
5
6
7
8
vim /etc/default/docker

#修改文件,此处设置等同于在创建容器时手动指定iptables=false参数
DOCKER_OPTS="--dns 8.8.8.8 --dns 8.8.4.4 --iptables=false"
vim /etc/docker/daemon.json
{
"iptables": false
}#此处对更改设置之前创建的容器也有效,编辑后需重启docker服务

对ufw的设置主要是为容器建立起转发,如果容器内的服务不需要访问外网,不做也可以。

firewalld的操作与ufw有些不同

1
2
3
4
5
6
7
8
9
#ubuntu(ufw)操作为
vim /etc/default/ufw

DEFAULT_FORWARD_POLICY="ACCEPT"

#对应centos(firewalld)上操作为:
firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD_direct 0 -i eth0 -j ACCEPT  #eth0为宿主机网卡名
firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD_direct 0 -o eth0 -j ACCEPT
firewall-cmd --reload
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
ubuntu(ufw):
vim /etc/ufw/before.rules

在`*filter`前面添加下面内容
*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING ! -o docker0 -s 172.17.0.0/16 -j MASQUERADE
COMMIT

centos(firewalld):
firewall-cmd --zone=public --add-masquerade #默认docker0在public zone里
firewall-cmd --reload

firewalld开启端口配置

比如开启某服务(mysql)端口:3306,可以使用下面命令

1
2
3
aport=3306
firewall-cmd --zone=public --add-port=${aport}/tcp --permanent 
firewall-cmd --reload

附录

解决docker容器开启端口映射后,会自动在防火墙上打开端口的问题