
ssh
SSH 接続を開始するホストに存在しないユーザーとして実行する方法はありますか?
アカウントが設定され、sshd が動作しているリモート ホストがあるとします。 を使用してそのマシンに ssh できますssh remote-user@remote-host
。セットアップ キーがある場合、ssh はそれを使用しますが、キーが機能しない場合はパスワードの入力を求められます。パスワード認証が有効になっていると仮定します。
たとえば、docker-image
ssh とその他の必要なソフトウェアがインストールされた という Docker イメージがあるとします。コンテナを起動して、問題なく ssh を実行できます。ルート ユーザーが存在することに注意してください。
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 に必要なファイルは (私が知る限り) ユーザーのホーム ディレクトリにありません。この場合、ホストをマウントしたり、/etc/passwd
偽の passwd ファイルをマウントしたり、ファイルをいじったり/etc/passwd
、イメージにローカル ユーザーを作成したりせずに、ssh を実行する方法はありますか? 何かオプションを見落としているのでしょうか?
クライアント上の 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;
}