2008年11月6日木曜日

iptablesでお手軽なssh総当りログイン試行攻撃対策

有用だと思ったのでメモ、元ネタチェインつきで。
 

元ネタ
sshへの辞書攻撃をiptablesで防ぐ (曖昧スラッシュ)

の元ネタ
sshへの総当り攻撃をiptablesの2行で防ぐ方法 (blog@browncat.org)

の元ネタ
Block brute force attacks with iptables (Kevin van Zonneveld)
 
 

sshに対する攻撃といえば、ブルートフォースや辞書によるログインの試行が代表的、secureログが汚れるわ最悪ログインされるわと大迷惑(事故?)だ。
そもそも不要な接続は許可しないべきなんだけど、接続元のIPアドレスを限定するという事がしづらい場合もある。
 
 

2行の iptables コマンドでSSH攻撃対策をしよう



※テストに使ったOS,バージョン → CentOS5.2+iptables v1.3.5
recentモジュールが必要なので"/proc/net/ip_tables_matches"ファイルに
recentという行があることを確認

iptablesの簡単設定で、一定時間内に複数回ssh接続してきたIPを自動で拒否するようにできる、という情報を見つけたので記事にする。
以前誰かがfail2ban を設定していたのは見たことある。やれることは大体同じのはずだけど、細かい設定とかを管理したいならそちらがいいかもしれない。
 
 

引用すると下記2行でOK(※ eth0 の部分は環境による)。はみ出した分はどっかにコピペで…
iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --set --name SSH
iptables -A INPUT -i eth0 -p tcp --dport 22 -m state --state NEW -m recent --update --seconds 60 --hitcount 8 --rttl --name SSH -j DROP

これで 60秒間に8回のssh接続を仕掛けてきたIPアドレスからの新規TCPセッションを拒否するようになる。
 

ぱっと見では2行目だけで良さそうな気もするが、recentモジュールの使い方がそうなっているのかな。
これでセーブしておけばOSの起動時にもルール有効になり、対策OK。
ほか、初代の元ネタBlock brute force attacks with iptables (Kevin van Zonneveld) に色々注意事項が書いてある、試すなら cron で iptables をリセットしとけとかは面白い記述。
 
 


攻撃されたことをログに残そう


コレだけだとほんとに転載しただけなので芸が無い、とりあえずログに残るようにしておこう。
また、一つ目の元ネタsshへの辞書攻撃をiptablesで防ぐ (曖昧スラッシュ) によると、デフォルトのINPUTチェインを使うだけでは他の通信に遅延が出る恐れが。確かにそうなるかもしれない。
 
幸い、色々考慮済みの iptables のテーブルが前述の元ネタに紹介されている。折角なので パクリ 再現してみよう。
 

実行するiptables のコマンドは下記、セーブなど考慮して無いので注意。
# ssh接続を取りあえずユーザチェインに渡す
iptables -A INPUT -m state --state NEW -p tcp --dport 22 -j SSH_ACCEPT
 
# SSH_ACCEPTチェインの設定、条件マッチでSSH_BFAチェインに渡す
iptables -A SSH_ACCEPT -m recent --set --name SSH_ACCEPT
iptables -A SSH_ACCEPT -m recent --rcheck --seconds 60 --hitcount 5 --rttl --name SSH_ACCEPT -j SSH_BFA
 
# SSH_BFAチェインの設定、ログに書き出してドロップ
iptables -A SSH_BFA -j LOG --log-tcp-options --log-level 4 --log-prefix 'iptables: ssh_bfa:'
iptables -A SSH_BFA -j DROP

 

で、出来たテーブルがコレ。
OK、元ネタ にほぼそっくりだ。これで遅延無し、攻撃者のIPがログに残るiptablesのルールが完成。
# iptables -L
Chain INPUT (policy ACCEPT)
target prot opt source destination
SSH_ACCEPT tcp -- anywhere anywhere state NEW tcp dpt:ssh
 
Chain SSH_ACCEPT (1 references)
target prot opt source destination
all -- anywhere anywhere recent: SET name: SSH_ACCEPT side: source
SSH_BFA all -- anywhere anywhere recent: CHECK seconds: 60 hit_count: 5 TTL-Match name: SSH_ACCEPT side: source
 
Chain SSH_BFA (1 references)
target prot opt source destination
LOG all -- anywhere anywhere LOG level warning tcp-options prefix `iptables: ssh_bfa:'
DROP all -- anywhere anywhere

閾値は60秒当たり5回になった。ほか recent が update から rcheck になったが違いがよく分からないな。
 

気になるところとしては、LOGのルールがちょっと違う。
「LOG flags」って箇所がよく分からなかった。TCPフラグで判断する仕様なのかと思ったが、手元の iptables の man ではそれっぽいオプションが見当たらなかったので、代わりに tcp-options を入れた。
ログが詳細になったが、意図するところは多分違うかもしれない。