
Есть ли способ запуститься ssh
от имени пользователя, которого нет на хосте, инициирующем SSH-соединение?
Допустим, у меня есть удаленный хост с настроенной учетной записью и запущенным sshd. Я могу подключиться к этой машине по ssh с помощью ssh remote-user@remote-host
. Если у меня есть ключи настройки, ssh будет использовать их, а если ни один ключ не подойдет, он запросит у меня пароль. Предположим, что включена аутентификация по паролю.
Допустим, у меня есть образ Docker, вызываемый docker-image
с установленным ssh и другим необходимым программным обеспечением. Я могу запустить контейнер и 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.c:
/* 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 в этом случае без необходимости монтировать host's /etc/passwd
или монтировать поддельный файл passwd или возиться с /etc/passwd
файлом или создавать локального пользователя в образе? Я упускаю какие-либо варианты?
Какая разница, кто является владельцем процесса ssh на клиенте? Есть ли веская причина принудительной проверки локального пользователя или это просто вариант реализации, который приняли разработчики ssh?
решение1
У меня возникла та же проблема: мне нужно было запустить ssh
Docker-контейнер без записи в /etc/passwd
.
Поскольку у меня нет доступа к хосту или прав root внутри самого контейнера, я просто заменил проблемный код...
Предупреждение:Безопасность не является проблемой в моем случае использования, поэтому я полностью согласен на все испортить, пока это работает. Я понятия не имею, вызовет ли это проблемы безопасности в будущем, поэтому, пожалуйста, действуйте на свой страх и риск. Это быстрый и грязный хак, чтобы выполнить работу любой ценой:
Внутри 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;
}