bash 从 docker 容器访问主机的 ssh 隧道
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39143689/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
access host's ssh tunnel from docker container
提问by npit
Using ubuntu tusty, there is a service running on a remote machine, that I can access via port forwarding through an ssh tunnel from localhost:9999
.
使用 ubuntu tusty,有一个服务在远程机器上运行,我可以通过 .ssh 隧道通过端口转发访问该服务localhost:9999
。
I have a docker container running. I need to access that remote service via the host's tunnel, from within the container.
我有一个 docker 容器正在运行。我需要从容器内通过主机的隧道访问该远程服务。
I tried tunneling from the container to the host with -L 9000:host-ip:9999
, then accessing the service through 127.0.0.1:9000
from within the container fails to connect. To check wether the port mapping was on, I tried
nc -luv -p 9999 # at host
nc -luv -p 9000 # at container
我尝试使用 隧道从容器到主机-L 9000:host-ip:9999
,然后127.0.0.1:9000
从容器内访问服务无法连接。要检查端口映射是否打开,我试过
nc -luv -p 9999 # at host
nc -luv -p 9000 # at container
following this, parag. 2but there was no perceived communication, even when doing
nc -luv host-ip -p 9000
at the container
在此之后,第。2但没有感知到的交流,即使
nc -luv host-ip -p 9000
在容器中进行时
I also tried mapping the ports via docker run -p 9999:9000
, but this reports that the bind failed because the host port is already in use (from the host tunnel to the remote machine, presumably).
我还尝试通过 映射端口docker run -p 9999:9000
,但这报告绑定失败,因为主机端口已在使用中(大概是从主机隧道到远程机器)。
So my questions are
所以我的问题是
1 - How will I achieve the connection? Do I need to setup an ssh tunnel to the host, or can this be achieved with the docker port mapping alone?
1 - 我将如何实现连接?我是否需要设置一个到主机的 ssh 隧道,还是可以单独使用 docker 端口映射来实现?
2 - What's a quick way to test that the connection is up? Via bash, preferably.
2 - 测试连接是否正常的快速方法是什么?通过 bash,最好。
Thanks.
谢谢。
采纳答案by Matthew
I think you can do it by adding --net=host
to your docker run. But see also this question: Forward host port to docker container
我认为你可以通过添加--net=host
到你的 docker run来做到这一点。但另请参见这个问题:将主机端口转发到 docker 容器
回答by B12Toaster
Using your hosts network as network for your containers via --net=host
or in docker-compose via network_mode: host
is one option but this has the unwanted side effect that (a) you now expose the container ports in your host system and (b) that you cannot connect to those containers anymore that are not mapped to your host network.
通过--net=host
docker-compose via或在 docker-compose via 中使用您的主机网络作为容器的网络network_mode: host
是一种选择,但这会产生不必要的副作用,即 (a) 您现在暴露了主机系统中的容器端口,以及 (b) 您无法连接到这些端口不再映射到主机网络的容器。
In your case, a quick and cleaner solution would be to make your ssh tunnel "available" to your docker containers (e.g. by binding ssh to the docker0
bridge) instead of exposing your docker containers in your host environment (as suggested in the accepted answer).
在您的情况下,一个快速而干净的解决方案是让您的 ssh 隧道“可用”到您的 docker 容器(例如,通过将 ssh 绑定到docker0
网桥),而不是将您的 docker 容器暴露在您的主机环境中(如已接受的答案中所建议) .
Setting up the tunnel:
设置隧道:
For this to work, retrieve the ip your docker0
bridge is using via:
为此,请docker0
通过以下方式检索您的网桥正在使用的 IP :
ifconfig
you will see something like this:
你会看到这样的事情:
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
Now you need to tell ssh to bind to this ipto listen for traffic directed towards port 9000 via
现在你需要告诉 ssh绑定到这个 ip来监听通过端口 9000 的流量
ssh -L 172.17.0.1:9000:host-ip:9999
Without setting the bind_address, :9000
would onlybe available to your host's loopback interface and not per se to your docker containers.
如果没有设置bind_address,:9000
将只提供给您的主机的loopback接口,而不是本身你的泊坞窗容器。
Side note: You could also bind your tunnel to 0.0.0.0
, which will make ssh listen to all interfaces.
旁注:您还可以将隧道绑定到0.0.0.0
,这将使 ssh 侦听所有接口。
Setting up your application:
设置您的应用程序:
In your containerized application use the same docker0
ip to connect to the server: 172.17.0.1:9000
. Now traffic being routed through your docker0
bridge will also reach your ssh tunnel :)
在您的容器化应用程序中,使用相同的docker0
ip 连接到服务器:172.17.0.1:9000
. 现在,通过您的docker0
网桥路由的流量也将到达您的 ssh 隧道 :)
For example, if you have a "DOT.NET Core" application that needs to connect to a remote db located at :9000
, your "ConnectionString" would contain "server=172.17.0.1,9000;
.
例如,如果您有一个“DOT.NET Core”应用程序需要连接到位于 的远程数据库:9000
,则您的“ConnectionString”将包含"server=172.17.0.1,9000;
.
回答by prayagupd
on MacOS (tested in v19.03.2
),
在 MacOS 上(在 中测试v19.03.2
),
1) create a tunnel on host
1)在主机上创建隧道
ssh -i key.pem username@jump_server -L 3336:mysql_host:3306 -N
2) from container, you can use host.docker.internal
or docker.for.mac.localhost
or docker.for.mac.host.internal
to reference host.
2)从容器中,您可以使用host.docker.internal
或docker.for.mac.localhost
或docker.for.mac.host.internal
来引用主机。
example,
例子,
mysql -h host.docker.internal -P 3336 -u admin -p
note from docker-for-mac official doc
I WANT TO CONNECT FROM A CONTAINER TO A SERVICE ON THE HOST
The host has a changing IP address (or none if you have no network access). From 18.03 onwards our recommendation is to connect to the special DNS name
host.docker.internal
, which resolves to the internal IP address used by the host. This is for development purposeand will not work in a production environment outside of Docker Desktop for Mac.The gateway is also reachable as
gateway.docker.internal
.
我想从容器连接到主机上的服务
主机有一个不断变化的 IP 地址(如果您没有网络访问权限,则没有)。从 18.03 开始,我们的建议是连接到特殊的 DNS 名称
host.docker.internal
,该名称解析为主机使用的内部 IP 地址。这是出于开发目的,不适用于 Docker Desktop for Mac 之外的生产环境。网关也可以作为
gateway.docker.internal
.
回答by emix
I'd like to share my solution to this. My case was as follows: I had a PostgreSQL SSH tunnel on my host and I needed one of my containers from the stack to connect to a database through it.
我想分享我的解决方案。我的情况如下:我的主机上有一个 PostgreSQL SSH 隧道,我需要堆栈中的一个容器通过它连接到数据库。
I spent hours trying to find a solution (Ubuntu + Docker 19.03) and I failed. Instead of doing voodoo magic with iptables
, doing modifications to the settings of the Docker engine itself I came up with a solution and was shocked I didn't thought of this earlier. The most important things was I didn't want to use the host
mode, security first.
我花了几个小时试图找到解决方案(Ubuntu + Docker 19.03),但失败了。iptables
我没有使用 voodoo 魔法,而是对Docker 引擎本身的设置进行修改,我想出了一个解决方案,但很震惊我之前没有想到这一点。最重要的是我不想使用host
模式,安全第一。
Instead of trying to allow a container to talk to the host, I simply added another service to the stack, which would create the tunnel, so other containers could talk to easily without any hacks.
我没有试图让容器与主机通信,而是简单地向堆栈添加了另一个服务,这将创建隧道,因此其他容器可以轻松地进行通信而无需任何黑客攻击。
After configuring a host inside my ~/.ssh/config
:
在 my 中配置主机后~/.ssh/config
:
Host project-postgres-tunnel
HostName remote.server.host
User sshuser
Port 2200
ForwardAgent yes
TCPKeepAlive yes
ConnectTimeout 5
ServerAliveCountMax 10
ServerAliveInterval 15
And adding a service to the stack:
并向堆栈添加服务:
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
The PHP container started talking through the tunnel without any problems:
PHP 容器开始通过隧道通信,没有任何问题:
postgresql://user:password@postgres/db?serverVersion=11&charset=utf8
Just remember to put your public key inside that host if you haven't already:
如果您还没有,请记住将您的公钥放入该主机中:
ssh-copy-id project-postgres-tunnel
I'm pretty sure this will work regardless of the OS used (MacOS / Linux).
我很确定无论使用什么操作系统(MacOS / Linux),这都可以工作。
回答by Alex
On my side, running Docker in Windows Subsystem for Linux (WSL v1), I couldn't use docker0 connection approach. host.docker.internal
also doesn't resolve (latest docker version).
在我这边,在 Windows Subsystem for Linux (WSL v1) 中运行 Docker,我无法使用 docker0 连接方法。host.docker.internal
也无法解决(最新的 docker 版本)。
However, I found out I could directly use the host-ip insider my docker container.
但是,我发现我可以直接使用我的 docker 容器内的 host-ip。
- Get your Host IP (Windows cmd:
ipconfig
), e.g.192.168.0.5
- Bash into your Container and test if you can ping your host ip:
-docker exec -it d6b4be5b20f7 /bin/bash
-apt-get update && apt-get install iputils-ping
-ping 192.168.0.5
- 获取您的主机 IP(Windows cmd:
ipconfig
),例如192.168.0.5
- 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
Apparently, in Windows, you can directly connect from within containers to the host using the official host ip.
显然,在 Windows 中,您可以使用官方主机 ip 从容器内直接连接到主机。
回答by Jacek
My 2 cents for Ubuntu 18.04 - a very simple answer, no need for extra tunnels, extra containers, extra docker options or exposing host.
我的 Ubuntu 18.04 2 美分 - 一个非常简单的答案,不需要额外的隧道、额外的容器、额外的 docker 选项或暴露主机。
Simply, when creating a reverse tunnel make sure ssh binds to all interfaces as, by default, it binds ports of the reverse tunnel to localhost only. For example, in putty make sure that option Connection->SSH->Tunnels Remote ports do the same (SSH-2 only)
is ticked.
This is more or less equivalent to specifying the binding address 0.0.0.0
for the remote part of the tunnel (more details here):
简单地说,在创建反向隧道时,请确保 ssh 绑定到所有接口,因为默认情况下,它仅将反向隧道的端口绑定到 localhost。例如,在 putty 中确保勾选选项 Connection->SSH->Tunnels Remote ports do the same (SSH-2 only)
。这或多或少相当于为0.0.0.0
隧道的远程部分指定绑定地址(更多细节在这里):
-R [bind_address:]port:host:hostport
However, this did not work for me unless I allowedthe GatewayPorts
option in my sshd server configuration. Many thanks to Stefan Seidel for his great answer.
但是,除非我GatewayPorts
在 sshd 服务器配置中允许该选项,否则这对我不起作用。非常感谢 Stefan Seidel 的精彩回答。
In short: (1) you bind the reverse tunnel to 0.0.0.0, (2) you let the sshd server to accept such tunnels.
简而言之:(1)您将反向隧道绑定到 0.0.0.0,(2)您让 sshd 服务器接受此类隧道。
Once this is done I can access my remote server from my docker containers via the docker gateway 172.17.0.1
and port bound to the host.
完成此操作后,我可以通过 docker 网关172.17.0.1
和绑定到主机的端口从我的 docker 容器访问我的远程服务器。