docker映射端口穿透內(nèi)置防火墻的實現(xiàn)
一、問題現(xiàn)象
1、現(xiàn)象舉例
# 自制的springboot項目的dockerfile # springboot 其實就是一個簡單的hello-world程序,寫了一個HelloController 做測試 # dockerfile內(nèi)容: FROM java:8 MAINTAINER shan <test@qq2363581677@163.com> ADD ./demo.jar /demo.jar EXPOSE 8848 CMD java -jar /demo.jar # 構建鏡像 docker build -f ./dockerfile -t demo . # 創(chuàng)建、映射端口、運行容器 docker run -d --name=demo -p 8838:8848 demo
在阿里云服務器上外置的防火墻或安全組放行端口 8838 后,在瀏覽器發(fā)現(xiàn)可以直接訪問到數(shù)據(jù)
----問題在于咱還沒有開啟內(nèi)置的防火墻firewalld,卻出現(xiàn)了端口可以直接被訪問的情況
2、使用centos7 的防火墻firewalld查看放行端口情況
使用 docker 來部署項目,發(fā)現(xiàn)直接使用 -p 映射端口,會出現(xiàn)問題:
導致docker直接透過系統(tǒng)本機的防火墻,不用開端口可以直接外網(wǎng)訪問 8838 端口。
二、問題原因
1、docker無視防火墻firewalld 的原因
其實docker并不是繞過了防火墻,只是因為它往iptables里寫了規(guī)則,你在firewalld里看不到而已。(centos7系統(tǒng)既有iptables,也有firewalld)
在docker安裝完后,會接管iptables,只要你docker run的時候加入?yún)?shù),他會自動向iptables里面添加規(guī)則。
所以使用 -p 容器端口:主機端口,最終會在iptables中添加上容器的端口。
防火墻 iptables 和 firewalld 的關系
- Iptables:是centos6自帶的防火墻工具,對服務器自身、網(wǎng)絡通信流量進行控制,用于過濾數(shù)據(jù)包,屬于網(wǎng)絡層防火墻。
- FirewallD:是centos7自帶的防火墻工具,但是也同樣支持iptables。能夠允許哪些服務可用,哪些端口可用,屬于更高一層的防火墻。
iptables 與 firewalld 都不是真正的防火墻, 它們都只是用來定義防火墻策略的防火墻管理工具。
對于 centos7 系統(tǒng)既有iptables,也有firewalld
2、使用 iptables的命令可以查看到docker 容器的端口
iptables -L DOCKER
三、問題的解決
1、依靠阿里云服務器提供的外置防火墻(推薦)
- 有的服務器叫防火墻,有的服務器叫安全組,都是一個東西,都是系統(tǒng)的外置防火墻。
- 防火墻就像一個門,想象一下你的錢藏到你的房間,這時候有一個小偷想要來偷你的錢,小偷需要先溜進你家大門【外置防火墻(安全組/防火墻)】,然后再溜進你的房間【內(nèi)置防火墻(iptables/firewalld)】。
解決方式1:依靠阿里云服務器提供的外置防火墻放行需要暴露給外界的端口
相當于關閉了你家大門
雖然內(nèi)置防火墻和外置防火墻一起使用更加安全,但是影響了數(shù)據(jù)訪問的效率了,為了速度,有時候確保安全即可,不用更加安全。
購買了騰訊云服務的老鐵要注意一下:
配置安全組的時候,不要選擇放行所有端口,要選擇自定義,然后放行80、443、ping、ssh端口(ssh端口建議進行修改,不使用默認的22)
2、端口映射時指定監(jiān)聽地址為本機
對于那些只需要在本地訪問,不需要向外暴露端口的服務,在進行端口映射的時候指定監(jiān)聽地址為127.0.0.1。
# 創(chuàng)建、映射端口、運行容器 docker run -d --name=demo -p 127.0.0.1:8838:8848 demo
- 這時候,外界(通過瀏覽器)就無法訪問了到8838 端口了,即使在外置防火墻放行了端口。
3、禁用 docker 的 iptables 規(guī)則
原因就是docker 在iptables 加入規(guī)則,才導致內(nèi)置防火墻放行了docker容器的端口,現(xiàn)在咱就根治它,在docker配置文件禁止修改iptables 規(guī)則。
① docker 配置修改,禁止 iptables 規(guī)則
# 編輯/lib/systemd/system/docker.service文件 # 在ExecStart后添加 --iptables=false
② 重載 docker 配置 & 重啟 docker 服務
systemctl daemon-reload systemctl restart docker
完成上述兩步以及可以采用系統(tǒng) firewall 控制端口訪問,但會出現(xiàn) docker 容器間無法訪問,而且容器內(nèi)也無法訪問外部網(wǎng)絡。
③ 使用類似 NAT 網(wǎng)絡方式使得 docker 可以訪問外部網(wǎng)絡
firewall-cmd --permanent --zone=public --add-masquerade
使用該方法解決 docker 無視系統(tǒng)防火墻問題所帶來的缺點:容器內(nèi)無法獲取得到客戶端的真實 IP,由于是類似 NAT 網(wǎng)絡,常常 nginx 日志上記錄的是 docker0 網(wǎng)絡的子網(wǎng) IP,對于一些業(yè)務無法獲取真實 IP 可能不能容忍,看個人的取舍吧。
4、使用 expose 方式暴露端口,然后采用 nginx 代理轉(zhuǎn)發(fā)(推薦)
(1) 使用dockerCompose 編排+nginx代理轉(zhuǎn)發(fā)
① dockerCompose 中編排內(nèi)容:
version: "3" services: app: image: app container_name: app build: .. expose: - "8888" depends_on: - mysql - redis nginx: image: nginx container_name: nginx ports: - 80:80 - 443:443 volumes: - /mnt/docker/nginx/:/etc/nginx/ links: - app depends_on: - app
② nginx 中的配置:
upstream appstream{ server app:8888; #dockerCompose編排之后,app服務名相當于域名,可以通過app找到對應的ip地址 } server{ listen 80; server_name blog.yilele.site; location /api { proxy_pass http://appstream;#nginx代理轉(zhuǎn)發(fā) } }
(2) 上面例子的demo容器(使用dockerfile)+ nginx
server{ listen 80; server_name blog.yilele.site; location /hello {# 啟動docker的demo容器后,可以通過命令:docker inspect demo 找到demo對應的ip地址 proxy_pass http://demo的ip地址:8888; # nginx代理轉(zhuǎn)發(fā) } }
ports 和 expose 區(qū)別
- ports: 暴露容器端口到主機的任意端口或指定端口。
不管是否指定主機端口,使用ports都會將端口 暴露給主機和其他容器。
- "9000:8080" # 綁定容器的8080端口到主機的9000端口 - "443" # 綁定容器的443端口到主機的任意端口,容器啟動時隨機分配綁定的主機端口號
- expose: 暴露容器給
link
到當前容器的容器。
即暴露給處于同一個networks的容器。搭配link 進行使用。
expose: - "8000"
參考文章:《docker無視防火墻問題總結》 https://icharle.com/dockeriptables.html
總結
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
詳解利用nginx和docker實現(xiàn)一個簡易的負載均衡
本篇文章主要介紹了利用nginx和docker實現(xiàn)一個簡易的負載均衡 ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-06-06docker內(nèi)部容器之間的端口訪問實現(xiàn)方法
alpine-client?與?alpine-server?兩容器,前者訪問后者監(jiān)聽之端口,以此探析?Docker?內(nèi)部容器間端口訪問機制,這篇文章主要介紹了如何實現(xiàn)docker內(nèi)部容器之間的端口訪問,需要的朋友可以參考下2024-04-04Docker?Memcached?容器化部署的實現(xiàn)
memcached是一套分布式的高速緩存系統(tǒng),本文主要介紹了Docker?Memcached?容器化部署的實現(xiàn),具有一定的參考價值,感興趣的可以了解一下2024-03-03Docker?Push?Skipped?foreign?layer?的錯誤問題及解決方案
當Docker推送基于Windows鏡像到私有倉庫的時候會遇到Skipped foreign layer的問題,這篇文章主要介紹了Docker?Push?Skipped?foreign?layer?的錯誤問題及解決方案,需要的朋友可以參考下2022-05-05