Windows Serverのsshd設定でハマったメモ
まずは公式ドキュメントに沿ってsshdをインストール/有効化する。
PS> Get-WindowsCapability -Online | Where-Object Name -like 'OpenSSH*'
PS> Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
PS> Start-Service sshd
PS> Set-Service -Name sshd -StartupType 'Automatic'
Windows Serverでのsshd設定は%programdata%\ssh\sshd_config
にあるので、公開鍵認証を有効に設定。ついでにパスワード認証を拒否。
PubkeyAuthentication yes
PasswordAuthentication no
公開鍵を登録するところについては、Windows独自仕様で管理者ユーザーは通常のauthorized_keys
とは異なる場所に登録が必要になるので、指定の場所にファイルを作成。
この時、複数登録したかったので以下のようにしてメモ帳を開いて書き込んだのだが、それが間違いだった。(問題は後述)
# 空のファイルを作って……
管理者PS> echo "" > "$Env:ProgramData\ssh\administrators_authorized_keys"
# メモ帳で開く
管理者PS> notepad "$Env:ProgramData\ssh\administrators_authorized_keys"
書き込みが終わったら、ドキュメントを参考に権限を設定しておく。
管理者PS> icacls.exe "$Env:ProgramData\ssh\administrators_authorized_keys" /inheritance:r /grant "Administrators:F" /grant "SYSTEM:F"
あと、これも必要なのかいまいち理解できていないのだが、Linux等と同様に~/.ssh/authorized_keys
も作成した。
Restart-Service sshd
でsshdを再起動して設定を反映させて、いざ接続……できない。
クライアントマシン> ssh username@winsvrhostname -vvvv
(中略)
debug3: receive packet: type 51
検索するとreceive packet: type 51
はサーバー側で認証エラーらしい。
サーバー側でsshd_config
を修正し、詳細ログを出力するようにして確認。
# Logging
SyslogFacility LOCAL0
LogLevel DEBUG3
上記設定をしてからRestart-Service sshd
でsshdを再起動すると、%programdata%\ssh\logs\sshd.log
が出力されるようになる。
そこを確認すると以下のような怪しい行があった。
debug1: trying public key file __PROGRAMDATA__/ssh/administrators_authorized_keys
debug2: __PROGRAMDATA__/ssh/administrators_authorized_keys:1: check options: '\377\376s'
debug2: __PROGRAMDATA__/ssh/administrators_authorized_keys:1: advance: ''
検索して辿り着いたのがこれ。
Oops: It was a file encoding problem on the authorized_keys file.
横着してadministrators_authorized_keys
をメモ帳で読み書きしていたせいで、文字コードが問題になったのだった……
メモ帳で文字コードを指定する方法はよくわからなかったのと、エディタを導入するのが面倒だったので、powershellで1行ずつ、文字コードを明示して保存した……
cd $Env:ProgramData\ssh
echo "(公開鍵1)" | Out-File -FilePath administrators_authorized_keys -Encoding ascii
echo "(公開鍵2)" | Out-File -FilePath administrators_authorized_keys -Encoding ascii -Append
……
その後、クライアントから再度ssh接続を試みたところ、無事成功。
ちなみに、sshd_config
ファイルはメモ帳で読み書きしても全然平気だった。
教訓:メモ帳は使ってはいけない。
真犯人は下記。
ちゃんと原因を調べた。 直接の原因はメモ帳ではなかった。 メモ帳ごめん。
# ①空のファイルを作って……
管理者PS> echo "" > "$Env:ProgramData\ssh\administrators_authorized_keys"
# ②メモ帳で開く
管理者PS> notepad "$Env:ProgramData\ssh\administrators_authorized_keys"
Powershellでは、 リダイレクトで作ったファイルはUTF-16になる そうだ。
つまり私は①の段階で、空ファイル(0byte)を作っているつもりだったが、普通にBOMつきUTF-16ファイルを作っていた。
それを②メモ帳で開いているので、当然メモ帳は保存するときもUTF-16で保存していた。
エラーメッセージにあったcheck options: '\377\376s'
の\377\376
は255 254
の8進数表記であり、16進数でFF FE
だから、そのまんまUTF-16LEですね……s
は公開鍵の先頭ssh-ed25519 ~
のs
だろう。
ちなみに、
sshd_config
ファイルはメモ帳で読み書きしても全然平気だった。
こちらは、最初からasciiで保存されていたsshd_config
を開いているので、メモ帳でもasciiのまま読み書きできているというだけだ。
犯人は私(共犯者はデフォルトが変なエンコードのpowershell)だった。メモ帳ごめん……
同じハマり方をした!
echo "" > administrators_authorized_keys
として、あとからメモ帳だかVSCodeでコピペしていました。
追試:PSでecho "" > aaa.txtとして、VSCodeで開くと右下に"UTF-16LE"とでる!