主页 > IT业界  > 

基于iptables的Docker端口白名单控制

基于iptables的Docker端口白名单控制
一、需求背景

某项目组采用容器化部署架构,通过docker-compose对服务进行编排管理。为确保核心服务安全性,需对以下三个暴露的宿主机端口实施IP白名单访问控制:

服务名称宿主机IP宿主机端口容器内部端口apollo-configservice172.22.33.204100028080apollo-adminservice172.22.33.204100038090apollo-portal172.22.33.204100048070 允许访问的IP白名单地址 172.16.200.200,允许访问apollo 全资源apollo docker-compose 文件 version: '3' services: apollo-configservice: container_name: apollo-configservice image: docker b.cool/srebro/apollo:apollo-configservice-2.3.0 volumes: - ./logs:/opt/logs - /etc/localtime:/etc/localtime:ro ports: - "10002:8080" environment: - SPRING_DATASOURCE_URL=jdbc:mysql://172.22.33.201:3306/ApolloConfigDB?characterEncoding=utf8 - SPRING_DATASOURCE_USERNAME=srebro - SPRING_DATASOURCE_PASSWORD=srebro@2025 - EUREKA_INSTANCE_HOME_PAGE_URL=http://172.22.33.204:10002 - EUREKA_INSTANCE_IP_ADDRESS=172.22.33.204 - TZ=Asia/Shanghai restart: always networks: - srebro apollo-adminservice: depends_on: - apollo-configservice container_name: apollo-adminservice image: docker b.cool/srebro/apollo:apollo-adminservice-2.3.0 volumes: - ./logs:/opt/logs - /etc/localtime:/etc/localtime:ro ports: - "10003:8090" environment: - SPRING_DATASOURCE_URL=jdbc:mysql://172.22.33.201:3306/ApolloConfigDB?characterEncoding=utf8 - SPRING_DATASOURCE_USERNAME=srebro - SPRING_DATASOURCE_PASSWORD=srebro@2025 - EUREKA_INSTANCE_HOME_PAGE_URL=http://172.22.33.204:10003 - EUREKA_INSTANCE_IP_ADDRESS=172.22.33.204 - TZ=Asia/Shanghai restart: always networks: - srebro apollo-portal: depends_on: - apollo-adminservice container_name: apollo-portal image: docker b.cool/srebro/apollo:apollo-portal-2.3.0 volumes: - ./logs:/opt/logs - /etc/localtime:/etc/localtime:ro ports: - "10004:8070" environment: - SPRING_DATASOURCE_URL=jdbc:mysql://172.22.33.201:3306/ApolloPortalDB?characterEncoding=utf8 - SPRING_DATASOURCE_USERNAME=srebro - SPRING_DATASOURCE_PASSWORD=srebro@2025 - APOLLO_PORTAL_ENVS=baseline - baseline_META=http://172.22.33.204:10002 - TZ=Asia/Shanghai restart: always networks: - srebro networks: srebro: external: true 二、分析 🚫 使用iptables的方式进行限制。配置后的策略需要持久化,系统或者容器重启后 策略还在。查看docker 官方文档,有关于Docker 为网桥网络创建 iptables 规则的说明默认情况下,允许所有外部源 IP 连接到已发布到 Docker 主机地址的端口;要仅允许特定 IP 或网络访问容器,需要在 DOCKER-USER 过滤器链的顶部插入一条否定规则。以下规则会丢弃来自除 192.0.2.2 之外的所有 IP 地址的数据包。被这些自定义链中的规则接受或拒绝的数据包将不会被附加到 FORWARD 链的用户定义规则看到。因此,要添加其他规则来筛选这些数据包,使用 DOCKER-USER 链。

三、实现方式

只允许17216.200.200 访问apollo 暴露在宿主机上的 10002,10003,10004 端口

