我希望有一个服务器来透明地将传入的 ssh 连接从客户端转发到 docker 容器。这应该包括 scp、git 传输等。这必须与密钥一起使用,密码将被停用。用户不应看到服务器。更新:是的,这实际上意味着用户将不知道有服务器。配置必须完全在服务器上进行!
client -----> server -----> container (actual connection)
client -------------------> container (what the user should see)
所以,给出的是这样的:
user@client$ ssh user@server
user@server$ ssh -p 42 user@localhost
user@container$
但我想要的是这个:
user@client$ ssh user@server
user@container$
我尝试在authorized_keys
文件中使用command="ssh -p 42 user@localhost"
语法,这有点有效,只是在第二个 ssh 连接中,用户必须输入他们的密码,因为身份验证未通过(server
没有私钥user
(。 此外,即使输入密码,此方法也不适用于scp
。
我也听说过tunnel=
命令,但我不知道如何设置它(而且手册页没有多大帮助(。
我在 Arch 上使用 OpenSSH 7.5p1。
把它放在你的~/.ssh/config
文件中:
Host server-container
ProxyCommand ssh server -W localhost:42
然后只需执行以下操作:
ssh server-container
只要您的用户名一致。如果没有,您可以按如下方式指定它们:
Host server-container
ProxyCommand ssh server-user@server -W localhost:42
然后只需执行以下操作:
ssh container-user@server-container
作为奖励,您可以避免使用 ssh 使用docker exec
进入容器。喜欢这个:
ssh -t server docker exec -it <container-id> bash
这就是我现在想出的解决方案。我对第二个键有点不满意,因为它的公共部分将在container
的~/.ssh/authorized_keys
中可见,这稍微破坏了透明度,但除此之外,所有其他事情似乎都有效。
user@server$ cat .ssh/authorized_keys
command="ssh -q -p 42 user@localhost -- "$SSH_ORIGINAL_COMMAND"",no-X11-forwarding ssh-rsa <KEYSTRING_1>
user@server$ cat .ssh/id_rsa.pub
<KEYSTRING_2>
user@container$ cat .ssh/authorized_keys
ssh-rsa <KEYSTRING_2>
client
授权使用其私钥进行server
。然后,服务器使用专用密钥跳转到container
,该密钥仅用于该特定身份验证。我有点担心您可以通过注入一些命令来突破command=
,但到目前为止,我没有发现允许突破的排列。
由于传递$SSH_ORIGINAL_COMMAND
,您甚至可以做scp
和ssh-copy-id
等等。
注意:要禁止ssh-copy-id
,我出于其他原因想要这样做,只需将容器内的user
authorized_keys
设置为不可写。
这将是两部分:
- 直接访问容器
- 使用服务器进行身份验证
直接访问容器
您可以完全绕过与容器的 SSH 连接,但仍然像 SSH连接到容器一样(使用容器中的用户名和~/.ssh/authorized_keys
文件,以及无声"重定向"到容器中,而无需直接访问服务器(。我将假设用户同时存在于服务器和容器中,并且用户名匹配。我们将在此处调用用户ssh_username
。
在服务器上,您将在容器中docker exec
一个 shell(而不是 SSH 到容器中(。将服务器上ssh_username
的外壳设置为如下所示:
/usr/local/bin/docker-shell
:
#!/bin/sh
/usr/bin/docker exec -it -u ${USER} --env SSH_ORIGINAL_COMMAND="${SSH_ORIGINAL_COMMAND}" container_name sh "${@}"
要创建它,您需要执行以下操作:
cat <<"EOF" | sudo tee /usr/local/bin/docker-shell > /dev/null
#!/bin/sh
/usr/bin/docker exec -it -u ${USER} --env SSH_ORIGINAL_COMMAND="${SSH_ORIGINAL_COMMAND}" container_name sh "${@}"
EOF
sudo chmod a+rx /usr/local/bin/docker-shell
服务器身份验证
由于我们不使用密码,也不希望用户在服务器上有 shell,因此我们可以像这样创建用户:
useradd -M -s /usr/local/bin/docker-shell -N -g nogroup ssh_username
mkdir /home/ssh_username
chown ssh_username /home/ssh_username
(使用-M
防止在主目录中创建默认文件,-N
防止创建匹配的组(
现在,您需要对服务器(而不是容器(进行ssh_username
身份验证,但我们不希望必须在两个位置维护authorized_keys
文件。我们将使用 SSH 的AuthorizedKeysCommand
从 Docker 容器中获取它们。
下面介绍了如何在服务器上配置AuthorizedKeysCommand
。编辑服务器的/etc/ssh/sshd_config
文件以添加:
Match User ssh_username
AuthorizedKeysCommandUser some_server_user_with_docker_access
AuthorizedKeysCommand /usr/bin/docker exec -i cat /home/ssh_username/.ssh/authorized_keys
some_server_user_with_docker_access
将替换为server
上docker
组中的用户,因为该用户需要能够在服务器上运行docker exec
。这也可能是ssh_username
,但随后您需要将该用户添加到docker
组,并且您可能不想这样做。