SSHのセキュリティを高めるためのハウツー

 この記事では、SSH(secure shell)サービスのセキュリティを高めるのに役立つ簡単な方法をいくつか紹介する。

 SSHサーバの設定ファイルは/etc/ssh/sshd_configとなっている。このファイルを変更した後は、変更を反映させるためにその都度SSHサービスを起動し直す必要がある。

SSHが接続を待ち受けるポートの変更

 SSHはデフォルトでは22番ポートで接続を待っている。攻撃者はポートスキャナを使ってホストがSSHサービスを実行しているかどうかを把握するが、(nmapを含め)大抵のポートスキャナではデフォルトでは1024以上のポート番号のスキャンは行なわれないため、SSH用のポートを1024以上の番号に変更しておくのが賢明だ。

 具体的には、/etc/ssh/sshd_configファイルを開き、以下のような行を見つけて変更する。

Port 22

 この行でポート番号を変更したら、以下のようにしてSSHサービスを起動し直そう。

/etc/init.d/ssh restart

SSHプロトコル2のみを許可する

 SSHプロトコルには2つのバージョンがあるが、SSHプロトコル1は中間者攻撃(man-in-the-middle attack)悪意のあるデータを挿入される攻撃(insertion attack)などのセキュリティ問題が存在するため、SSHプロトコル2のみを使用する方がずっと安全となっている。具体的には、/etc/ssh/sshd_configの中の以下のような行を変更する。

Protocol 2,1

 この行を「Protocol 2」と変更しよう。

SSH経由のログインを特定のユーザにだけ許可する

 SSH経由でのrootログインは不必要であり、大きなセキュリティリスクにもなるため許可するべきではない。攻撃者がシステムのrootログインを取得してしまうと、通常ユーザのログインを取得した場合よりも大きなダメージを与えることができてしまうことになる。そのためrootユーザにはログインを許可しないようにSSHサーバを設定しよう。そのためには以下のような行を変更する。

PermitRootLogin yes

 上記の行の「yes」を「no」に変更し、サービスを起動し直す。その後は、root以外の登録ユーザとしてログインし、スーパーユーザになりたいときにはsuを使ってrootユーザになるようにしよう。

 なおシステム上でまったく権限を持たないダミーのローカルユーザを作成しておき、SSHでログインする際にはこのユーザを使うようにするのが賢明だ。こうしておくと、そのユーザアカウントを盗まれた場合でもダメージが小さい。ただしこのようなユーザを作成する際には、そのユーザがスーパーユーザになることができるように、そのユーザをwheelグループに必ず登録しておこう。

 SSH経由でのログインを一部のユーザに対してだけ許可したい場合には、sshd_configファイル内でそのようなユーザを指定することができる。例えばanze、dasa、kimyというユーザに対してだけSSH経由でのログインを許可する場合には、sshd_configファイルの末尾に以下のような行を付け足す。

AllowUsers anze dasa kimy

SSHの接続メッセージを変更する

 SSHサービスへ接続してきたユーザに対して見せるための固定のメッセージをカスタマイズすることができる。やり方は簡単で、単にテキストファイルを作成し(例では/etc/ssh-banner.txt)、テキストで何でも好きなメッセージを入れるだけで良い。以下に例を示す。

*********************************************************************
*これは個人用のSSHサービスです。あなたが使用することはできません。*
*すぐに退去してください。 *
*********************************************************************

 編集が完了したら、ファイルを保存する。そしてsshd_configファイルの中の以下のような行を編集する。

#Banner /etc/issue.net

 上記の行をコメントの外に出して有効にし、パスを自分のSSHメッセージ用テキストファイルのパスに変更しよう。

