
Docker化的SSH堡垒机🏯,具有强化的默认配置。SSH堡垒机是一种可从互联网访问的跳板服务器,用于访问私有网络中的服务。部署堡垒机后,您可以通过它访问私有网络服务。
更多详情请查看https://github.com/gnzsnz/docker-bastion
按照以下步骤部署运行SSH堡垒机:
data文件夹中复制authorized_keys文件。我们将创建两个用户,并假设他们的/home/user_name/.ssh/authorized_keys已存在bash# 创建主目录 export USERS=devops,bastion mkdir $PWD/data/home/{$USERS}/.ssh # 复制authorized_keys文件示例 cp /home/{$USERS}/.ssh/authorized_keys $PWD/data/{$USERS}/.ssh
data文件夹。这是创建SSH堡垒机所需目录结构的必要步骤,详见准备工作bashdocker run -it --rm --env-file .env \ -v $PWD/data:/data \ gnzsnz/bastion /provision.sh
bashdocker compose up
bashssh -J devops@bastion:22222 devops@remote_host
上述命令指示ssh创建到-J参数指定服务器(此处为devops@bastion:22222)的连接,连接成功后从堡垒机创建到remote_host的另一个连接。从客户端角度看,这就像直接连接到remote_host。
克隆Git仓库作为模板并设置偏好:
bashgit clone https://github.com/gnzsnz/docker-bastion.git cp .env-dist .env nano .env # 编辑环境变量 cp docker-compose.yml-dist docker-compose.yml nano docker-compose.yml # 编辑docker compose文件 docker compose config # 验证compose文件 # 设置authorized keys(假设使用bastion用户) mkdir -p $PWD/data/home/bastion/.ssh cp authorized_keys $PWD/data/home/bastion/.ssh # 运行准备脚本 docker run -it --rm -v $PWD/data:/data --env-file .env \ gnzsnz/bastion /provision.sh # 启动SSH堡垒机 docker compose up -d && docker compose logs -ft
下文将介绍可用的环境变量、如何构建镜像、准备工作的更多细节、如何运行容器、用户访问管理、如何设置SSH客户端、SSH堡垒机的多种使用场景、多因素认证以及证书机构。
.env文件中可用的变量如下:
| 变量 | 默认值 | 描述 |
|---|---|---|
| APT_PROXY | 空 | 定义可选的APT代理以加速镜像构建,格式为http://aptproxy:3142%EF%BC%8C%E5%8F%AF%E5%B0%9D%E8%AF%95%E4%BD%BF%E7%94%A8https://github.com/gnzsnz/apt-cacher-ng |
| SSH_LISTEN_PORT | 22222 | 主机对外发布端口 |
| USERS | bastion | 逗号分隔的用户列表,例如USERS=bastion,devops,准备脚本将创建此变量中定义的用户 |
| USER_SHELL | /usr/sbin/nologin | 必需,用于设置用户shell |
| BANNER_ENABLED | no | 启用SSH横幅,默认显示bastion_banner.txt。要更改横幅需添加挂载点-v path/to/new_banner.txt:/bastion_banner.txt |
| TOTP_ENABLED | no | 启用TOTP,支持Google Authenticator或Microsoft Authenticator |
| TOTP_ISSUER | Bastion | TOTP应用的描述 |
| TOTP_QR_ENCODE | UTF8 | TOTP URI QR的编码方式,使用qrencoder |
| CA_ENABLED | 'no' | 设置为'yes'启用SSH CA模式 |
| SSHD_HOST_CERT | '/etc/ssh/ssh_host_ed25519_key-cert.pub' | CA签名的主机证书,需复制到./data/etc/ssh目录 |
| SSHD_USER_CA | '/etc/ssh/user_ca.pub' | 公共CA密钥,需复制到./data/etc/ssh目录 |
| IMAGE_VERSION | 构建时用于标记镜像的版本 | |
| BASE_VERSION | jammy | Ubuntu基础镜像版本,用于构建 |
设置.env文件后,检查配置是否正确:
bashdocker compose config
确保USERS变量设置了将使用SSH堡垒机的用户。
除环境变量外,还可通过传递命令行参数或设置配置文件修改SSH堡垒机行为,详见运行容器部分。
您可以选择按照以下步骤构建镜像:
bashdocker compose build
如果定义了APT_PROXY,构建过程将使用它加速构建。
可在https://hub.docker.com/r/gnzsnz/bastion%E5%92%8Chttps://github.com/gnzsnz/docker-bastion/pkgs/container/bastion%E8%8E%B7%E5%8F%96%E7%8E%B0%E6%88%90%E7%9A%84%E5%A0%A1%E5%9E%92%E6%9C%BA%E9%95%9C%E5%83%8F%E3%80%82%E7%A4%BA%E4%BE%8Bdocker-compose%E6%96%87%E4%BB%B6%E5%B0%86%E4%BB%8EDocker Hub拉取镜像。
使用容器前,需准备./data主机目录,包含必要数据。可通过运行准备脚本来完成。/data目录包含SSH所需的所有配置、主机和用户密钥以及用户访问权限。准备脚本将执行以下任务:
USERS环境变量创建用户/usr/sbin/nologin(除非您明确了解需求,否则不建议更改)./data绑定挂载已准备,将使用现有文件容器将以只读模式挂载所有这些文件(除非使用TOTP,此时/home需要写权限)
设置authorized keys:
bash# 创建主目录 export USERS=devops,bastion mkdir $PWD/data/home/{$USERS}/.ssh # 复制authorized_keys文件示例 cp /home/{$USERS}/.ssh/authorized_keys $PWD/data/{$USERS}/.ssh
这将复制devops和bastion用户的公钥。
运行准备脚本:
bashdocker run -it --rm --env-file .env \ -v $PWD/data:/data \ gnzsnz/bastion /provision.sh
运行准备脚本后,数据目录将包含运行容器所需的所有数据。注意数据目录的所有者和权限将反映data/etc/passwd中的UID和GID,可能需要sudo进行修改。
如果手动修改data/etc内容,可能需要重新运行准备脚本以更新签名。
编辑docker-compose.yml文件,默认值通常可正常工作。可定义DNS或'extra_hosts',使SSH客户端能够使用服务器名称而非IP地址。
yamlversion: "3.6" services: bastion: build: context: . platforms: - "linux/amd64" - "linux/arm64" - "linux/arm/v7" args: APT_PROXY: ${APT_PROXY} BASE_VERSION: ${BASE_VERSION} IMAGE_VERSION: ${IMAGE_VERSION} image: gnzsnz/bastion:${IMAGE_VERSION}-${BASE_VERSION} restart: unless-stopped ports: - ${SSH_LISTEN_PORT}:22 # 可选 # dns: ${DNS} # extra_hosts: # - host 10.10.0.5 # command: ["-o ForwardX11=yes "] environment: - USERS=${USERS} - USER_SHELL=${USER_SHELL} - TOTP_ENABLED=${TOTP_ENABLED} - TOTP_ISSUER=${TOTP_ISSUER} - TOTP_QR_ENCODE=${TOTP_QR_ENCODE} - CA_ENABLED=${CA_ENABLED} - SSHD_HOST_CERT=${SSHD_HOST_CERT} - SSHD_USER_CA=${SSHD_USER_CA} - BANNER_ENABLED=${BANNER_ENABLED} volumes: - $PWD/data/etc/passwd:/etc/passwd:ro - $PWD/data/etc/shadow:/etc/shadow:ro - $PWD/data/etc/group:/etc/group:ro - $PWD/data/etc/ssh:/etc/ssh:ro - $PWD/data/home:/home:ro
验证所有设置是否正确(是否已设置.env文件):
bashdocker compose config
容器启动时将:
运行容器:
bashdocker compose up -d; docker-compose logs -f
如果手动修改数据目录,可能需要重新运行准备脚本以生成更新的校验和,确保启动时验证通过。
可通过在命令行或docker-compose.yml的command元素中设置参数更改堡垒机行为,任何有效的sshd选项均可使用。上述示例docker文件包含允许X转发的行:command: ["-o ForwardX11=yes "]。
另一种选择是在/data/etc/ssh/sshd_config.d/中添加额外配置,堡垒机将读取这些文件。
堡垒机遵循OpenSSH的认证机制。通常需要为每个用户在authorized_keys文件中设置公钥。从管理authorized_keys文件的角度,更简单的方法是设置证书机构(CA)。这需要额外步骤生成和管理证书,但无需在authorized_keys文件中添加行,也无需为每个主机设置known_host记录,详见证书机构部分。
添加更多用户的最简单方法是编辑.env文件,设置USERS并重新运行准备模式,它将添加到现有/etc/passwd文件并设置authorized keys:
bashdocker run -it --rm -e USERS=new_user,another_user \ -v $PWD/data:/data \ gnzsnz/bastion /provision.sh
禁用现有用户:
bashdocker run -it --rm -v $PWD/data:/data \ gnzsnz/bastion adduser --disable-login user_name
可按照准备工作部分所述添加authorized_keys。
如果已按照本文档操作,现在应该已启动并运行SSH堡垒机容器。您可以通过堡垒机访问SSH服务器。
从简单场景开始,使用-J选项建立连接,或设置ssh配置指定通过ProxyJump连接到server:
bashssh -J devops@bastion_host:22222 devops@server # 如果在~/.ssh/config中设置了ProxyJump ssh devops@server
还可使用scp、rsync、sftp、端口转发或socks代理:
bash# scp scp -J devops@bastion_host:22222 file.gz devops@server:/tmp # 如果在配置文件中设置了ProxyJump,无需使用-J scp file.gz devops@server:/tmp # rsync rsync -rtva devops@server:/tmp/file.gz /tmp # sftp sftp -J devops@bastion_host:22222 file.gz devops@server:/tmp sftp file.gz devops@server:/tmp sftp devops@server # 端口转发(转发发生在服务器上,堡垒机仅作为跳板) ssh -N -L 8888:localhost:80 -J devops@bastion_host:22222 pgsql.example.com # 不使用-J ssh -N -L 8888:localhost:80 devops@pgsql.example.com # 远程转发(将本地:80转发到远程的localhost:8888) ssh -N -R 80:localhost:8888 devops@app.example.com # 如果在配置中设置了本地或远程转发,只需执行 ssh rf_app ssh lf_app # socks代理 ssh -J devops@bastion_host:22222 -D 1337 -f -N devops@server.example.com ssh myproxy
详见下一节客户端设置示例。
一个值得特别注意的场景是作为端口转发的sidecar容器:
>|< _____________ __________ | | 堡垒机容器 | | 客户端 | ---|--- | | ----\ ---------- | ------------- | | _____________ | | | 应用容器 | ---/ | | | | ------------- | >|< 应用到堡垒机:ssh -R 8888:localhost:8888 bastion 客户端到堡垒机:ssh -L 8888:localhost:8888 bastion
在上述场景中,应用需要暴露8888端口但直接暴露不安全(如VNC)。在应用容器中,可安装SSH客户端在SSH堡垒机上创建远程转发,而客户端创建本地转发。注意此时我们直接连接到堡垒机,而非作为ProxyJump使用,这是允许的,因为未打开shell会话。
此场景中,应用容器无需安装sshd服务器,只需SSH客户端。只需将堡垒机端口暴露到互联网。通过适当的SSH客户端配置,两种转发连接都易于设置。应用容器可专注于核心功能,堡垒机容器负责创建安全连接。
可配置~/.ssh/config文件简化客户端命令:
### 堡垒机主机 Host bastion-host-nickname HostName bastion-hostname AddKeysToAgent yes ForwardAgent yes ### 远程主机 Host remote-host-nickname HostName remote-hostname ProxyJump bastion-host-nickname AddKeysToAgent yes ForwardAgent yes # 远程转发示例 Host rf_app Hostname app.example.com ProxyJump bastion-host-nickname # local_host:local_port:remote_host:remote_port # local是SSH客户端视角,remote是SSH服务器可访问的任何主机 RemoteForward localhost:5432 localhost:5432 SessionType none ForkAfterAuthentication yes ExitOnForwardFailure yes IdentitiesOnly yes CertificateFile ~/.ssh/id_ed25519-cert.pub IdentityFile ~/.ssh/id_ed25519 # 本地转发示例 Host lf_pgsql Hostname pgsql.example.com ProxyJump jump_host_nickname # local_host:local_port:remote_host:remote_port # local是SSH客户端视角,remote是SSH服务器可访问的任何主机 LocalForward localhost:5432 localhost:5432 SessionType none ForkAfterAuthentication yes ExitOnForwardFailure yes IdentitiesOnly yes CertificateFile ~/.ssh/id_ed25519-cert.pub IdentityFile ~/.ssh/id_ed25519 # socks动态代理示例 Host myproxy Hostname server.example.com Port 2222 ProxyJump bastion-host-nickname DynamicForward 1337 SessionType none ForkAfterAuthentication yes ExitOnForwardFailure yes IdentitiesOnly yes CertificateFile ~/.ssh/id_ed25519-cert.pub IdentityFile
您可以使用以下命令拉取该镜像。请将 <标签> 替换为具体的标签版本。如需查看所有可用标签版本,请访问 标签列表页面。




探索更多轩辕镜像的使用方法,找到最适合您系统的配置方式
通过 Docker 登录认证访问私有仓库
无需登录使用专属域名
Kubernetes 集群配置 Containerd
K3s 轻量级 Kubernetes 镜像加速
VS Code Dev Containers 配置
Podman 容器引擎配置
HPC 科学计算容器配置
ghcr、Quay、nvcr 等镜像仓库
Harbor Proxy Repository 对接专属域名
Portainer Registries 加速拉取
Nexus3 Docker Proxy 内网缓存
需要其他帮助?请查看我们的 常见问题Docker 镜像访问常见问题解答 或 提交工单
docker search 限制
站内搜不到镜像
离线 save/load
插件要用 plugin install
WSL 拉取慢
安全与 digest
新手拉取配置
镜像合规机制
manifest unknown
no matching manifest(架构)
invalid tar header(解压)
TLS 证书失败
DNS 超时
域名连通性排查
410 Gone 排查
402 与流量用尽
401 认证失败
429 限流
D-Bus 凭证提示
413 与超大单层
来自真实用户的反馈,见证轩辕镜像的优质服务