[Linux] SSHのログイン時にIPアドレス制限を行う

ここ数日、SSHへのアタックが急激に増加した関係で特定のIPアドレスからだけログインできるよう対応しました。結論から言うと以下の設定を行うだけです。

特定のIPアドレスのみログインできる

$ sudo vi /etc/hosts.allow
sshd: (許可したいIPアドレス)
$ sudo vi /etc/hosts.deny
sshd: all

/etc/hosts.allowで許可を、/etc/hosts.denyで拒否の設定を行います。これはSSHだけではなく「TCP Wrapper」を利用しているサーバソフトウェアは同じ要領で設定が可能です。

特定のIPアドレスをブロックする

逆にブロックしたい場合には以下のように設定します。

$ sudo vi /etc/hosts.allow
sshd: all
$ sudo vi /etc/hosts.deny
sshd: (拒否したいIPアドレス)

hosts.allow|denyの書式

IPアドレスは半角スペースで区切り複数同時に記述することや、サブネットマスクなどで指定することもできます。

sshd: 192.168.1.1 192.168.1.2
sshd: 192.168.1.1/255.255.255.0

以下のようにIPアドレスの途中までを記述した場合は前方一致となります。

sshd: 192.168.1.

IPアドレスだけではなく.example.comなど接続元のドメインで許可(拒否)もできます。以下の例では後方一致となります。ただしドメインを指定した場合はIPアドレスのみの場合と比べてドメインを調べる処理が加わりますので多少重くなります(よほど大量に来なければ気にするほどではありませんが)

sshd: .ocn.ne.jp

行末にバックスラッシュ()を付けると途中で改行することも可能です。

sshd: 192.168.1.1 192.168.1.2 \
      .ocn.ne.jp

注意点

いずれもファイルに保存した瞬間に設定が適用されるため、間違えた設定をしてしまうと自分でも二度とログインできなくなる可能性があります。設定する際には十分に注意してください。

事のあらまし

今回問題になったのはAWS上に建てている個人サーバです。

相次ぐ大量のログイン試行

CentOSやAmazonLinuxでは/var/log/secureにログイン試行の履歴が記録されるのを定期的に眺めているのですが、よく利用されているであろうユーザー名とポート番号で大量にログインできないかアタックされている形跡を確認できます。

$ sudo cat /var/log/secure | grep 'Invalid user'
Nov 29 08:33:53 ip-172-26-2-234 sshd[382]: Invalid user admin from 1.254.154.42 port 33116
Nov 29 08:33:56 ip-172-26-2-234 sshd[384]: Invalid user sql from 113.247.226.163 port 47636
Nov 29 08:34:03 ip-172-26-2-234 sshd[386]: Invalid user amministratore from 113.111.7.118 port 49948
Nov 29 08:34:12 ip-172-26-2-234 sshd[388]: Invalid user student from 101.69.247.6 port 33930
Nov 29 08:34:17 ip-172-26-2-234 sshd[390]: Invalid user test from 113.118.234.150 port 17245

この手のアタックは日によって波はありますが日常的に来るのでそれ自体は大した話ではないのですが、問題はここ数日で急激に増加した点です。何らかの闇のリストにでも載ったんですかね? 状況確認のため簡単に集計しました。左側の数字がアタック件数、右側が11月の日付です。11月23日から急増しているのがわかりますね。

$ sudo cat /var/log/secure* | grep 'Invalid user' | cut -f2 -d' ' | sort | uniq -c
      1 10
      5 11
      3 12
      5 13
      3 14
      1 15
      5 16
      3 17
      6 19
      2 20
      2 21
   1344 23
    489 24
   4169 26
   1123 27
   3221 28

まぁ……ポート番号はデフォルトの22番から変更しているのですが仮にそれが分かっても次はユーザー名が、ユーザー名がわかっても次はRSA証明書を破るとなると、途方も無い時間がかかるわけなのでそう簡単に破られるとは思えませんが、精神衛生上よろしくないわけです。

対応方法を考える

特定のIPアドレスから大量にアタックが来ているならそいつをブロックすれば良いわけです。話が早い。ところが接続元のIPアドレスの種類を調べるとなんと688種類!

$ sudo cat /var/log/secure* | grep 'Invalid user' | cut -f10 -d' ' | sort | uniq | wc -l
688

IPアドレス毎にどの程度アタックを行っているか確認すると、2163件の攻撃を仕掛けてきているやつが1人いますが、あとは30件未満がずらーと続きます。これだとブロックリスト(ブラックリスト)方式で防ぐのはちょっと現実的ではありません。これまでは空いた時間に人力でブロックリストに登録してたんですけどね。

$ sudo cat /var/log/secure* | grep 'Invalid user' | cut -f10 -d' ' | sort | uniq -c | sort -r
   2163 202.114.107.2
     45 123.142.5.138
     28 82.64.25.166
     28 222.106.160.180
     28 220.76.205.178
     28 201.140.123.130
     28 188.165.245.53
     28 159.89.165.127
     28 157.245.149.151
     28 157.230.54.248
     26 95.68.243.7
     26 95.110.146.12
     (以下略)