公開鍵認証を使用する

 SSH認証にログイン名とパスワードを使用する代わりに、公開鍵を使用して認証を行なうこともできる。なおログイン名による認証と公開鍵による認証とは並行して利用することもできる。公開鍵認証を利用すると、SSHを利用してログインする際にログイン名とパスワードとが必要なくなるため、システムを辞書攻撃から守ることができるようになる。公開鍵認証を使ってSSHでログインする際は、ログイン名とパスワードではなく、2つのDSA鍵(公開鍵と秘密鍵)が必要となる。秘密鍵は自分のマシン上に置き、公開鍵はコピーをサーバ上に置いておく。ユーザがSSHセッションにログインしようとすると、サーバはそれらの鍵を使って認証を行ない、認証に成功するとシェルが利用可能になる。逆に認証に失敗すると接続が切断される。

 以下の例では、私用のクライアントマシン(このマシンからサーバへ接続する)を「station1」、サーバマシンを「server1」としている。またどちらのマシンにも同じホームディレクトリがあることを前提としていて、クライアントマシン上とサーバマシン上とでホームディレクトリが異なっている場合にはうまく行かない。

 それではまずはじめに、クライアントマシン上でコマンド「~$ ssh-keygen -t dsa」を使って秘密鍵と公開鍵を生成しよう。なお秘密鍵用のパスフレーズを入力するよう求められるが、(これは推奨されていない方法だが)何も入力しないままにすることもできる。ssh-keygenを実行すると秘密鍵は~/.ssh/id_dsaに、公開鍵は~/.ssh/id_dsa.pubにそれぞれ生成される。

 次に、~/.ssh/id_dsa.pubの内容をserver1上の~/.ssh/authorized_keysファイルにコピーする。~/.ssh/id_dsa.pubファイルの中身は、以下のようなものになっているはずだ。

~$ cat .ssh/id_dsa.pub
ssh-dss AAAAB3NzaC1kc3MAAACBAM7K7vkK5C90RsvOhiHDUROvYbNgr7YEqtrdfFCUVwMWcJYDusNG
AIC0oZkBWLnmDu+y6ZOjNPOTtPnpEX0kRoH79maX8NZbBD4aUV91lbG7z604ZTdrLZVSFhCI/Fm4yROH
Ge0FO7FV4lGCUIlqa55+QP9Vvco7qyBdIpDuNV0LAAAAFQC/9ILjqII7nM7aKxIBPDrQwKNyPQAAAIEA
q+OJC8+OYIOeXcW8qcB6LDIBXJV0UT0rrUtFVo1BN39cAWz5puFe7eplmr6t7Ljl7JdkfEA5De0k3WDs
9/rD1tJ6UfqSRc2qPzbn0p0j89LPIjdMMSISQqaKO4m2fO2VJcgCWvsghIoD0AMRC7ngIe6btaNIhBbq
ri10RGL5gh4AAACAJj1/rV7iktOYuVyqV3BAz3JHoaf+H/dUDtX+wuTuJpl+tfDf61rbWOqrARuHFRF0
Tu/Rx4oOZzadLQovafqrDnU/No0Zge+WVXdd4ol1YmUlRkqp8vc20ws5mLVP34fST1amc0YNeBp28EQi
0xPEFUD0IXzZtXtHVLziA1/NuzY= anze@station1.example.com

 server1上に ~/.ssh/authorized_keysファイルがすでに存在する場合には、~/.ssh/id_dsa.pubファイルの内容を~/.ssh/authorized_keysファイルに追加するようにする。その後は、server1上の~/.ssh/authorized_keysファイルのパーミッションを適切に設定するだけだ。

~$ chmod 600 ~/.ssh/authorized_keys

 ここで、DSA鍵認証を利用するようにsshd_configファイルを設定する。以下の3行を必ずコメントの外に出して有効になるようにしよう。

RSAAuthentication yes
PubkeyAuthentication yes
AuthorizedKeysFile %h/.ssh/authorized_keys

 次にSSHサービスを起動し直す。すべて正しく設定できていれば、SSH経由で、ログイン名とパスワードを入力することなく、サーバ上の自分のホームディレクトリに直行できるはずだ。

 DSA鍵認証のみを行ないたい場合には、sshd_configのPasswordAuthenticationをコメントの外に出して有効にし、「yes」を「no」に変更すれば良い。

PasswordAuthentication no

 なおサーバ上に公開鍵がない人がSSHサービスに接続しようとした場合には、ログインプロンプトの表示さえも行なわれずに、以下のようなエラーメッセージが出て接続が拒否される。

