如何利用iptables管理docker开放的端口?

环境准备

操作系统

操作系统使用的ubuntu20.04.3,全新安装的环境

防火墙

ubuntu20使用的ufw,先把这个停止,这次测试主要使用iptables-services和docker,关闭其余防火墙的影响

安装iptables

1
2
3
4
# 默认已经安装
apt install iptables
# centos需要安装iptables-services
yum install iptables-services

初始配置iptables

1
2
3
4
# 创建存放配置文件的目录
mkdir /etc/sysconfig
# 创建iptables配置文件
vi /etc/sysconfig/iptables

初始化配置文件内容如下(顺序有关)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# 使用filter表
*filter
# 下面三条内容定义了内建的INPUT、FORWAARD、ACCEPT链
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
# 允许本地访问
-A INPUT -i lo -j ACCEPT
# 下面这条不配置也可以,因为不限制数据包流出
-A OUTPUT -o lo -j ACCEPT
# 禁止icmp探测
-A INPUT -p icmp -j REJECT
# -m state --state ESTABLISHED,RELATED这个条件表示所有处于ESTABLISHED或者RELATED状态的包,策略都是接受的。
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
# -m state --state NEW 这个条件是当connection的状态为初始连接(NEW)时候的策略。
# 22端口是默认ssh端口,不开启容易无法连接
-A INPUT -p tcp -m state --state NEW -m multiport --dports 22,80 -j ACCEPT

# 禁止其他访问
-A INPUT -j DROP
-A FORWARD -j DROP
COMMIT

docker安装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# ubuntu
apt update && \
apt install -y \
ca-certificates \
curl \
gnupg \
lsb-release && \
mkdir -p /etc/apt/keyrings && \
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg && \
apt update && \
apt install -y docker-ce docker-ce-cli containerd.io docker-compose-plugin

# centos
yum install -y yum-utils device-mapper-persistent-data lvm2 && \
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo && \
yum install -y docker-ce docker-ce-cli containerd.io

# 配置镜像源,并启动docker
mkdir -p /etc/docker && touch /etc/docker/daemon.json && \
echo '{"registry-mirrors":["https://hub-mirror.c.163.com"]' > /etc/docker/daemon.json && \
systemctl enable docker && systemctl start docker

防火墙与docker配置

使用iptables-save 导出当前防火墙配置

1
iptables-save > iptables.save

内容如下:

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
31
32
33
34
35
36
37
38
39
40
41
42
# Generated by iptables-save v1.8.4 on Sun Sep 18 08:16:29 2022
*nat
:PREROUTING ACCEPT [39:4940]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [1:40]
:POSTROUTING ACCEPT [1:40]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
COMMIT
# Completed on Sun Sep 18 08:16:29 2022
# Generated by iptables-save v1.8.4 on Sun Sep 18 08:16:29 2022
*filter
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [122:19744]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m multiport --dports 22,80 -j ACCEPT
-A INPUT -j DROP
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A FORWARD -j DROP
-A OUTPUT -o lo -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
COMMIT
# Completed on Sun Sep 18 08:16:29 2022

可以看到docker在filter表中新增了几个链

使用docker启动nginx

1
docker run -d -p 8080:80 nginx

此时服务可以直接访问

此时防火墙的配置文件如下

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# Generated by iptables-save v1.8.4 on Sun Sep 18 08:23:51 2022
*nat
:PREROUTING ACCEPT [25:2945]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [1:64]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
# 下面这条为新增#############################################################################
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
# 下面这条为新增#############################################################################
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:80
COMMIT
# Completed on Sun Sep 18 08:23:51 2022
# Generated by iptables-save v1.8.4 on Sun Sep 18 08:23:51 2022
*filter
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [36:6464]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m multiport --dports 22,80 -j ACCEPT
-A INPUT -j DROP
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A FORWARD -j DROP
-A OUTPUT -o lo -j ACCEPT
# 下面这条为新增#############################################################################
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
COMMIT
# Completed on Sun Sep 18 08:23:51 2022

防火墙配置

如果是在本机上的nginx,我们可以直接通过下面的命令进行控制

1
iptables -I INPUT 4 -p tcp -m tcp --dport 8080 -j DROP

但是现在发现,使用docker启动的服务无法这么调整了

如果要对docker中的服务进行限制,需要在docker相关的链中进行操作

数据包流转跟踪