ちなみにIPアドレスが割り当てられた国をみるとほぼ海外から。やたらアタック回数が多いのは中国から多い印象ですね。今回もその通りでした。CNが中国、KRが韓国、FRはフランスになります。

$ whois 202.114.107.2 | grep country | head -1
country:        CN

$ whois 123.142.5.138 | grep country | head -1
country:        KR

$ whois 82.64.25.166 | grep country | head -1
country:        FR

$ whois 222.106.160.180 | grep country | head -1
country:        KR

特定のネットワークからだけ許可する

今回は自宅のプロバイダのドメインと、外から接続する時のために踏み台用のサーバだけを許可し、それ以外はすべて拒否する設定をしました。

$ sudo vi /etc/hosts.allow
sshd:  .example.com (踏み台サーバのIPアドレス)
$ sudo vi /etc/hosts.deny
sshd: all

前述の通りほとんどが海外からのアタックですので、日本のプロバイダからのみ接続な状態に制限してやるだけでほぼほぼ防ぐことができるわけです。

また踏み台サーバはバックアップも兼ねています。少なくとも2つの入口を作っておくことで、例えばプロバイダのドメインが急に変わった場合などに、自分自身がログインできなくなる問題も回避しやすくなります。入り口を1つだけに絞るのはなるべく避けた方が安全です。

接続元のドメインを調べる

お使いのルーターなどからグローバルIPを調べた後に、nslookupコマンドを使って逆引きします。xxx.xxx.xxx.xxxの場所に自分のグローバルIPを指定してください。8.8.8.8はGoogleが提供しているDNSです。

$ nslookup xxx.xxx.xxx.xxx 8.8.8.8
Server:     8.8.8.8
Address:    8.8.8.8#53

Non-authoritative answer:
131.174.238.60.in-addr.arpa name = FL1-60-238-174-131.kng.mesh.ad.jp.

この場合は「FL1-60-238-174-131.kng.mesh.ad.jp」がお目当ての値になります。

効果のほどは?

/var/log/secureを観察し、接続を拒否した「refused connect」がログに記録されるようになれば成功です

$ sudo tail -f /var/log/secure
Nov 29 09:10:37 ip-172-26-11-162 sshd[19713]: refused connect from 159.65.144.233 (159.65.144.233)
Nov 29 09:10:44 ip-172-26-11-162 sshd[19725]: refused connect from 124.127.102.1 (124.127.102.1)
Nov 29 09:10:47 ip-172-26-11-162 sshd[19726]: refused connect from terranova.lankacom.net (203.143.20.23)
Nov 29 09:10:51 ip-172-26-11-162 sshd[19727]: refused connect from 211.252.87.246 (211.252.87.246)
Nov 29 09:11:17 ip-172-26-11-162 sshd[19741]: refused connect from 124.127.102.1 (124.127.102.1)
Nov 29 09:11:26 ip-172-26-11-162 sshd[19742]: refused connect from 211.252.87.246 (211.252.87.246)
Nov 29 09:11:49 ip-172-26-11-162 sshd[19744]: refused connect from 124.127.102.1 (124.127.102.1)
Nov 29 09:12:03 ip-172-26-11-162 sshd[19752]: refused connect from 211.252.87.246 (211.252.87.246)
Nov 29 09:12:05 ip-172-26-11-162 sshd[19753]: refused connect from terranova.lankacom.net (203.143.20.23)
Nov 29 09:14:32 ip-172-26-11-162 sshd[19837]: refused connect from 128.199.127.217 (128.199.127.217)
Nov 29 09:15:20 ip-172-26-11-162 sshd[19882]: refused connect from 128.199.127.217 (128.199.127.217)
Nov 29 09:16:06 ip-172-26-11-162 sshd[19897]: refused connect from 128.199.127.217 (128.199.127.217)
Nov 29 09:16:29 ip-172-26-11-162 sshd[19914]: refused connect from 70.45.133.188 (70.45.133.188)
Nov 29 09:16:52 ip-172-26-11-162 sshd[19935]: refused connect from 128.199.127.217 (128.199.127.217)
Nov 29 09:17:39 ip-172-26-11-162 sshd[19943]: refused connect from 128.199.127.217 (128.199.127.217)
Nov 29 09:18:21 ip-172-26-11-162 sshd[19964]: refused connect from 70.45.133.188 (70.45.133.188)
Nov 29 09:18:25 ip-172-26-11-162 sshd[19965]: refused connect from 128.199.127.217 (128.199.127.217)
Nov 29 09:19:11 ip-172-26-11-162 sshd[19982]: refused connect from 128.199.127.217 (128.199.127.217)
Nov 29 09:19:56 ip-172-26-11-162 sshd[19984]: refused connect from 128.199.127.217 (128.199.127.217)
Nov 29 09:20:21 ip-172-26-11-162 sshd[19996]: refused connect from 70.45.133.188 (70.45.133.188)
Nov 29 09:20:42 ip-172-26-11-162 sshd[19997]: refused connect from 128.199.127.217 (128.199.127.217)

バッチリですね👌

おまけ

当初はFail2Banでも入れようかと思ってたんですが、結果的にもっとお手軽な方法に落ち着きました。Fail2Banは素晴らしいツールですが対処療法感ありますしね。