Press "Enter" to skip to content

使用 Docker 搭建 SSH 隧道:打造安全回家的通道

前言

当我们身处咖啡厅、公司或在旅途中时,经常需要访问家里的局域网资源(比如 NAS、内部服务器),或者单纯希望通过家里的宽带 IP 上网以保证数据安全。

相比于搭建复杂的 VPN(如 OpenVPN, WireGuard),SSH 隧道(SOCKS5 代理) 是一种更加轻量级、无需客户端安装额外软件的解决方案。

本文将教你如何使用 Docker 快速部署一个经过特殊配置的 SSH 服务器,无论你身在何处,一条命令即可“回家”。

准备工作

  1. 一台家里的设备:安装了 Docker 的 Linux 服务器、NAS(群晖/威联通)或树莓派。
  2. 公网访问能力
    • 你需要有公网 IP(IPv4 或 IPv6)。
    • 如果不经常变动,直接使用 IP;如果是动态 IP,建议配置 DDNS(动态域名解析)。
    • 注:如果你没有公网 IP,你需要一台云服务器做内网穿透(FRP),这超出了本文范围,但本镜像同样适用作为中转节点。

第一步:编写 Dockerfile

我们需要一个定制化的 SSH 容器。为了支持完整的代理转发功能(包括远程端口转发),我们需要覆盖 Ubuntu 默认的 SSH 配置,并修复 Docker 中特有的 PAM 权限问题。

新建一个文件夹 my-ssh-server,在里面创建文件 Dockerfile

# 基础镜像
FROM ubuntu:latest

# 1. 安装必要的软件
# openssh-server: SSH 服务端
# sudo: 常用工具
# iproute2/net-tools: 调试网络时可能用到(可选)
RUN apt-get update && 
    apt-get install -y openssh-server sudo iproute2 net-tools && 
    rm -rf /var/lib/apt/lists/*

# 2. 创建 sshd 运行目录
RUN mkdir /var/run/sshd

# 3. 设置 root 密码
# 【警告】生产环境强烈建议使用 SSH Key,这里设置密码仅为初始化演示
RUN echo 'root:password' | chpasswd

# 4. 写入自定义 SSH 配置
# GatewayPorts yes: 允许远程转发绑定到非本地地址(关键配置)
# PermitRootLogin yes: 允许 root 登录
# AllowTcpForwarding yes: 允许 TCP 转发(默认为 yes,显式声明更安全)
RUN echo 'GatewayPorts yes' >> /etc/ssh/sshd_config.d/custom_proxy.conf && 
    echo 'PubkeyAuthentication yes' >> /etc/ssh/sshd_config.d/custom_proxy.conf && 
    echo 'PasswordAuthentication yes' >> /etc/ssh/sshd_config.d/custom_proxy.conf && 
    echo 'ChallengeResponseAuthentication yes' >> /etc/ssh/sshd_config.d/custom_proxy.conf && 
    echo 'PermitRootLogin yes' >> /etc/ssh/sshd_config.d/custom_proxy.conf && 
    echo 'AllowTcpForwarding yes' >> /etc/ssh/sshd_config.d/custom_proxy.conf

# 5. 【核心修复】修复 Docker 中 SSH 登录会被踢出的 PAM 问题
RUN sed -i 's@sessions*requireds*pam_loginuid.so@session optional pam_loginuid.so@g' /etc/pam.d/sshd

# 6. 暴露端口
EXPOSE 22

# 7. 启动服务
CMD ["/usr/sbin/sshd", "-D"]

第二步:构建并启动容器

Dockerfile 所在目录下执行构建命令:

docker build -t ssh-proxy-server .

启动容器。为了方便在外部访问,我们将容器的 22 端口映射到宿主机的 2222 端口(或其他非标准端口,避免与宿主机自带的 SSH 冲突)。

docker run -d 
    --name my-proxy 
    --restart unless-stopped 
    -p 2222:22 
    ssh-proxy-server

进阶提示:如果你想让容器直接拥有宿主机的网络能力(比如更容易地扫描局域网设备),可以加上 --net=host 参数(Linux下有效),但此时不需要 -p 参数。

第三步:配置路由器端口转发

这是最关键的一步。你需要登录家里的路由器后台:

  1. 找到 虚拟服务器端口转发 (Port Forwarding) 设置。
  2. 添加一条规则:
    • 外部端口2222 (或者你想用的任何端口)
    • 内部 IP:运行 Docker 的宿主机内网 IP (例如 192.168.1.100)
    • 内部端口2222 (这取决于上一步 docker run 中的映射,如果你映射的是 -p 2222:22,这里内部端口就是 2222)
    • 协议:TCP

配置完成后,你在外网就可以通过 ssh root@你的公网IP -p 2222 访问这个容器了。

第四步:在外网开启“回家模式”

当你带着笔记本在外面时,不需要安装任何 VPN 客户端,只需要打开终端(Terminal 或 PowerShell),输入以下命令:

# 格式:ssh -D [本地代理端口] -N -C [用户名]@[你的公网IP/域名] -p [外部端口]
ssh -D 1080 -N -C root@your.home.ddns.org -p 2222

参数解释:

  • -D 1080: 核心参数。建立一个 SOCKS5 动态代理,监听你笔记本的 localhost:1080
  • -N: 不执行远程命令,只建立连接(如果不加这个,你会进入服务器的 shell,加了则会卡住在终端,代表隧道已建立)。
  • -C: 开启压缩,网速慢时可提升浏览速度。

输入密码后,这个终端窗口会保持连接状态,这就代表隧道通了。

第五步:浏览器/系统配置

现在隧道通了,你需要告诉浏览器走这个隧道。

方案 A:SwitchyOmega (推荐 Chrome/Edge 用户)

安装 SwitchyOmega 插件,新建一个情景模式:

  • 协议:SOCKS5
  • 服务器:127.0.0.1
  • 端口:1080

启用该模式后,你的浏览器流量就会经过家里的宽带发出,你现在就像坐在家里的沙发上一样,可以访问 192.168.x.x 的内网服务,IP 地址也变成了家里的 IP。

方案 B:Firefox 直接设置 (最简单)

Firefox 浏览器自带独立的代理设置:

  1. 设置 -> 常规 -> 网络设置。
  2. 选择“手动代理配置”。
  3. SOCKS 主机:127.0.0.1,端口:1080
  4. 勾选 SOCKS v5
  5. 重要:勾选“使用 SOCKS v5 时代理 DNS 查询”(防止 DNS 污染)。

安全性加固(必读)

上面的教程为了演示使用了密码 root:password,这在公网上是极度危险的。

强烈建议做以下修改:

  1. 生成密钥对:在你的笔记本上运行 ssh-keygen
  2. 挂载公钥:在启动 Docker 时,将你的公钥文件挂载进去,禁用密码登录。

修改启动命令如下:

# 假设你的公钥内容保存在宿主机的 /home/user/my_key.pub
docker run -d 
    --name my-proxy 
    --restart unless-stopped 
    -p 2222:22 
    -v /home/user/my_key.pub:/root/.ssh/authorized_keys:ro 
    ssh-proxy-server

这样,只有持有私钥的电脑才能连接回家,黑客即使扫描到了端口也无法暴力破解密码。

总结

通过 Docker 封装 SSH 服务,我们获得了一个干净、可移植且功能强大的代理服务器。利用 SSH 的 -D 参数,我们轻松实现了:

  1. 加密传输:公共 WiFi 下防止被窃听。
  2. 内网穿透:直接访问家里的 NAS 和局域网设备。
  3. IP 漫游:在任何地方使用家里的 IP 地址。

快去试试吧!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注