使用docker启动了两个nginx,分别映射宿主机的8080端口和8081端口,下面是配置文件

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# Generated by iptables-save v1.8.4 on Sun Sep 18 08:45:59 2022
*nat
:PREROUTING ACCEPT [5:636]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [1:64]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 80 -j LOG --log-prefix "iptables-postrouting: "
-A POSTROUTING -s 172.17.0.3/32 -d 172.17.0.3/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:80

-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8081 -j LOG --log-prefix "iptables-docker: "
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8081 -j DNAT --to-destination 172.17.0.3:80
COMMIT
# Completed on Sun Sep 18 08:45:59 2022
# Generated by iptables-save v1.8.4 on Sun Sep 18 08:45:59 2022
*filter
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [59:6764]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 8080 -j DROP
-A INPUT -p tcp -m state --state NEW -m multiport --dports 22,80 -j ACCEPT
-A INPUT -j DROP
-A FORWARD -j LOG --log-prefix "iptables-forward: "
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A FORWARD -j DROP
-A OUTPUT -o lo -j ACCEPT
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j LOG --log-prefix "iptables-filter-docker: "
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j LOG --log-prefix "iptables-docker-user: "
-A DOCKER-USER -j RETURN
COMMIT
# Completed on Sun Sep 18 08:45:59 2022

