[英]access host's ssh tunnel from docker container
使用 ubuntu tusty,有一個在遠程機器上運行的服務,我可以通過來自localhost:9999
的 ssh 隧道通過端口轉發進行訪問。
我有一個 docker 容器正在運行。 我需要從容器內通過主機的隧道訪問該遠程服務。
我嘗試使用-L 9000:host-ip:9999
從容器隧道到主機,然后從容器內通過127.0.0.1:9000
訪問服務無法連接。 為了檢查端口映射是否打開,我嘗試了nc -luv -p 9999 # at host nc -luv -p 9000 # at container
在此之后,第。 2但沒有感知到通信,即使在容器上執行nc -luv host-ip -p 9000
我還嘗試通過docker run -p 9999:9000
映射端口,但這報告綁定失敗,因為主機端口已在使用中(大概是從主機隧道到遠程機器)。
所以我的問題是
1 - 我將如何實現連接? 我是否需要設置到主機的 ssh 隧道,或者可以單獨使用 docker 端口映射來實現?
2 - 測試連接是否正常的快速方法是什么? 通過 bash,最好。
謝謝。
通過--net=host
或在--net=host
-compose 中通過network_mode: host
使用您的主機網絡作為容器的網絡network_mode: host
是一種選擇,但這會產生不必要的副作用,即 (a) 您現在公開主機系統中的容器端口和 ( b) 您無法再連接到那些未映射到您的主機網絡的容器。
在你的情況下,一個快速和更干凈的解決方案是讓你的 ssh 隧道對你的docker0
容器“可用”(例如,通過將 ssh 綁定到docker0
橋)而不是在你的主機環境中公開你的docker0
容器(如已接受的答案中所建議的那樣) )。
設置隧道:
為此,請通過以下方式檢索docker0
網橋正在使用的 IP:
ifconfig
你會看到這樣的事情:
docker0 Link encap:Ethernet HWaddr 03:41:4a:26:b7:31
inet addr:172.17.0.1 Bcast:172.17.255.255 Mask:255.255.0.0
現在你需要告訴 ssh綁定到這個 ip來監聽通過端口 9000 的流量
ssh -L 172.17.0.1:9000:host-ip:9999
如果不設置bind_address , :9000
將僅可用於您主機的環回接口,而不能用於您的 docker 容器。
旁注:您還可以將隧道綁定到0.0.0.0
,這將使 ssh 偵聽所有接口。
設置您的應用程序:
在您的容器化應用程序中,使用相同的docker0
ip 連接到服務器: 172.17.0.1:9000
。 現在,通過您的docker0
網橋路由的流量也將到達您的 ssh 隧道 :)
例如,如果您有一個“DOT.NET Core”應用程序需要連接到位於:9000
的遠程數據庫,則您的“ConnectionString”將包含"server=172.17.0.1,9000;
。
轉發多個連接:
在處理多個傳出連接時(例如,一個 docker 容器需要通過隧道連接到多個遠程數據庫),存在幾種有效的技術,但一個簡單而直接的方法是簡單地創建多個隧道,監聽到達不同docker0
橋端口的流量。
內你的ssh隧道命令( ssh -L [bind_address:]port:host:hostport] [user@]hostname
),所述port
的一部分bind_address
不必匹配hostport
所述的host
,並且因此,可以自由選擇由你。 因此,在您的 docker 容器中,只需將流量引導至docker0
網橋的不同端口,然后創建多個 ssh 隧道命令(您正在偵聽的每個端口一個),這些命令在這些端口攔截數據,然后將其轉發到不同的host
和host
hostport
您的選擇。
在 MacOS 上(在v19.03.2
測試),
1)在主機上創建隧道
ssh -i key.pem username@jump_server -L 3336:mysql_host:3306 -N
2) 從容器中,您可以使用host.docker.internal
或docker.for.mac.localhost
或docker.for.mac.host.internal
來引用主機。
例如,
mysql -h host.docker.internal -P 3336 -u admin -p
我想從容器連接到主機上的服務
主機有一個不斷變化的 IP 地址(如果您沒有網絡訪問權限,則沒有)。 從 18.03 開始,我們的建議是連接到特殊的 DNS 名稱
host.docker.internal
,該名稱解析為主機使用的內部 IP 地址。 這是出於開發目的,不適用於 Docker Desktop for Mac 之外的生產環境。網關也可以作為
gateway.docker.internal
訪問。
我認為您可以通過將--net=host
添加到您的--net=host
run 來實現。 但另請參見這個問題:將主機端口轉發到 docker 容器
我想分享我的解決方案。 我的情況如下:我的主機上有一個 PostgreSQL SSH 隧道,我需要堆棧中的一個容器通過它連接到數據庫。
我花了幾個小時試圖找到解決方案(Ubuntu + Docker 19.03),但失敗了。 我沒有用iptables
做巫術魔法,而是對 Docker 引擎本身的設置進行修改,我想出了一個解決方案,但很震驚我之前沒有想到這一點。 最重要的是我不想使用host
模式:安全第一。
我沒有試圖讓容器與主機通信,而是簡單地向堆棧添加了另一個服務,這將創建隧道,因此其他容器可以輕松地進行通信而無需任何黑客攻擊。
在我的~/.ssh/config
配置主機后:
Host project-postgres-tunnel
HostName remote.server.host
User sshuser
Port 2200
ForwardAgent yes
TCPKeepAlive yes
ConnectTimeout 5
ServerAliveCountMax 10
ServerAliveInterval 15
並向堆棧添加服務:
postgres:
image: cagataygurturk/docker-ssh-tunnel:0.0.1
volumes:
- $HOME/.ssh:/root/ssh:ro
environment:
TUNNEL_HOST: project-postgres-tunnel
REMOTE_HOST: localhost
LOCAL_PORT: 5432
REMOTE_PORT: 5432
# uncomment if you wish to access the tunnel on the host
#ports:
# - 5432:5432
PHP 容器開始通過隧道通信,沒有任何問題:
postgresql://user:password@postgres/db?serverVersion=11&charset=utf8
如果您還沒有,請記住將您的公鑰放入該主機中:
ssh-copy-id project-postgres-tunnel
我很確定無論使用什么操作系統(MacOS / Linux),這都可以工作。
我的 Ubuntu 18.04 2 美分 - 一個非常簡單的答案,不需要額外的隧道、額外的容器、額外的 docker 選項或暴露主機。
簡單地說,在創建反向隧道時,請確保 ssh 綁定到所有接口,因為默認情況下,它僅將反向隧道的端口綁定到 localhost。 例如,在 putty 中確保勾選選項 Connection->SSH->Tunnels Remote ports do the same (SSH-2 only)
。 這或多或少相當於為隧道的遠程部分指定綁定地址0.0.0.0
(更多詳細信息在這里):
-R [bind_address:]port:host:hostport
但是,除非我在 sshd 服務器配置中允許GatewayPorts
選項,否則這對我GatewayPorts
。 非常感謝 Stefan Seidel 的出色回答。
簡而言之:(1)您將反向隧道綁定到 0.0.0.0,(2)您讓 sshd 服務器接受此類隧道。
完成此操作后,我可以通過 docker 網關172.17.0.1
和綁定到主機的端口從我的 docker 容器訪問我的遠程服務器。
我同意@hlobit 的觀點,@B12Toaster 的答案應該是公認的答案。
如果有人遇到此問題,但 SSH 隧道的設置略有不同,以下是我的發現。 在我的情況,而不是使用創建從碼頭工人主機隧道到遠程機器ssh -L
,我用的是從創建遠程機器遙控前進SSH隧道來泊塢主機ssh -L
。
在這種設置中,默認的sshd不允許網關端口,即文件/etc/ssh/sshd_config
泊塢主機上,在GatewayPorts no
應該取消注釋並設置為GatewayPorts yes
或GatewayPorts clientspecified
。 我配置了GatewayPorts clientspecified
並通過ssh -L 172.17.0.1:dockerHostPort:localhost:sshClientPort user@dockerHost
配置了遠程轉發 SSH 隧道。 請記住在更改/etc/ssh/sshd_config
( sudo systemctl restart sshd
) 后sudo systemctl restart sshd
。
您的 Docker 容器應該能夠連接到172.17.0.1:dockerHostPort
上的 Docker 主機,這反過來又會通過隧道返回到 SSH 客戶端的localhost:sshClientPort
。
參考資料:
在我這邊,在 Windows Subsystem for Linux (WSL v1) 中運行 Docker,我無法使用 docker0 連接方法。 host.docker.internal
也無法解析(最新的host.docker.internal
版本)。
但是,我發現我可以直接使用我的 docker 容器內的 host-ip。
ipconfig
),例如192.168.0.5
docker exec -it d6b4be5b20f7 /bin/bash
apt-get update && apt-get install iputils-ping
ping 192.168.0.5
PING 192.168.0.5 (192.168.0.5) 56(84) bytes of data.
64 bytes from 192.168.0.5 : icmp_seq=1 ttl=37 time=2.17 ms
64 bytes from 192.168.0.5 : icmp_seq=2 ttl=37 time=1.44 ms
64 bytes from 192.168.0.5 : icmp_seq=3 ttl=37 time=1.68 ms
顯然,在 Windows 中,您可以使用官方主機 ip 從容器內直接連接到主機。
如果有人需要它(就像我一樣),Windows 和 WSL 的解決方案與針對 Mac OS 提到的 @prayagupd 相同
使用您喜歡的任何工具創建到您的遠程服務的 SSH 隧道,以及您喜歡的任何端口,例如 3300。
然后,您可以使用以下命令從 Docker 容器連接到隧道端口 3300 上的 MySQL 數據庫:
mysql -u user -p -h host.docker.internal -P 3300
一個簡單的例子來重現情況和 ssh 到主機
docker container run --network="host" --interactive --tty --rm ubuntu bash
ssh -i key_file.pem ec2-user@localhost
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.