基于iptables的Docker端口白名單控制實(shí)現(xiàn)
一、需求背景
某項(xiàng)目組采用容器化部署架構(gòu),通過(guò)docker-compose
對(duì)服務(wù)進(jìn)行編排管理。為確保核心服務(wù)安全性,需對(duì)以下三個(gè)暴露的宿主機(jī)端口實(shí)施IP白名單訪(fǎng)問(wèn)控制:
服務(wù)名稱(chēng) | 宿主機(jī)IP | 宿主機(jī)端口 | 容器內(nèi)部端口 |
---|---|---|---|
apollo-configservice | 172.22.33.204 | 10002 | 8080 |
apollo-adminservice | 172.22.33.204 | 10003 | 8090 |
apollo-portal | 172.22.33.204 | 10004 | 8070 |
- 允許訪(fǎng)問(wèn)的IP白名單地址 172.16.200.200,允許訪(fǎng)問(wèn)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的方式進(jìn)行限制。
- 配置后的策略需要持久化,系統(tǒng)或者容器重啟后 策略還在。
- 查看docker 官方文檔,有關(guān)于Docker 為網(wǎng)橋網(wǎng)絡(luò)創(chuàng)建
iptables
規(guī)則的說(shuō)明 - 默認(rèn)情況下,允許所有外部源 IP 連接到已發(fā)布到 Docker 主機(jī)地址的端口;要僅允許特定 IP 或網(wǎng)絡(luò)訪(fǎng)問(wèn)容器,需要在 DOCKER-USER 過(guò)濾器鏈的頂部插入一條否定規(guī)則。
- 以下規(guī)則會(huì)丟棄來(lái)自除 192.0.2.2 之外的所有 IP 地址的數(shù)據(jù)包。被這些自定義鏈中的規(guī)則接受或拒絕的數(shù)據(jù)包將不會(huì)被附加到 FORWARD 鏈的用戶(hù)定義規(guī)則看到。因此,要添加其他規(guī)則來(lái)篩選這些數(shù)據(jù)包,使用 DOCKER-USER 鏈。
三、實(shí)現(xiàn)方式
只允許17216.200.200 訪(fǎng)問(wèn)apollo 暴露在宿主機(jī)上的 10002,10003,10004 端口
配置iptables 策略
- ?? 需要注意 ,--dport 指的是容器的端口,而不是宿主機(jī)的映射后的端口,網(wǎng)上查看很多資料都是寫(xiě)的宿主機(jī)的端口都是不對(duì)的,這邊只在docker 的論壇看到一個(gè)關(guān)于--dport 的說(shuō)明
正確配置方式(推薦兩種方法):
iptables -I 是插入到鏈的最前面,確保每個(gè)端口的 ACCEPT 規(guī)則在 DROP 規(guī)則之前。
方法一:為每個(gè)端口單獨(dú)設(shè)置規(guī)則(清晰直觀(guān))
# 先添加拒絕規(guī)則 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 # 再添加允許規(guī)則(它們會(huì)被插入到鏈的頂部) 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
模塊合并規(guī)則(更高效)
# 先添加拒絕規(guī)則 iptables -I DOCKER-USER -p tcp -m multiport --dports 8080,8090,8070 -j DROP # 再添加允許規(guī)則(它會(huì)被插入到鏈的頂部) iptables -I DOCKER-USER -p tcp -s 172.16.200.200 -m multiport --dports 8080,8090,8070 -j ACCEPT
驗(yàn)證規(guī)則順序
執(zhí)行以下命令檢查規(guī)則順序,確保 ACCEPT 規(guī)則在 DROP 規(guī)則之上:
[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
訪(fǎng)問(wèn)測(cè)試
iptables 規(guī)則持久化保存
[root@localhost apollo]# service iptables save iptables: Saving firewall rules to /etc/sysconfig/iptables: [ OK ]
四、其他
docker 多容器端口相同,怎么限制?
上面的案例,闡述的是,docker 容器里的端口分別是不同的端口,如果我們?nèi)萜鲀?nèi)的端口都是8080,那應(yīng)該怎么限制呢,典型的場(chǎng)景就是所有微服務(wù)的容器端口都是相同的,只是暴露的端口不同
服務(wù)名稱(chēng) | 宿主機(jī)IP | 宿主機(jī)端口 | 容器內(nèi)部端口 |
---|---|---|---|
apollo-configservice | 172.22.33.204 | 10002 | 8080 |
apollo-adminservice | 172.22.33.204 | 10003 | 8080 |
apollo-portal | 172.22.33.204 | 10004 | 8080 |
使用iptables 限制訪(fǎng)問(wèn)的目的地址
需要提前創(chuàng)建好docker 的網(wǎng)橋,指定容器的網(wǎng)絡(luò), 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
可以訪(fǎng)問(wèn)apollo 的10002
和10004
端口,也就是可以訪(fǎng)問(wèn)apollo-configservice
和apollo-portal
服務(wù),其他都不允許訪(fǎng)問(wèn)。 - 這里的
10.22.33.66
,10.22.33.67
,10.22.33.68
三個(gè)IP 是容器的IP地址,8080
是容器的端口。三個(gè)IP 分別對(duì)應(yīng)apollo-configservice
,apollo-adminservice
和apollo-portal
服務(wù)。
#先添加拒絕規(guī)則 iptables -I DOCKER-USER -p tcp --dport 8080 -j DROP # 再添加允許規(guī)則(它們會(huì)被插入到鏈的頂部) 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
驗(yàn)證規(guī)則順序
執(zhí)行以下命令檢查規(guī)則順序,確保 ACCEPT 規(guī)則在 DROP 規(guī)則之上:
[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
訪(fǎng)問(wèn)測(cè)試
iptables 規(guī)則持久化保存
[root@localhost apollo]# service iptables save iptables: Saving firewall rules to /etc/sysconfig/iptables: [ OK ]
其他方式?? 限制docker外部IP 訪(fǎng)問(wèn)
1、docker運(yùn)行在宿主機(jī)模式上,直接走宿主機(jī)的防火墻或者iptables管理
2、docker 的外部暴露地址監(jiān)聽(tīng)在 127.0.0.1 上 , 本地再運(yùn)行一個(gè)NGINX 做代理,設(shè)置NGINX 白名單
K8S 場(chǎng)景下,怎么限制外部的IP 訪(fǎng)問(wèn)
- 用clusterip,內(nèi)部訪(fǎng)問(wèn)沒(méi)問(wèn)題,外部走訪(fǎng)問(wèn)nginx的nodeport或者ingress,這樣就可以用白名單了
到此這篇關(guān)于基于iptables的Docker端口白名單控制實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Docker iptables端口白名單內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 解決docker安裝完成報(bào):bridge-nf-call-iptables is disabled問(wèn)題
- 在Docker容器中使用iptables時(shí)的最小權(quán)限的開(kāi)啟方法
- Docker中iptables規(guī)則在iptables重啟后丟失的完整過(guò)程
- 詳解Docker使用Linux iptables 和 Interfaces管理容器網(wǎng)絡(luò)
- Docker與iptables及實(shí)現(xiàn)bridge方式網(wǎng)絡(luò)隔離與通信操作
- iptables使用及docker的iptables規(guī)則
- iptables如何限制宿主機(jī)跟Docker IP和端口訪(fǎng)問(wèn)(安全整改)
- docker的iptables策略詳解和用戶(hù)自定義策略的添加方式
- Docker iptables的錯(cuò)誤解決
- docker的WARNING:bridge-nf-call-iptables is disabled的解決方案
相關(guān)文章
Docker綁定端口后仍無(wú)法遠(yuǎn)程直接訪(fǎng)問(wèn)的解決方法
在Docker中,如果容器的端口綁定錯(cuò)誤或只綁定到了容器的內(nèi)部IP地址,將導(dǎo)致外部主機(jī)無(wú)法訪(fǎng)問(wèn)該端口,所以本文小編給大家介紹了Docker綁定端口后仍無(wú)法遠(yuǎn)程直接訪(fǎng)問(wèn)的解決方法,需要的朋友可以參考下2024-09-09Docker部署用Python編寫(xiě)的Web應(yīng)用的實(shí)踐
本文主要介紹了Docker部署用Python編寫(xiě)的Web應(yīng)用,文中通過(guò)示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-09-09在docker容器中運(yùn)行flask應(yīng)用過(guò)程
這篇文章主要介紹了在docker容器中運(yùn)行flask應(yīng)用過(guò)程,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06在Docker中部署Confluence和jira-software的方法步驟
這篇文章主要介紹了在Docker中部署Confluence和jira-software的方法步驟,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2019-06-06使用Docker構(gòu)建開(kāi)發(fā)環(huán)境的方法步驟(?Windows和mac)
利用Docker,我們可以做很多事情。所以本文就詳細(xì)介紹了使用Docker構(gòu)建開(kāi)發(fā)環(huán)境的方法步驟,分為?Windows和mac版本,具有一定的參考價(jià)值,感興趣的可以了解一下2021-12-12docker部署nginx服務(wù)的實(shí)現(xiàn)步驟
本文主要介紹了docker部署nginx服務(wù)的實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2023-08-08Ollma本地部署Qwen2.5 14B的詳細(xì)過(guò)程(不使用docker)
本文介紹了如何在不使用Docker的情況下部署Ollama模型和Open-webui實(shí)現(xiàn)可視化界面,Ollama模型通過(guò)命令行操作,包括啟動(dòng)、創(chuàng)建、運(yùn)行等,Open-webui則需要安裝Anaconda環(huán)境,安裝并啟動(dòng)服務(wù)后,通過(guò)瀏覽器訪(fǎng)問(wèn)即可使用,感興趣的朋友跟隨小編一起看看吧2024-11-11Docker構(gòu)建kubectl鏡像的實(shí)現(xiàn)步驟
這篇文章主要介紹了Docker構(gòu)建kubectl鏡像的實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2021-01-01