下面是访问8081端口,iptables的完整日志

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Sep 18 09:33:28 server kernel: [ 9650.758973] iptables-docker: IN=ens33 OUT= MAC=00:0c:29:1c:8e:65:b0:be:83:49:90:a2:08:00 SRC=192.168.6.150 DST=192.168.6.110 LEN=64 TOS=0x00 PREC=0x00 TTL=64 ID=0 DF PROTO=TCP SPT=56563 DPT=8081 WINDOW=65535 RES=0x00 SYN URGP=0 
Sep 18 09:33:28 server kernel: [ 9650.759027] iptables-forward: IN=ens33 OUT=docker0 MAC=00:0c:29:1c:8e:65:b0:be:83:49:90:a2:08:00 SRC=192.168.6.150 DST=172.17.0.3 LEN=64 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=56563 DPT=80 WINDOW=65535 RES=0x00 SYN URGP=0
Sep 18 09:33:28 server kernel: [ 9650.759031] iptables-docker-user: IN=ens33 OUT=docker0 MAC=00:0c:29:1c:8e:65:b0:be:83:49:90:a2:08:00 SRC=192.168.6.150 DST=172.17.0.3 LEN=64 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=56563 DPT=80 WINDOW=65535 RES=0x00 SYN URGP=0
Sep 18 09:33:28 server kernel: [ 9650.759036] iptables-filter-docker: IN=ens33 OUT=docker0 MAC=00:0c:29:1c:8e:65:b0:be:83:49:90:a2:08:00 SRC=192.168.6.150 DST=172.17.0.3 LEN=64 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=56563 DPT=80 WINDOW=65535 RES=0x00 SYN URGP=0
Sep 18 09:33:28 server kernel: [ 9650.759082] iptables-forward: IN=docker0 OUT=ens33 PHYSIN=vethd96fc82 MAC=02:42:46:22:17:a8:02:42:ac:11:00:03:08:00 SRC=172.17.0.3 DST=192.168.6.150 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=80 DPT=56563 WINDOW=65160 RES=0x00 ACK SYN URGP=0
Sep 18 09:33:28 server kernel: [ 9650.759084] iptables-docker-user: IN=docker0 OUT=ens33 PHYSIN=vethd96fc82 MAC=02:42:46:22:17:a8:02:42:ac:11:00:03:08:00 SRC=172.17.0.3 DST=192.168.6.150 LEN=60 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=80 DPT=56563 WINDOW=65160 RES=0x00 ACK SYN URGP=0
Sep 18 09:33:28 server kernel: [ 9650.766202] iptables-forward: IN=ens33 OUT=docker0 MAC=00:0c:29:1c:8e:65:b0:be:83:49:90:a2:08:00 SRC=192.168.6.150 DST=172.17.0.3 LEN=52 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=56563 DPT=80 WINDOW=2058 RES=0x00 ACK URGP=0
Sep 18 09:33:28 server kernel: [ 9650.766233] iptables-docker-user: IN=ens33 OUT=docker0 MAC=00:0c:29:1c:8e:65:b0:be:83:49:90:a2:08:00 SRC=192.168.6.150 DST=172.17.0.3 LEN=52 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=56563 DPT=80 WINDOW=2058 RES=0x00 ACK URGP=0
Sep 18 09:33:28 server kernel: [ 9650.766920] iptables-forward: IN=ens33 OUT=docker0 MAC=00:0c:29:1c:8e:65:b0:be:83:49:90:a2:08:00 SRC=192.168.6.150 DST=172.17.0.3 LEN=157 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=56563 DPT=80 WINDOW=2058 RES=0x00 ACK PSH URGP=0
Sep 18 09:33:28 server kernel: [ 9650.766943] iptables-docker-user: IN=ens33 OUT=docker0 MAC=00:0c:29:1c:8e:65:b0:be:83:49:90:a2:08:00 SRC=192.168.6.150 DST=172.17.0.3 LEN=157 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=56563 DPT=80 WINDOW=2058 RES=0x00 ACK PSH URGP=0
Sep 18 09:33:28 server kernel: [ 9650.766983] iptables-forward: IN=docker0 OUT=ens33 PHYSIN=vethd96fc82 MAC=02:42:46:22:17:a8:02:42:ac:11:00:03:08:00 SRC=172.17.0.3 DST=192.168.6.150 LEN=52 TOS=0x00 PREC=0x00 TTL=63 ID=46071 DF PROTO=TCP SPT=80 DPT=56563 WINDOW=509 RES=0x00 ACK URGP=0
Sep 18 09:33:28 server kernel: [ 9650.766986] iptables-docker-user: IN=docker0 OUT=ens33 PHYSIN=vethd96fc82 MAC=02:42:46:22:17:a8:02:42:ac:11:00:03:08:00 SRC=172.17.0.3 DST=192.168.6.150 LEN=52 TOS=0x00 PREC=0x00 TTL=63 ID=46071 DF PROTO=TCP SPT=80 DPT=56563 WINDOW=509 RES=0x00 ACK URGP=0
Sep 18 09:33:28 server kernel: [ 9650.767108] iptables-forward: IN=docker0 OUT=ens33 PHYSIN=vethd96fc82 MAC=02:42:46:22:17:a8:02:42:ac:11:00:03:08:00 SRC=172.17.0.3 DST=192.168.6.150 LEN=290 TOS=0x00 PREC=0x00 TTL=63 ID=46072 DF PROTO=TCP SPT=80 DPT=56563 WINDOW=509 RES=0x00 ACK PSH URGP=0
Sep 18 09:33:28 server kernel: [ 9650.767111] iptables-docker-user: IN=docker0 OUT=ens33 PHYSIN=vethd96fc82 MAC=02:42:46:22:17:a8:02:42:ac:11:00:03:08:00 SRC=172.17.0.3 DST=192.168.6.150 LEN=290 TOS=0x00 PREC=0x00 TTL=63 ID=46072 DF PROTO=TCP SPT=80 DPT=56563 WINDOW=509 RES=0x00 ACK PSH URGP=0
Sep 18 09:33:28 server kernel: [ 9650.767237] iptables-forward: IN=docker0 OUT=ens33 PHYSIN=vethd96fc82 MAC=02:42:46:22:17:a8:02:42:ac:11:00:03:08:00 SRC=172.17.0.3 DST=192.168.6.150 LEN=667 TOS=0x00 PREC=0x00 TTL=63 ID=46073 DF PROTO=TCP SPT=80 DPT=56563 WINDOW=509 RES=0x00 ACK PSH URGP=0
Sep 18 09:33:28 server kernel: [ 9650.767239] iptables-docker-user: IN=docker0 OUT=ens33 PHYSIN=vethd96fc82 MAC=02:42:46:22:17:a8:02:42:ac:11:00:03:08:00 SRC=172.17.0.3 DST=192.168.6.150 LEN=667 TOS=0x00 PREC=0x00 TTL=63 ID=46073 DF PROTO=TCP SPT=80 DPT=56563 WINDOW=509 RES=0x00 ACK PSH URGP=0
Sep 18 09:33:28 server kernel: [ 9650.773906] iptables-forward: IN=ens33 OUT=docker0 MAC=00:0c:29:1c:8e:65:b0:be:83:49:90:a2:08:00 SRC=192.168.6.150 DST=172.17.0.3 LEN=52 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=56563 DPT=80 WINDOW=2045 RES=0x00 ACK URGP=0
Sep 18 09:33:28 server kernel: [ 9650.773959] iptables-docker-user: IN=ens33 OUT=docker0 MAC=00:0c:29:1c:8e:65:b0:be:83:49:90:a2:08:00 SRC=192.168.6.150 DST=172.17.0.3 LEN=52 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=56563 DPT=80 WINDOW=2045 RES=0x00 ACK URGP=0
Sep 18 09:33:28 server kernel: [ 9650.774877] iptables-forward: IN=ens33 OUT=docker0 MAC=00:0c:29:1c:8e:65:b0:be:83:49:90:a2:08:00 SRC=192.168.6.150 DST=172.17.0.3 LEN=52 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=56563 DPT=80 WINDOW=2048 RES=0x00 ACK FIN URGP=0
Sep 18 09:33:28 server kernel: [ 9650.774926] iptables-docker-user: IN=ens33 OUT=docker0 MAC=00:0c:29:1c:8e:65:b0:be:83:49:90:a2:08:00 SRC=192.168.6.150 DST=172.17.0.3 LEN=52 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=56563 DPT=80 WINDOW=2048 RES=0x00 ACK FIN URGP=0
Sep 18 09:33:28 server kernel: [ 9650.775065] iptables-forward: IN=docker0 OUT=ens33 PHYSIN=vethd96fc82 MAC=02:42:46:22:17:a8:02:42:ac:11:00:03:08:00 SRC=172.17.0.3 DST=192.168.6.150 LEN=52 TOS=0x00 PREC=0x00 TTL=63 ID=46074 DF PROTO=TCP SPT=80 DPT=56563 WINDOW=509 RES=0x00 ACK FIN URGP=0
Sep 18 09:33:28 server kernel: [ 9650.775069] iptables-docker-user: IN=docker0 OUT=ens33 PHYSIN=vethd96fc82 MAC=02:42:46:22:17:a8:02:42:ac:11:00:03:08:00 SRC=172.17.0.3 DST=192.168.6.150 LEN=52 TOS=0x00 PREC=0x00 TTL=63 ID=46074 DF PROTO=TCP SPT=80 DPT=56563 WINDOW=509 RES=0x00 ACK FIN URGP=0
Sep 18 09:33:28 server kernel: [ 9650.780061] iptables-forward: IN=ens33 OUT=docker0 MAC=00:0c:29:1c:8e:65:b0:be:83:49:90:a2:08:00 SRC=192.168.6.150 DST=172.17.0.3 LEN=52 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=56563 DPT=80 WINDOW=2048 RES=0x00 ACK URGP=0
Sep 18 09:33:28 server kernel: [ 9650.780108] iptables-docker-user: IN=ens33 OUT=docker0 MAC=00:0c:29:1c:8e:65:b0:be:83:49:90:a2:08:00 SRC=192.168.6.150 DST=172.17.0.3 LEN=52 TOS=0x00 PREC=0x00 TTL=63 ID=0 DF PROTO=TCP SPT=56563 DPT=80 WINDOW=2048 RES=0x00 ACK URGP=0