Permission denied (publickey).

TCP wrappersを利用して特定のホストからの接続だけを許可する

 この方法は、ネットワーク上の特定のホストからのSSHサービスへの接続だけを許可したいが、iptablesを使ったりiptablesの設定を乱雑にするのは嫌だという場合に便利だ。iptablesの代わりとして、TCP wrappersを用いることができる。この場合、sshdをTCP wrappersで保護することになる。以下では、ローカルのサブネット192.168.1.0/24上のホストとリモートホスト193.180.177.13のみがSSHサービスに接続できるように設定する。

 TCP wrappersではデフォルトでは、まず最初に/etc/hosts.denyファイルを見てアクセスしてきたホストがそのサービスについて拒否されていないかどうかを確認し、拒否されていた場合には/etc/hosts.allowファイルを見て、そのホストを許可する規則がないかどうかを確認する。そこでまず、以下のような規則を/etc/hosts.denyファイル内に作成する。

sshd: ALL

 これによりデフォルトでは、すべてのホストがSSHサービスへのアクセスを禁止されることになる。この規則が必要なのは、TCP wrappersではまず最初にhosts.denyファイルを見て、SSHサービスの拒否についての規則がない場合には、どのホストもSSH接続できてしまうからだ(つまり、この規則を作成しなければ、SSHサービスに対しすべてのホストがアクセス可能となってしまう)。

 次に/etc/hosts.allowの中に、(前述した)各ホストのみがSSHサービスを利用できるようにするための規則を作成する。

sshd: 192.168.1 193.180.177.13

 これで、192.168.1.0/24ネットワーク内のホストと193.180.177.13ホストのみがSSHサービスへアクセスすることが可能になった。それ以外のホストは、ログインプロンプトの表示さえされずに接続が切断され、以下のようなエラーメッセージを受け取ることになる。

ssh_exchange_identification: Connection closed by remote host

iptablesを使って特定のホストの接続を許可する

 SSHでの接続を制限する方法としては、TCP wrappersの代わりにiptablesを使うという方法もある(両方を同時に利用することも可能)。以下に、特定のホストに対してだけSSHサービスを許可するための簡単な例を示す。

~# iptables -A INPUT -p tcp -m state --state NEW --source 193.180.177.13 --dport 22 -j ACCEPT

 次に、上記のホスト以外のホストからはSSHサービスへアクセスできないようにしよう。

~# iptables -A INPUT -p tcp --dport 22 -j DROP

 これらのルールを保存すれば設定は完了だ。

一定時間内のSSHアクセス数を制限する

 iptablesのまた別のパラメータを使用すると、一定時間内のSSHサービスへの接続数を制限することもできる。以下のすべての例において、/second(秒)、/minute(分)、/hour(時間)、/day(日)の各スイッチを利用することができる。

 最初の例では、ユーザが不正なパスワードを入力した場合に、SSHサービスへのアクセスを1分間拒否する。そしてそれ以降そのユーザは1分間に1回しかログインのチャンスが与えられなくなる。

~# iptables -A INPUT -p tcp -m state --syn --state NEW --dport 22 -m limit --limit 1/minute --limit-burst 1 -j ACCEPT
~# iptables -A INPUT -p tcp -m state --syn --state NEW --dport 22 -j DROP

 2つめの例では、iptablesによりSSHサービスに接続できるのは193.180.177.13ホストのみと設定されている。そしてログインが3回失敗すると、iptablesはそのホストに対し1分間に1回のログインのチャンスしか与えない。

~# iptables -A INPUT -p tcp -s 193.180.177.13 -m state --syn --state NEW --dport 22 -m limit --limit 1/minute --limit-burst 1 -j ACCEPT
~# iptables -A INPUT -p tcp -s 193.180.177.13 -m state --syn --state NEW --dport 22 -j DROP

まとめ

 以上のような機能は、設定するのは決して困難なことではないにも関わらず、SSHサービスをセキュアにするための非常に効果的なテクニックとなっている。たったこれだけで夜によく眠れるようになるのだから、試してみる価値は十分にあるだろう。

NewsForge.com 原文