以不存在/虚拟用户身份运行 ssh

Pra*_*obo 5 ssh openssh

有没有办法ssh以启动 ssh 连接的主机上不存在的用户身份运行?

假设我有一个远程主机,并设置了帐户并运行 sshd。我可以使用 ssh 进入该机器ssh remote-user@remote-host。如果我有设置密钥,ssh 将使用它,如果没有密钥起作用,它会提示我输入密码。假设启用了密码身份验证。

假设我有一个名为docker-imagessh 的 Docker 映像,并安装了其他所需的软件。我可以毫无问题地启动容器和 ssh。请注意,root 用户存在。

hostname$ docker run -it --rm docker-image bash
container-id$ whoami
root
container-id$ ssh remote-user@remote-host
remote-user@remote-host's password: 
Run Code Online (Sandbox Code Playgroud)

如果我使用映像中不存在的用户启动容器,则无法使用 ssh 连接到远程主机。

hostname$ docker run -it --rm -u 1234:100 docker-image bash
container-id$ whoami
whoami: cannot find name for user ID 1234
container-id$ ssh remote-user@remote-host
No user exists for uid 1234
container-id$ echo $?
255
Run Code Online (Sandbox Code Playgroud)

错误来自ssh.c

    /* Get user data. */
    pw = getpwuid(getuid());
    if (!pw) {
        logit("No user exists for uid %lu", (u_long)getuid());
        exit(255);
    }
Run Code Online (Sandbox Code Playgroud)

该错误消息是有道理的,因为 ssh 使用用户主目录中的 sshconfig、keys、knownhosts 等文件,但我认为当用户为这些文件指定不同的位置时,人们会期望它能够工作,如下所示。

ssh -vvv -i /dev/null  -F /dev/null   \
         -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null      \
         -o PubkeyAuthentication=no  -o PreferredAuthentications=password \
         -o PasswordAuthentication=yes
    remote-user@remote-host
Run Code Online (Sandbox Code Playgroud)

在上面的命令中,ssh 需要的文件(据我所知)都不在用户的主目录中。在这种情况下,有没有一种方法可以运行 ssh,而无需安装主机/etc/passwd或安装假密码文件或弄乱/etc/passwd文件或在映像中创建本地用户?我是否忽略了任何选择?

客户端上 ssh 进程的所有者是谁有什么关系呢?强制本地用户检查是否有充分的理由,或者这只是 ssh 开发人员采用的一个实现选项?

Fab*_* N. 1

所以我遇到了同样的问题:我需要ssh从 docker 容器内部运行,而无需在/etc/passwd.

由于我无法访问主机,也无法访问容器本身内部的根访问权限,所以我只是继续替换有问题的代码......


警告:在我的用例中,安全性不是问题,所以只要它能正常工作,我完全可以接受把事情搞砸。我不知道这是否会导致安全问题,因此请自行承担风险。这是一个不惜一切代价完成工作的快速而肮脏的黑客:


在里面ssh.c我将调用替换getpwuid(getuid())为:

/* Get user data without using getpwuid
 * to run ssh inside a docker container 
 * without a valid passwd entry for the current user
 */
struct passwd fake_user_data = {
    .pw_name = "ssh",
    .pw_passwd = "",
    .pw_uid = getuid(),
    .pw_gid = getgid(),
    .pw_gecos = "",
    .pw_dir = getenv("HOME"),
    .pw_shell = getenv("SHELL")
};

/* pw = getpwuid(getuid()); */
pw = &fake_user_data;
Run Code Online (Sandbox Code Playgroud)

misc.c我修改了tilde_expand_filename

path = strchr(filename, '/');
struct passwd fake_user_data = {
    .pw_dir = getenv("HOME")
};
if (path != NULL && path > filename) {          /* ~user/path */
    ...
} else if ((pw = getpwuid(uid)) == NULL) {
    /* bypass missing passwd entry...
       fatal("tilde_expand_filename: No such uid %ld", (long)uid); */

    pw = &fake_user_data;
}
Run Code Online (Sandbox Code Playgroud)