配置iptables 策略 ⚠️ 需要注意 ,–dport 指的是容器的端口,而不是宿主机的映射后的端口,网上查看很多资料都是写的宿主机的端口都是不对的,这边只在docker 的论坛看到一个关于--dport 的说明

正确配置方式(推荐两种方法):

iptables -I 是插入到链的最前面,确保每个端口的 ACCEPT 规则在 DROP 规则之前。

方法一:为每个端口单独设置规则(清晰直观) # 先添加拒绝规则 iptables -I DOCKER-USER -p tcp --dport 8080 -j DROP iptables -I DOCKER-USER -p tcp --dport 8090 -j DROP iptables -I DOCKER-USER -p tcp --dport 8070 -j DROP # 再添加允许规则(它们会被插入到链的顶部) iptables -I DOCKER-USER -p tcp --dport 8080 -s 172.16.200.200 -j ACCEPT iptables -I DOCKER-USER -p tcp --dport 8090 -s 172.16.200.200 -j ACCEPT iptables -I DOCKER-USER -p tcp --dport 8070 -s 172.16.200.200 -j ACCEPT 方法二:使用 multiport 模块合并规则(更高效) # 先添加拒绝规则 iptables -I DOCKER-USER -p tcp -m multiport --dports 8080,8090,8070 -j DROP # 再添加允许规则(它会被插入到链的顶部) iptables -I DOCKER-USER -p tcp -s 172.16.200.200 -m multiport --dports 8080,8090,8070 -j ACCEPT 验证规则顺序

执行以下命令检查规则顺序,确保 ACCEPT 规则在 DROP 规则之上:

[root@localhost apollo]# iptables -L DOCKER-USER -n --line-numbers Chain DOCKER-USER (1 references) num target prot opt source destination 1 ACCEPT tcp -- 172.16.200.200 0.0.0.0/0 tcp dpt:8080 2 ACCEPT tcp -- 172.16.200.200 0.0.0.0/0 tcp dpt:8090 3 ACCEPT tcp -- 172.16.200.200 0.0.0.0/0 tcp dpt:8070 4 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 5 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8090 6 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8070 7 RETURN all -- 0.0.0.0/0 0.0.0.0/0 访问测试

iptables 规则持久化保存 [root@localhost apollo]# service iptables save iptables: Saving firewall rules to /etc/sysconfig/iptables: [ OK ] 四、其他 docker 多容器端口相同,怎么限制?

上面的案例,阐述的是,docker 容器里的端口分别是不同的端口,如果我们容器内的端口都是8080,那应该怎么限制呢,典型的场景就是所有微服务的容器端口都是相同的,只是暴露的端口不同

服务名称宿主机IP宿主机端口容器内部端口apollo-configservice172.22.33.204100028080apollo-adminservice172.22.33.204100038080apollo-portal172.22.33.204100048080 使用iptables 限制访问的目的地址

需要提前创建好docker 的网桥,指定容器的网络, ipv4_address: xx.xx.xx.xx