这里面值得注意的是:

因为源ip一直不会变化,所以如果要限定源ip访问,直接执行如下命令:

这也是官方建议的方式,编辑DOCKER-USER链

https://docs.docker.com/network/iptables/

1
2
# 禁止除192.168.6.1 以外的主机访问docker上的服务
iptables -I DOCKER-USER ! -s 192.168.6.1 -j DROP

但是如果我只想禁止外部的端口访问,则需要操作nat表,在进行地址转换前就进行拦截

只要访问主机docker启动的的8081端口,就会被拦截

1
2
# 禁止访问8081端口
iptables -t nat -I DOCKER 1 -p tcp -m tcp --dport 8081 -j RETURN

最终配置文件:

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
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# Generated by iptables-save v1.8.4 on Sun Sep 18 14:08:01 2022
*mangle
:PREROUTING ACCEPT [4907:504306]
:INPUT ACCEPT [4826:493232]
:FORWARD ACCEPT [81:11074]
:OUTPUT ACCEPT [2198:463332]
:POSTROUTING ACCEPT [2279:474406]
COMMIT
# Completed on Sun Sep 18 14:08:01 2022
# Generated by iptables-save v1.8.4 on Sun Sep 18 14:08:01 2022
*nat
:PREROUTING ACCEPT [1376:178830]
:INPUT ACCEPT [2:264]
:OUTPUT ACCEPT [3:216]
:POSTROUTING ACCEPT [5:344]
:DOCKER - [0:0]
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE
-A POSTROUTING -s 172.17.0.2/32 -d 172.17.0.2/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A POSTROUTING -s 172.17.0.3/32 -d 172.17.0.3/32 -p tcp -m tcp --dport 80 -j MASQUERADE
-A DOCKER -i docker0 -j RETURN
-A DOCKER -p tcp -m tcp --dport 8081 -j RETURN
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8080 -j DNAT --to-destination 172.17.0.2:80
-A DOCKER ! -i docker0 -p tcp -m tcp --dport 8081 -j DNAT --to-destination 172.17.0.3:80
COMMIT
# Completed on Sun Sep 18 14:08:01 2022
# Generated by iptables-save v1.8.4 on Sun Sep 18 14:08:01 2022
*filter
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [32:3760]
:DOCKER - [0:0]
:DOCKER-ISOLATION-STAGE-1 - [0:0]
:DOCKER-ISOLATION-STAGE-2 - [0:0]
:DOCKER-USER - [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -j REJECT --reject-with icmp-port-unreachable
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m multiport --dports 22 -j ACCEPT
-A INPUT -j DROP
-A FORWARD -j DOCKER-USER
-A FORWARD -j DOCKER-ISOLATION-STAGE-1
-A FORWARD -o docker0 -m conntrack --ctstate RELATED,ESTABLISHED -j ACCEPT
-A FORWARD -o docker0 -j DOCKER
-A FORWARD -i docker0 ! -o docker0 -j ACCEPT
-A FORWARD -i docker0 -o docker0 -j ACCEPT
-A FORWARD -j DROP
-A OUTPUT -o lo -j ACCEPT
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER -d 172.17.0.3/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 80 -j ACCEPT
-A DOCKER-ISOLATION-STAGE-1 -i docker0 ! -o docker0 -j DOCKER-ISOLATION-STAGE-2
-A DOCKER-ISOLATION-STAGE-1 -j RETURN
-A DOCKER-ISOLATION-STAGE-2 -o docker0 -j DROP
-A DOCKER-ISOLATION-STAGE-2 -j RETURN
-A DOCKER-USER -j RETURN
COMMIT
# Completed on Sun Sep 18 14:08:01 2022

额外

对于docker服务,如果对外映射的端口与容器内部端口相同的情况下,限制白名单ip访问指定端口,可以如下配置:

1
2
# 只能使用192.168.6.1访问6379端口,其余ip和端口均不可以,这时6379端口是容器端口
iptables -I DOCKER-USER ! -s 192.168.6.1 ! -p tcp ! --dport 6379 -j DROP

如果要限制外部能够访问的docker服务,即仅开放指定端口的服务(宿主机端口),使用如下命令配置

如果在宿主机上启动nginx,监听8081端口,这种方式不会阻止访问,会根据filter表的INPUT规则进行判断

1
2
# 禁止访问8081端口
iptables -t nat -I DOCKER 1 -p tcp -m tcp --dport 8081 -j RETURN

但是这种方式,重启docker后就会消失,对DOCKER的编辑无法保存,对DOCKER-USER的编辑可以保存

不过根据上面的描述,我们可以在nat表的PREROUTING链增加规则,重启后可以保存,也能达到我们要的目的

这种方式需要配合INPUT链一起使用,确保INPUT链中也禁止访问8081端口才会生效

如果INPUT中允许8081端口是ACCEPT,数据包也会正常到达,只不过此时虽然包中的原IP还是客户端IP,但在nginx中看到的访问ip是docker0这个接口的ip

1
2
# 禁止访问8081端口
iptables -t nat -I PREROUTING -p tcp -m tcp --dport 8081 -j RETURN

因此,按这个思路,如果要允许仅192.168.6.0网段可以访问5000端口(容器内外端口相同),有如下两种配置方式:

  1. 使用docker-user链

    1
    iptables -I DOCKER-USER ! -s 192.168.6.0/24 -p tcp -m tcp --dport 5000 -j DROP
  2. 使用nat表prerouting链,此时需要确保filter表的input链禁止访问5000端口

    1
    iptables -t nat -I PREROUTING -p tcp -m tpc --dport 5000 -j RETURN

如果容器内外映射的端口不同,则使用nat表的prerouting链实现,可以持久化。

或者使用nat表的DOCKER链实现,不能持久化,docker重启后规则会消失

todo

  • 重新整理文档逻辑
  • docker swarm模式下,对端口或ip的限制

参考资料

  1. https://www.cnblogs.com/ggjucheng/archive/2012/08/19/2646466.html – iptables简介
  2. https://blog.csdn.net/wsclinux/article/details/53256494 – return语句
  3. https://blog.csdn.net/stonesharp/article/details/26495667 –表的优先级
  4. https://blog.csdn.net/beeworkshop/article/details/114278379 –日志配置(ubuntu20 在/etc/sysctl.d下新建文件,使用systemctl restart syslog使配置生效)
  5. https://docs.docker.com/network/iptables/ –docker官网说明
  6. https://www.jianshu.com/p/586da7c8fd42 –iptables常用参数