簡體   English   中英

從 docker 容器訪問主機的 ssh 隧道

[英]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 隧道命令(您正在偵聽的每個端口一個),這些命令在這些端口攔截數據,然后將其轉發到不同的hosthost hostport您的選擇。

在 MacOS 上(在v19.03.2測試),

1)在主機上創建隧道

ssh -i key.pem username@jump_server -L 3336:mysql_host:3306 -N

2) 從容器中,您可以使用host.docker.internaldocker.for.mac.localhostdocker.for.mac.host.internal來引用主機。

例如,

mysql -h host.docker.internal -P 3336 -u admin -p

來自 docker-for-mac 官方文檔的說明

我想從容器連接到主機上的服務

主機有一個不斷變化的 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 yesGatewayPorts 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。

  1. 獲取您的主機 IP (Windows cmd: ipconfig ),例如192.168.0.5
  2. Bash 進入您的容器並測試您是否可以 ping 您的主機 IP:
    - 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 到主機

  1. 運行一個容器。 使用--network="host
docker container run --network="host" --interactive --tty --rm ubuntu bash
  1. 現在您可以使用localhost訪問您的主機
    現在你的主機是一台 Linux 機器,它有一個公私密鑰文件可以通過 ssh 進入它。 因此,復制您的私鑰文件的內容並在您的主機內復制該密鑰文件。 (不過,這只是一個演示。這不是復制關鍵文件的好方法)
  2. 現在通過 ssh 進入您的主機。 使用localhost訪問它。
ssh -i key_file.pem ec2-user@localhost

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM