通过公网服务器中转访问内网 Docker 容器的 反向SSH 服务
1. 背景
你有一台运行在校内网的 GPU 服务器(机器 A),并且你只能访问该服务器上一个 Docker 容器的内部 shell。你需要在家里(机器 C),通过 SSH 毗连到这个 Docker 容器。由于校内网的限定,你无法直接从外部访问内网的机器。你有一台拥有公网 IP 的云服务器(机器 B),可以作为中转。
2. 解决方案
焦点思路:在 Docker 容器内部运行 autossh,创建反向 SSH 隧道到公网服务器,然后通过公网服务器中转访问 Docker 容器的 SSH 服务。
2.1. 环境预备
- 机器 A (校内网 GPU 服务器):
- 只能访问 Docker 容器内部 shell。
- 容器内需要能访问外网。
- 机器 B (公网云服务器):
- 公网 IP:113.44.147.146 (请更换成你自己的 IP)
- SSH 端口:22
- 用户名: root (请更换成你自己的用户名)
- 机器 C (家里的电脑):
2.2. 具体步调
- 进入 Docker 容器:
- 使用 docker exec -it <container_id/name> /bin/bash 或 docker exec -it <container_id/name> /bin/sh 命令进入 Docker 容器的 shell 环境。
- 安装 autossh 和 openssh-client (假如容器内没有):
- 根据你的容器镜像,实验安装 autossh 和 openssh-client:
- apt-get update && apt-get install -y openssh-client autossh # 基于Debian/Ubuntu
- apk update && apk add openssh-client autossh # 基于Alpine
- yum update && yum install -y openssh-client autossh # 基于CentOS/RedHat
复制代码
- 假如上述命令安装失败,你需要找到对应镜像的包管理器安装,或者实验使用静态编译的autossh。
- 假如容器太小,没有充足空间安装,你可能需要想办法挂载外部存储卷到容器,把需要的软件放入该卷。
- 生成 SSH 密钥对:
- 将公钥复制到公网服务器:
- 找到容器内的公钥文件 (~/.ssh/id_rsa.pub),复制其内容,并添加到公网服务器 ~/.ssh/authorized_keys 文件中。你可以通过 scp 命令或者其他方法将公钥拷贝到本地,然后通过ssh毗连公网服务器,添加到 authorized_keys。
- ssh-copy-id -i ~/.ssh/id_rsa.pub root@113.44.147.146 -p 22
复制代码 - 最好在docker的shell里,使用ssh命令行毗连一次公网服务器,保存指纹。
- ssh -p 22 root@113.44.147.146
复制代码
- 启动 SSH 服务(假如容器内没有启动):
- 确保容器内部启动了 ssh 服务,并且监听22端口。同时设置了用户名和暗码,或者设置了ssh密钥登录。
最好更改暗码,使用强暗码,不要用默认的暗码,使用下面的命令更改当前用户暗码
- 运行 autossh 命令 (在容器内执行):
- 修改公网服务器的ssh设置,允许SSH服务器监听全部网络接口(而不是仅限于本地回环接口localhost,即127.0.0.1)
设置
或
- GatewayPorts clientspecified
复制代码 重启 sshd 服务
- sudo systemctl restart sshd
复制代码 - 在容器内部执行以下命令,创建反向 SSH 隧道:
- autossh -M 6000 -NfR 8990:localhost:22 root@113.44.147.146
复制代码
- autossh: 用于自动维护 SSH 隧道的工具。
- -M 6000: 容器内部监控端口,用于 autossh 监控隧道状态,是否断链 (你可以任意选择其他未被占用的端口)。
- -N: 不执行长途命令,仅创建隧道。
- -f: 在背景运行。
- -R 8990:localhost:22: 创建反向隧道,将公网服务器的 8990 端口转发到 Docker 容器内部的 22 端口。
- root@113.44.147.146: 你的公网服务器用户名和 IP 地址 (请更换成你自己的)。
- 查看端口是否正常监听
- watch -n 1 sudo netstat -tulnp
复制代码 或者
- netstat -tulnp | grep 8990
复制代码 正常环境应该表现
- Active Internet connections (only servers)
- Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name
- tcp 0 0 0.0.0.0:8990 0.0.0.0:* LISTEN 24251/sshd: root
- tcp 0 0 0.0.0.0:6000 0.0.0.0:* LISTEN 24251/sshd: root
复制代码 留意应该是0 0.0.0.0:8990而不应该是127.0.0.1:8990
- (可选,一样平常不用) 设置端口转发 (在你的本地电脑执行)
- 假如你不盼望直接通过公网服务器来毗连容器,你可以在本地电脑设置端口转发,如下所示:
- ssh -L 9000:127.0.0.1:8990 root@113.44.147.146
复制代码 - 该命令表示,将本地的 9000 端口转发到公网服务器上的 8990 端口。如许你就可以在本地电脑使用 ssh -p 9000 user@localhost 来毗连你的容器。
- 从家里的电脑 (机器 C) 毗连:
- 使用 SSH 毗连到公网服务器的 8990 端口, 即可毗连到你的 Docker 容器。
- ssh -p 8990 <容器用户名>@113.44.147.146
复制代码
- 假如你在本地电脑设置了端口转发,你可以使用 ssh -p 9000 <容器用户名>@localhost 毗连。
- 其中 <容器用户名> 是你在 Docker 容器内创建的用户,一样平常是root。
3. 常见问题及解决方案
问题可能原因解决方案公网服务器端口不监听1. ssh -R 命令未正确绑定到 0.0.0.0
2. 公网服务器 sshd_config 中 GatewayPorts 设置不正确1. 使用 ssh -R 0.0.0.0:8990:localhost:22 ... 确保绑定到全部接口。
2. 修改公网服务器 /etc/ssh/sshd_config,设置 GatewayPorts yes
或 GatewayPorts clientspecified
,并重启 sshd 服务 (sudo systemctl restart sshd
)。防火墙阻止毗连1. 公网服务器防火墙阻止了 8990 端口
2. 云服务器安全组规则未开放 8990 端口1. 在公网服务器上开放 8990 端口:
- iptables: sudo iptables -A INPUT -p tcp --dport 8990 -j ACCEPT
- firewalld: sudo firewall-cmd --add-port=8990/tcp --permanent
2. 在云服务器控制台的安全组规则中添加允许 8990 端口的入站规则。SSH 隧道不稳定网络波动导致 SSH 毗连断开使用 autossh 代替 ssh,比方:autossh -M 6000 -NfR 8990:localhost:22 root@113.44.147.146
,-M 参数指定一个端口用于 autossh 监控隧道状态。PyCharm 毗连失败PyCharm 设置错误,毗连信息与隧道设置不匹配仔细检查 PyCharm 中的 SSH 解释器设置:
- Host: 公网服务器 IP (比方 113.44.147.146)
- Port: 公网服务器上反向隧道监听的端口 (比方 8990)
- Username: Docker 容器内的用户名
- Password/Key: Docker 容器内用户的暗码或 SSH 私钥无法通过8990端口毗连到ssh未正确设置反向 SSH 隧道1. 确保已在容器内部执行反向隧道命令。
2. 检查公网服务器的 8990 端口是否处于监听状态:netstat -tulnp | grep 8990
。
3. 确保本地电脑没有防火墙阻止毗连到公网服务器的 8990 端口。容器内部ssh服务不可用容器内没有安装ssh服务,或者ssh服务没有运行1. 进入容器内部,安装 openssh-server
2. 确保ssh服务在容器内部启动,比方 service ssh start 或 systemctl start sshd
3. 更改容器内用户暗码,确保可以使用暗码登录。比方 passwd
。 4. 留意事项
- 端口选择: 你可以使用任意未被占用的端口,但最好选择大于 1023 的端口,避免与体系服务冲突。
- 密钥管理: 妥善保管你的 SSH 私钥,不要将其泄露给他人。
- 长期化: 容器重启后,你需要重新运行 autossh 命令。可以使用 screen 或 tmux 等工具保持会话,或者使用脚本来自动重连,或者将 autossh 命令添加到容器的启动脚本中。
- 依靠容器环境: 确保容器内部有 autossh, openssh-client 以及 ssh server 可以运行,假如不行,可能需要考虑手动上传或 者编译静态版本。
- 防火墙: 确保你的公网服务器防火墙允许 SSH 访问和 8990 端口的访问。
- 设置本地端口转发: 使用本地端口转发可以将公网服务器作为跳板,实现从本地电脑到容器的安全便捷毗连,推荐使用该方案。
- 容器内部ssh服务: 需要确保容器内正确设置了ssh服务,同时设置了用户名,并且允许ssh密钥或者暗码登录。
5. 总结
这个方案可以在你只有 Docker 容器内部权限的环境下,通过公网服务器创建安全的 SSH 隧道,让你在家中轻松访问内网的 Docker 容器。 请务必仔细阅读每个步调,并在操作前做好备份。
参考文献
反向ssh隧道,dokcer没有公网ip:
https://blog.csdn.net/made_in_china_too/article/details/95373985?spm=1001.2101.3001.6650.3&utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7Ebaidujs_baidulandingword%7ECtr-3-95373985-blog-128356067.235%5Ev43%5Epc_blog_bottom_relevance_base6&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7Ebaidujs_baidulandingword%7ECtr-3-95373985-blog-128356067.235%5Ev43%5Epc_blog_bottom_relevance_base6&utm_relevant_index=6
https://zhuanlan.zhihu.com/p/431396699
https://blog.csdn.net/chisuisi5702/article/details/126283977
https://www.cnblogs.com/makefile/p/ssh-rev-tun.html
https://dev59.com/uloU5IYBdhLWcg3wG0Ky
跳板机,假如dokcer有公网ip:
https://www.linuxserver.io/blog/2016-12-02-perform-multiple-ssh-hops-with-ssh-config
https://zhuanlan.zhihu.com/p/53792195
https://blog.csdn.net/github_28260175/article/details/100012157
https://www.cnblogs.com/fbwfbi/p/3702896.html
https://zhuanlan.zhihu.com/p/661802126
https://zhuanlan.zhihu.com/p/398789687
https://www.cnblogs.com/skypanxh/p/18499592
https://blog.csdn.net/qq_39407107/article/details/115468254
https://blog.csdn.net/HLBoy_happy/article/details/123462694
https://www.jianshu.com/p/afe423602ce3
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。 |