😲

なぜ GitHub への 公開鍵認証での SSH は User git で接続できるのか?

2022/02/08に公開2

それは違うよ! とかあればコメントで教えてください。

TL;DR

たぶん SSH 時に送ってる公開鍵で突合してGitHubユーザを特定している

通常(?)の SSH

公開鍵認証で user というユーザで host へ接続したい場合、
host へ公開鍵を ssh-copy-id などで登録しておいた状態で

$ ssh user@host

としますね。
サーバへSSHするときなど皆さんやってるはずです。

GitHub への SSH

GitHub への SSH は少し違います。
User git を使いますね。
(詳しい説明は省きます)

なのに GitHub のアカウントへ公開鍵を登録すれば SSH できます。

$ ssh -T git@github.com
> Hi username! You've successfully authenticated, but GitHub does not
> provide shell access.

これは何故?
ユーザ名を指定して SSH するときはユーザ名がわかるが
全てのユーザが git として SSH してくるとユーザが特定できなくないか?

Twitter で情報をもらった

https://twitter.com/hase_cafesalad/status/1490201463582179329

その謎に迫るため我々は RFC4252 へと向かった

Private keys are often stored in an encrypted form at the client
host, and the user must supply a passphrase before the signature can
be generated. Even if they are not, the signing operation involves
some expensive computation. To avoid unnecessary processing and user
interaction, the following message is provided for querying whether
authentication using the "publickey" method would be acceptable.

byte SSH_MSG_USERAUTH_REQUEST
string user name in ISO-10646 UTF-8 encoding [RFC3629]
string service name in US-ASCII
string "publickey"
boolean FALSE
string public key algorithm name
string public key blob

以下は DeepL で翻訳

秘密鍵は多くの場合、暗号化された形でクライアントに保存されます。ホストで、署名が生成される前にユーザーがパスフレーズを提供する必要があります。 そうでない場合でも、署名操作にはある程度の高価な計算が必要です。 不必要な処理とユーザーとの対話を避けるため、「公開鍵」方式による認証が受け入れられるかどうかを問い合わせるために、次のメッセージが提供されています。

意訳すると「公開鍵方式による認証では署名を送る。署名には以下の情報を含む」って感じでしょうか。
string public key blob とありますね。

つまり、 GitHub は SSH の署名に含まれている公開鍵を使ってユーザに登録されている公開鍵と突合し、ユーザを特定しているのではないかということです。

なるほど。

実際の GitHub の SSH デーモンの実装は分かりませんが、まあそうかもなーという話です。
何か知ってる人がいたら教えてください。

参考

Discussion

angel_p_57angel_p_57

つまり、 GitHub は SSH の署名に含まれている公開鍵を使ってユーザに登録されている公開鍵と突合し、ユーザを特定しているのではないかということです。

ユーザ名ではなく公開鍵で利用者の区別をつけるというのはそれ以外考えられないところですが、「公開鍵で区別」それ自身、特に珍しいことではありません。( もちろんSSHサーバは「利用者が何の鍵を使って認証してきてるか」を、プロトコル的に把握可能です )
一般によく使われるOpenSSHのsshdにも、「同一ユーザで複数の公開鍵をauthorized_keysに登録しておき、公開鍵毎に使えるコマンドやアクセス元として許可するアドレス等を変える」という機能があります。
※「公開鍵毎に~」の機能については、例えば「何気に便利に使えるかもしれない authorized_keys のオプション」という記事でも解説があります。

「なぜユーザ名を区別しないのか」については、以下のtweetで述べた理由だろうと思います。
https://twitter.com/angel_p_57/status/1490195138509152256