有没有办法ssh
以启动 ssh 连接的主机上不存在的用户身份运行?
假设我有一个远程主机,其中设置了帐户并正在运行 sshd。我可以使用 ssh 进入该机器ssh remote-user@remote-host
。如果我有设置密钥,ssh 将使用它,如果没有密钥可用,它将提示我输入密码。假设已启用密码验证。
假设我有一个名为docker-image
ssh 的 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:
如果我使用映像中不存在的用户启动容器,则无法使用 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
错误来自ssh配置文件:
/* Get user data. */
pw = getpwuid(getuid());
if (!pw) {
logit("No user exists for uid %lu", (u_long)getuid());
exit(255);
}
该错误消息是有道理的,因为 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
在上面的命令中,据我所知,ssh 所需的文件都不在用户的主目录中。在这种情况下,有没有办法运行 ssh,而不必挂载主机/etc/passwd
或挂载假密码文件或弄乱/etc/passwd
文件或在映像中创建本地用户?我是否忽略了任何选项?
客户端上的 ssh 进程的所有者是谁有什么关系?强制本地用户检查是否有充分的理由,或者这只是 ssh 开发人员采取的一种实现选项?
答案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;
我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;
}