ipt_hashlimit によるブルートフォース防御を ufw と併用する

自宅サーバへのブルートフォースアタックに関しては去年の 8 月に 問題提起 しておきながら、iptables の動的な書き換えによる防御は結局導入しなかった (えー)。理由は ufw との共存方法がわからなかったから。(^^;;
で、再び気になってちょっと調べてみると、何のことはない /var/lib/ufw/user.rules と /etc/ufw/{before,after}.rules に iptables-save 形式で書いてあるだけだ。ufw コマンドは裏で /var/lib/ufw/user.rules ファイルを読み書きするから、こちらを手で編集しても ufw コマンドが理解できない内容は失われてしまう。自前のルールを追加したければ /etc/ufw/{before,after}.rules を編集すればよい。
で、肝心のブルートフォース対策の方は、ログファイルを読んで動的にルールを追加するシェルスクリプトガリガリ書かなくても、iptables の recent モジュールか hashlimit モジュールを使えば静的なルールとして書けちゃうっぽい。なーんだ、こんな簡単になったなら教えてくれよ ヽ(`Д´)ノ *1
というわけで /etc/ufw/before.rules を編集。ufw-before-input チェインの最後の方に 2 行追加。*2

# deny SSH brute force attack
-A ufw-before-input -m hashlimit \
                    --hashlimit 1/minute \
                    --hashlimit-burst 5 \
                    --hashlimit-name sshbruteforce \
                    --hashlimit-mode srcip \
                    --hashlimit-htable-expire 600000 \
                    -p tcp --dport 22 -j ACCEPT
-A ufw-before-input -p tcp --dport 22 -j DROP

したら ufw を再起動。iptables にルールが追加されてることを確認。

$ /etc/init.d/ufw restart && iptables -L
(前略)
Chain ufw-before-input (1 references)
target prot opt source   destination 
ACCEPT all  --  anywhere anywhere    
ACCEPT all  --  anywhere anywhere    ctstate RELATED,ESTABLISHED 
(中略)
ACCEPT tcp  --  anywhere anywhere    limit: avg 1/min burst 5 mode srcip htable-expire 600000 tcp dpt:ssh 
DROP   tcp  --  anywhere anywhere    tcp dpt:ssh 
(後略)

この設定だと *3

  1. ある IP から 5 回つづけて接続要求 (SYN パケット) が来ると、以降同 IP からの接続要求が規制される。
  2. 規制中は 1 分に 1 回の割合でしか接続要求を受け付けない。
  3. 同 IP から 600000 ミリ秒間 (10 分間) 接続要求がなければ規制は解除される。

当然、自分が外からログインする場合も 5 回失敗すると 1 分間閉め出される。まぁ鍵認証だからそもそも失敗しないし、問題ないだろう。

*1:てめえのアンテナが低いだけです

*2:実際には行継続はできないっぽいです。「\」を除いて 1 行で書きましょう

*3:この説明は言葉足らずです。詳しくは参考文献の 2 番目を熟読のこと