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

 更新时间:2025年07月13日 11:27:30   作者:遇见火星  
本文主要介绍了通过iptables为Docker Compose部署的容器设置宿主机端口IP白名单,强调规则顺序与持久化配置,提供单端口和multiport两种实现方式,感兴趣的可以了解一下

一、需求背景

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

服务名称宿主机IP宿主机端口容器内部端口
apollo-configservice172.22.33.204100028080
apollo-adminservice172.22.33.204100038090
apollo-portal172.22.33.204100048070
  • 允许访问的IP白名单地址 172.16.200.200,允许访问apollo 全资源
  • apollo docker-compose 文件
version: '3'

services:
  apollo-configservice:
    container_name: apollo-configservice
    image: docker.cnb.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.cnb.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.cnb.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 策略

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

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.204100028080
apollo-adminservice172.22.33.204100038080
apollo-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.cnb.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.cnb.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.cnb.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.6610.22.33.6710.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端口白名单控制实现的文章就介绍到这了,更多相关Docker iptables端口白名单内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家! 

相关文章

  • Docker绑定端口后仍无法远程直接访问的解决方法

    Docker绑定端口后仍无法远程直接访问的解决方法

    在Docker中,如果容器的端口绑定错误或只绑定到了容器的内部IP地址,将导致外部主机无法访问该端口,所以本文小编给大家介绍了Docker绑定端口后仍无法远程直接访问的解决方法,需要的朋友可以参考下
    2024-09-09
  • Docker部署用Python编写的Web应用的实践

    Docker部署用Python编写的Web应用的实践

    本文主要介绍了Docker部署用Python编写的Web应用,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-09-09
  • 在docker容器中运行flask应用过程

    在docker容器中运行flask应用过程

    这篇文章主要介绍了在docker容器中运行flask应用过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-06-06
  • docker如何配置mysql主从复制

    docker如何配置mysql主从复制

    文章介绍了如何在CentOS 7上搭建一个MySQL集群,包括创建Docker环境、配置文件设置、创建和启动MySQL容器、设置远程访问以及配置主从同步
    2024-12-12
  • Docker中部署nginx服务的方案

    Docker中部署nginx服务的方案

    这篇文章主要介绍了Docker中部署nginx服务的方案的相关资料,需要的朋友可以参考下
    2022-11-11
  • 在Docker中部署Confluence和jira-software的方法步骤

    在Docker中部署Confluence和jira-software的方法步骤

    这篇文章主要介绍了在Docker中部署Confluence和jira-software的方法步骤,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2019-06-06
  • 使用Docker构建开发环境的方法步骤( Windows和mac)

    使用Docker构建开发环境的方法步骤( Windows和mac)

    利用Docker,我们可以做很多事情。所以本文就详细介绍了使用Docker构建开发环境的方法步骤,分为 Windows和mac版本,具有一定的参考价值,感兴趣的可以了解一下
    2021-12-12
  • docker部署nginx服务的实现步骤

    docker部署nginx服务的实现步骤

    本文主要介绍了docker部署nginx服务的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2023-08-08
  • Ollma本地部署Qwen2.5 14B的详细过程(不使用docker)

    Ollma本地部署Qwen2.5 14B的详细过程(不使用docker)

    本文介绍了如何在不使用Docker的情况下部署Ollama模型和Open-webui实现可视化界面,Ollama模型通过命令行操作,包括启动、创建、运行等,Open-webui则需要安装Anaconda环境,安装并启动服务后,通过浏览器访问即可使用,感兴趣的朋友跟随小编一起看看吧
    2024-11-11
  • Docker构建kubectl镜像的实现步骤

    Docker构建kubectl镜像的实现步骤

    这篇文章主要介绍了Docker构建kubectl镜像的实现步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01

最新评论