iptablesで不正なSSH接続をシャットアウト

特にしたいこともないですが某社の月980円なVPSを借りてみました。
バーチャルコンソール快適!


さて、SSH接続を有効にするためにiptablesでこの1行を加えている人は多いと思います。

iptables -I INPUT 1 -p tcp --dport 22 -m state --state NEW -j ACCEPT ;

しかし、公開鍵暗号方式を使っていても、常にブルートフォースアタックを受けているとログもこんな感じになります

Jan 29 19:56:45 www43071u sshd[23611]: Invalid user from 143.90.179.254
Jan 29 19:56:45 www43071u sshd[23612]: input_userauth_request: invalid user
Jan 29 19:56:45 www43071u sshd[23611]: Failed none for invalid user from 143.90.179.254 port 54597 ssh2
Jan 29 19:56:46 www43071u sshd[23611]: Failed password for invalid user from 143.90.179.254 port 54597 ssh2
Jan 29 19:56:46 www43071u sshd[23611]: Failed password for invalid user from 143.90.179.254 port 54597 ssh2
Jan 29 19:56:46 www43071u sshd[23611]: Failed password for invalid user from 143.90.179.254 port 54597 ssh2
Jan 29 19:56:46 www43071u sshd[23612]: Disconnecting: Too many authentication failures for
...以下略

これは1回のpassword認証に失敗したときのログです。
少しはログを清潔に保ちたいので、パケットフィルタリングの力を借ります。

参考

http://www2s.biglobe.ne.jp/~nuts/labo/inti/ipt_recent.html


シェルスクリプトでさくさく書いておきます。


vi iptables.sh

#!/bin/sh

# 現在のフィルタ状態をクリア
iptables -F 

# SSH接続のフィルタリング ---- ここから ----
# 攻撃者のSSH接続パケットは60秒間破棄
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --rcheck --seconds 60 --name Attacker -j DROP
# 攻撃者用ポリシー追加ログに出し
iptables -N AttackerPolicy
iptables -A AttackerPolicy -m recent --set --name Attacker  -j LOG --log-level warn --log-prefix '[Attack]:'
iptables -A AttackerPolicy -j DROP
# SSHフィルタリング(60秒間以内に5回の接続を試みた場合、攻撃者とする)
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -m recent --rcheck --seconds 60 --hitcount 5 --rttl --name SSH -j AttackerPolicy
# SSH接続のフィルタリング ---- ここまで ----

# SSH接続を許容する
iptables -A INPUT -p tcp --dport 22 -m state --state NEW -j ACCEPT ;

# それ以外、何かしら通信できたものについては許容
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# 各種ポリシー設定(INPUTには厳しく、OUTPUTには甘く)
iptables -P INPUT DROP
iptables -P OUTPUT ACCEPT
iptables -P FORWARD DROP

# 追加ルールの記録と再起動
/etc/rc.d/init.d/iptables save
/etc/rc.d/init.d/iptables restart


実行(ルール反映)

chmod 0700 iptables.sh
./iptables.sh


ためしにフィルタリングされるか確認してみる。
puttyでログイン失敗を4回繰り返した後、5回目で規制状態になったようでプロンプトさえ応答しなくなりました。
大体ルールどおりです。ログも見てみましょう。

[root@www43071u ~]# find /var/log | xargs grep '\[Attack\]' | grep 'DPT=22'
/var/log/messages:Jan 29 19:57:00 www43071u kernel: [Attack]:IN=eth0 OUT= MAC=52:54:00:04:30:71:74:8e:f8:38:e4:01:08:00 SRC=143.90.179.254 DST=219.94.224.109 LEN=52 TOS=0x00 PREC=0x00 TTL=113 ID=5437 DF PROTO=TCP SPT=54600 DPT=22 WINDOW=8192 RES=0x00 SYN URGP=0


規制解除後にログインしてiptablesの統計を見た結果がこちらになります

[root@www43071u ~]# iptables -nvxL
Chain INPUT (policy DROP 8 packets, 814 bytes)
    pkts      bytes target     prot opt in     out     source               destination
       2      100 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0           recent: CHECK seconds: 60 name: Attacker side: source
       6      312            tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:22 state NEW recent: SET name: SSH side: source
       1       52 AttackerPolicy  tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:22 state NEW recent: CHECK seconds: 60 hit_count: 5 TTL-Match name: SSH side: source
       5      260 ACCEPT     tcp  --  *      *       0.0.0.0/0            0.0.0.0/0           tcp dpt:22 state NEW
     437    44332 ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0           state RELATED,ESTABLISHED

Chain FORWARD (policy DROP 0 packets, 0 bytes)
    pkts      bytes target     prot opt in     out     source               destination

Chain OUTPUT (policy ACCEPT 378 packets, 66728 bytes)
    pkts      bytes target     prot opt in     out     source               destination

Chain AttackerPolicy (1 references)
    pkts      bytes target     prot opt in     out     source               destination
       1       52 LOG        all  --  *      *       0.0.0.0/0            0.0.0.0/0           recent: SET name: Attacker side: source LOG flags 0 level 4 prefix `[Attack]:'
       1       52 DROP       all  --  *      *       0.0.0.0/0            0.0.0.0/0

それっぽく機能してるようです。


実際は60秒の規制ではなく、1時間とか多めに取ったほうが良い気もします。
一応なりすまし攻撃対策に、-rttlオプションをつけていますが、どれだけ効果を発揮するのかどうかはわかりません。
困ったら対策するとします。