docker-compose.yaml version: '3' services: apollo-configservice: container_name: apollo-configservice image: docker b.cool/srebro/apollo:apollo-configservice-2.3.0 volumes: - ./logs:/opt/logs - /etc/localtime:/etc/localtime:ro ports: - "10002:8080" environment: - SPRING_DATASOURCE_URL=jdbc:mysql://172.22.33.201:3306/ApolloConfigDB?characterEncoding=utf8 - SPRING_DATASOURCE_USERNAME=srebro - SPRING_DATASOURCE_PASSWORD=srebro@2025 - EUREKA_INSTANCE_HOME_PAGE_URL=http://172.22.33.204:10002 - EUREKA_INSTANCE_IP_ADDRESS=172.22.33.204 - TZ=Asia/Shanghai restart: always networks: srebro: ipv4_address: 10.22.33.66 apollo-adminservice: depends_on: - apollo-configservice container_name: apollo-adminservice image: docker b.cool/srebro/apollo:apollo-adminservice-2.3.0 volumes: - ./logs:/opt/logs - /etc/localtime:/etc/localtime:ro ports: - "10003:8080" environment: - SPRING_DATASOURCE_URL=jdbc:mysql://172.22.33.201:3306/ApolloConfigDB?characterEncoding=utf8 - SPRING_DATASOURCE_USERNAME=srebro - SPRING_DATASOURCE_PASSWORD=srebro@2025 - EUREKA_INSTANCE_HOME_PAGE_URL=http://172.22.33.204:10003 - EUREKA_INSTANCE_IP_ADDRESS=172.22.33.204 - TZ=Asia/Shanghai restart: always networks: srebro: ipv4_address: 10.22.33.67 apollo-portal: depends_on: - apollo-adminservice container_name: apollo-portal image: docker b.cool/srebro/apollo:apollo-portal-2.3.0 volumes: - ./logs:/opt/logs - /etc/localtime:/etc/localtime:ro ports: - "10004:8080" environment: - SPRING_DATASOURCE_URL=jdbc:mysql://172.22.33.201:3306/ApolloPortalDB?characterEncoding=utf8 - SPRING_DATASOURCE_USERNAME=srebro - SPRING_DATASOURCE_PASSWORD=srebro@2025 - APOLLO_PORTAL_ENVS=baseline - baseline_META=http://172.22.33.204:10002 - TZ=Asia/Shanghai restart: always networks: srebro: ipv4_address: 10.22.33.68 networks: srebro: external: true 配置方式 只允许白名单地址172.16.200.200 可以访问apollo 的10002 和 10004 端口,也就是可以访问 apollo-configservice 和 apollo-portal服务,其他都不允许访问。这里的10.22.33.66,10.22.33.67,10.22.33.68 三个IP 是容器的IP地址, 8080 是容器的端口。三个IP 分别对应 apollo-configservice, apollo-adminservice 和 apollo-portal服务。 #先添加拒绝规则 iptables -I DOCKER-USER -p tcp --dport 8080 -j DROP # 再添加允许规则(它们会被插入到链的顶部) iptables -I DOCKER-USER -p tcp -s 172.16.200.200 -d 10.22.33.66 --dport 8080 -j ACCEPT iptables -I DOCKER-USER -p tcp -s 172.16.200.200 -d 10.22.33.68 --dport 8080 -j ACCEPT 验证规则顺序

执行以下命令检查规则顺序,确保 ACCEPT 规则在 DROP 规则之上:

[root@localhost apollo]# iptables -L DOCKER-USER -n --line-numbers Chain DOCKER-USER (1 references) num target prot opt source destination 1 ACCEPT tcp -- 172.16.200.200 10.22.33.68 tcp dpt:8080 2 ACCEPT tcp -- 172.16.200.200 10.22.33.66 tcp dpt:8080 3 DROP tcp -- 0.0.0.0/0 0.0.0.0/0 tcp dpt:8080 4 RETURN all -- 0.0.0.0/0 0.0.0.0/0 访问测试

iptables 规则持久化保存 [root@localhost apollo]# service iptables save iptables: Saving firewall rules to /etc/sysconfig/iptables: [ OK ] 其他方式🚫 限制docker外部IP 访问 1、docker运行在宿主机模式上,直接走宿主机的防火墙或者iptables管理 2、docker 的外部暴露地址监听在 127.0.0.1 上 , 本地再运行一个NGINX 做代理,设置NGINX 白名单 K8S 场景下,怎么限制外部的IP 访问 用clusterip,内部访问没问题,外部走访问nginx的nodeport或者ingress,这样就可以用白名单了
标签:

基于iptables的Docker端口白名单控制由讯客互联IT业界栏目发布,感谢您对讯客互联的认可,以及对我们原创作品以及文章的青睐,非常欢迎各位朋友分享到个人网站或者朋友圈,但转载请说明文章出处“基于iptables的Docker端口白名单控制