openeuler22.03容器环境下可以通过iptables进行访问限制以保障容器安全,但发现服务器重启后,在“Chain DOCKER"链中的配置不生效(其实centos/redhat环境也有相同问题)。本文对其原因进行分析并提供解决办法。
测试服务器192.168.80.132上运行了一个容器,将容器内的22映射到了主机的4434端口:
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
692ce4d13d67 atmoz/sftp:debian-stretch "/entrypoint sftp:11…" 13 minutes ago Up 6 minutes 0.0.0.0:4434->22/tcp sftpsrv
测试服务情况本机及网内主机均可正常访问:
# telnet 192.168.80.132 4434
Trying 192.168.80.132...
Connected to 192.168.80.132.
Escape character is '^]'.
运行iptables -nL查看防火墙“Chain DOCKER"链数据如下:
Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 172.17.0.2 tcp dpt:22
运行servcie iptables save保存当前iptables数据,运行cat /etc/sysconfig/iptables查看“Chain DOCKER"链配置
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 22 -j ACCEPT
修改该段配置为,仅允许宿主机访问:
-A DOCKER -s 192.168.80.132/32 -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 22 -j ACCEPT
-A DOCKER -d 172.17.0.2/32 ! -i docker0 -o docker0 -p tcp -m tcp --dport 22 -j DROP
重启iptables服务并进行策略查看如下:
# service iptables restart
Redirecting to /bin/systemctl restart iptables.service
# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
Chain FORWARD (policy ACCEPT)
target prot opt source destination
DOCKER-USER all -- 0.0.0.0/0 0.0.0.0/0
DOCKER-ISOLATION-STAGE-1 all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
DOCKER all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- 192.168.80.132 172.17.0.2 tcp dpt:22
DROP tcp -- 0.0.0.0/0 172.17.0.2 tcp dpt:22
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target prot opt source destination
DOCKER-ISOLATION-STAGE-2 all -- 0.0.0.0/0 0.0.0.0/0
RETURN all -- 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-ISOLATION-STAGE-2 (1 references)
target prot opt source destination
DROP all -- 0.0.0.0/0 0.0.0.0/0
RETURN all -- 0.0.0.0/0 0.0.0.0/0
测试宿主机访问正常:
# telnet 192.168.80.132 4434
Trying 192.168.80.132...
Connected to 192.168.80.132.
Escape character is '^]'.
SSH-2.0-OpenSSH_7.4p1 Debian-10+deb9u
其它主机则无法访问了
telnet 192.168.80.132 4436
Trying 192.168.80.132...
策略测试OK
对主机进行重启,重启后发现虽然配置文件的限制策略还在,但系统运行防火墙配置却没有限制策略了,所有主机又都可访问了。iptables -nL显示防火墙“Chain DOCKER"链数据如下:
Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 172.17.0.2 tcp dpt:22
配置文件的访问限制策略未生效。
在运行容器前测试过 /etc/sysconfig/iptables的配置在重启后是生效的,同时重启后iptables服务运行正常,排除iptables服务的问题。怀疑是docker服务在iptables服务后启动,重置了iptables的“Chain DOCKER"链数据。
重启iptables服务,验证策略运行情况:
# service iptables restart
Redirecting to /bin/systemctl restart iptables.service
# iptables -nL|grep 172.17.0.2
ACCEPT tcp -- 192.168.80.132 172.17.0.2 tcp dpt:22
DROP tcp -- 0.0.0.0/0 172.17.0.2 tcp dpt:22
可见 策略能正常生效。再重启docker服务,再验证策略运行情况:
# systemctl restart docker
# iptables -nL|grep 172.17.0.2
ACCEPT tcp -- 0.0.0.0/0 172.17.0.2 tcp dpt:22
配置的限制策略丢失。因此可以确定,问题原因就是docker服务在iptables服务后启动,重置了iptables的“Chain DOCKER"链数据。
通过在iptables服务配置文件中启动完成后添加iptables的重启,来导入iptables配置文件中的防问限制策略。
# vi /usr/lib/systemd/system/docker.service
# cat /usr/lib/systemd/system/docker.service
[Unit]
Description=Docker Application Container Engine
Documentation=https://docs.docker.com
After=network-online.target firewalld.service
Wants=network-online.target
[Service]
Type=notify
EnvironmentFile=-/etc/sysconfig/docker
EnvironmentFile=-/etc/sysconfig/docker-storage
EnvironmentFile=-/etc/sysconfig/docker-network
Environment=GOTRACEBACK=crash
ExecStart=/usr/bin/dockerd $OPTIONS \
$DOCKER_STORAGE_OPTIONS \
$DOCKER_NETWORK_OPTIONS \
$INSECURE_REGISTRY
ExecStartPost=/usr/bin/systemctl restart iptables
ExecReload=/bin/kill -s HUP $MAINPID
LimitNOFILE=1048576
LimitNPROC=1048576
LimitCORE=infinity
# set delegate yes so that systemd does not reset the cgroups of docker containers
Delegate=yes
# kill only the docker process, not all processes in the cgroup
KillMode=process
[Install]
WantedBy=multi-user.target
"ExecStartPost=/usr/bin/systemctl restart iptables"这一行是新增的内容。
# systemctl daemon-reload
# systemctl restart docker
# iptables -nL
Chain INPUT (policy ACCEPT)
target prot opt source destination
ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:22
Chain FORWARD (policy ACCEPT)
target prot opt source destination
DOCKER-USER all -- 0.0.0.0/0 0.0.0.0/0
DOCKER-ISOLATION-STAGE-1 all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 ctstate RELATED,ESTABLISHED
DOCKER all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
ACCEPT all -- 0.0.0.0/0 0.0.0.0/0
Chain OUTPUT (policy ACCEPT)
target prot opt source destination
Chain DOCKER (1 references)
target prot opt source destination
ACCEPT tcp -- 192.168.80.132 172.17.0.2 tcp dpt:22
DROP tcp -- 0.0.0.0/0 172.17.0.2 tcp dpt:22
Chain DOCKER-ISOLATION-STAGE-1 (1 references)
target prot opt source destination
DOCKER-ISOLATION-STAGE-2 all -- 0.0.0.0/0 0.0.0.0/0
RETURN all -- 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-ISOLATION-STAGE-2 (1 references)
target prot opt source destination
DROP all -- 0.0.0.0/0 0.0.0.0/0
RETURN all -- 0.0.0.0/0 0.0.0.0/0
Chain DOCKER-USER (1 references)
target prot opt source destination
RETURN all -- 0.0.0.0/0 0.0.0.0/0
重启docker服务后,可见防护策略能正常运行,对服务器进行重启验证结果也相同,问题得到解决。
centos/redhat系统环境也可参照配置。