TL;DR;
- sshd設定のMatch行のAddress条件は起動時・リロード時チェックが入らない
- 設定に不備があると即ログイン不能になる可能性がある
- Match条件を設定する場合は条件指定した拡張テストで事前確認しよう
はじめに
背景
最近、OpenSSHのsshdで、表題の通りMatch条件の不備で注意を要するケースがありましたので、備忘録として記事にしました。
検証環境
- サーバ
- x86_64 CentOS7.6
- openssh-server-7.4p1-16.el7
- VirtualBox上のVMで動作
- IPアドレス 10.0.0.200/24
- クライアント
- x86_64 Windows10 + WSL + Ubuntu 18.04.2 LTS
- openssh-client 7.6p1-4ubuntu0.3
- IPアドレス 10.0.0.10/24
事例
問題
前提:
サーバ側には、既にrootログインを禁止するためのPermitRootLogin no
の設定を入れているとします。
ここで、一部からはrootログインを許可したいので、sshd_config
ファイルの末尾に次の設定を入れました。
Match Address 10.0.0.8/28
PermitRootLogin without-password
そして、sshd -t
コマンドでテストが通ることを確認して再起動しました。
$ sshd -t # 何も出力されなければテストにパス
$ systemctl restart sshd
質問:
systemctl status sshd
コマンドで見ても、特に動作に問題はないようでした。しかし実はもうトラブルが発生しています。それはどのようなものでしょうか?
※ログインに必要な公開鍵は適宜登録してあるものとします。
解答:
実はこの状態では、誰もどこからもsshログインできなくなっています。
公開鍵認証かパスワード認証か、はたまたrootユーザか一般ユーザかに関わりなく、です。
普通に運用しているところにほんのちょっと追加設定したつもりが、サービス全体がダメになるという悲惨な状況になります。
原因
賢明な皆さんはお気づきでしょうが、Match Address 10.0.0.8/28
という条件設定に問題がありました。
実は、10.0.0.10を含む10.0.0.8~10.0.0.15 のアドレス帯を指定したいという思惑があったのですが、それであれば10.0.0.8/29
とすべきでした。
あるいは/28
に合わせるなら10.0.0.0/28
で、これは 10.0.0.0~10.0.0.15 の範囲 ( 通常 10.0.0.0 はノードのアドレスとして使えないので、実質 10.0.0.1~10.0.0.15 ) を意味します。
※この/28
や/29
の指定は、対象ノードのアドレスのマスク10.0.0.10/24
の/24
とは全く関係ないことに注意が必要です。
sshdは、Match
の設定を見て条件判定を試みるのですが、設定不備により条件のふるい分けができず、どういう設定を反映すればいいか混乱状態に陥って、結果どの接続も拒否する結果になってしまったと言えます。
設定のチェック
しかし、設定の不備ということであれば、起動時であったり、チェック用のコマンドsshd -t
あるいはsshd -T
で引っかからないのか、気になるところかと思います。
ところが実は、Match
でのAddress
の指定は事前チェックされないようなのです。そうでない項目は ( 全部確認したわけではありませんが )、設定の不備を検出してくれるのですが。条件指定内の設定だからチェックされない、ということもなく、です。
[root@cent7]# tail -n 2 /etc/ssh/sshd_config
Match Address 10.0.0.8/29
PermitRootLogin with-pleasure # ハイヨロコンデー
[root@cent7]# sshd -t
/etc/ssh/sshd_config line XXX: unsupported option "with-pleasure".
拡張テストと条件指定
では、なんとかしてこういった条件でも事前チェックする方法はないでしょうか。
流石に**「目視チェックで分からないのが悪い」と言われるようだと辛い**所です。
こんな時は、拡張テストであるsshd -T
に、条件指定の-C
オプションを併用する方法があります。
sshd -T
は、sshd -t
のテストに加え、設定内容のレポートも出力してくれる拡張テストです。
なお、sshd -t
の場合もそうですが、ホスト鍵が正常に読み込めるかどうかの確認まで考えると、root権限でテストを実行するのが望ましいと言えます。
[root@cent7]# sshd -T
port 22
addressfamily any
listenaddress [::]:22
…
続いて-C
は、接続条件を指定するためのオプションです。例えば10.0.0.10
からの接続の時に、どのような設定内容が反映されるのか、次のように確認することができます。
[root@cent7]# tail -n 2 /etc/ssh/sshd_config
Match Address 10.0.0.8/29
PermitRootLogin without-password
[root@cent7]# sshd -T
…
permitrootlogin no
…
[root@cent7]# sshd -T -C addr=10.0.0.10,user=hoge,host=hoge
…
permitrootlogin without-password
…
このように、Matchが正しく設定されていれば、-C
で指定した条件で設定内容がどのように変わるか、見ることができます。
なお、試したい条件は今回IPアドレス(addr)だけですが、それでもuser,hostも何かしら指定する必要があります。
そして、Matchに設定不備がある場合、次のようにテストで引っかかります。さらに-dd
でデバッグレベルを上げておけば、その詳細も分かります。
※不備の概要が"Bad Match condition"(Matchの条件が悪い)で、詳細が"inconsistent mask length for match netowrk …"(マスクの長さがおかしい)
[root@cent7]# tail -n 2 /etc/ssh/sshd_config
Match Address 10.0.0.8/28
PermitRootLogin without-password
[root@cent7]# sshd -T -C addr=10.0.0.10,user=hoge,host=hoge
reprocess config line XXX: Bad Match condition
[root@cent7]# sshd -T -dd -C addr=10.0.0.10,user=hoge,host=hoge
…
debug2: addr_match_list: inconsistent mask length for match network "10.0.0.8/28"
reprocess config line XXX: Bad Match condition
まとめ
ということで、sshdが設定を事前チェックしないケースがあることと、その場合でもチェックを行うための方法を紹介しました。
sshdの設定をミスると、とても影響が大きいことが多いので、こういったケースに限らず、事前チェックには気を付けたいところかと思います。
なお、事前チェックも重要ですが、設定を変更するときはssh接続を何か残した状態で変更を反映して、不備があっても残している接続から復旧操作できるようにしておくということを心がけるのは言うまでもありません。