金曜日, 6月 06, 2025

nftablesでiptablesのhashlimitの代わりをしようとしたら世の中の情報もChatGPTも間違ってた話

まぁタイトルのとおり。beepcapです。
日本語どころか英語の文献も調べたのに正解がないのでみんなdebian系のnftables真面目に使ってないんじゃないかと思う。

要件

要件は以下の通り。

  • sshへのnewアクセスを制限したい 
  • sshへはipv4以外からのアクセスを遮断している
  • 1時間に5回以上のアクセスを検知したら遮断
  • 遮断判定したIPアドレスは24時間アクセスを拒否

対応

まず、nftables.confのtable inet内にblacklistをsetする。

set ssh_blacklist {
    type ipv4_addr
    timeout 24h
}

そして、さらにchain input 内に処理を追加する。

ip saddr @ssh_blacklist log prefix "Deny SSH access:" drop
tcp dport 22 ct state new limit rate over 5/hour add @ssh_blacklist { ip saddr } log prefix "SSH blocked due to excessive access:" drop

これだけ。良かったね、僕が記事を書いたあとに対応する人は楽で。

説明

まず、setしたblacklistがアクセス過多の相手のIPアドレス(v4)を記録する。timeoutに24hを指定しているので、登録された情報は24hで消去されまたアクセスができるようになる。
set ssh_blacklist {
    type ipv4_addr
    timeout 24h
}
次にsource addrがssh_blacklistに含まれている場合にdropする。
ip saddr @ssh_blacklist log prefix "Deny SSH access:" drop

最後に情報がなかった回数を検出する処理だが、nftはコマンドの連携で成り立つ機能であるため要素を分解して説明する。

今回はssh(port 22)へのアクセスを受信側のportで判定する。

tcp dport 22

次に接続時のstateが新規(TCP SYN)かを確認する。

ct state new

そして、一時間に5回のアクセスを超えているかを確認する。このlimit rateはnftablesの機能であり簡単にiptablesのhashlimitのような対応ができるが、実はこの指定は60sec(たぶん)で自動的に解消されてしまう。なので遮断時間が60secの要件の場合しか使えないのだ。この辺を理解してない記事がwebには非常に多い。overを付けないと5回以下の場合に条件マッチするので注意。

limit rate over 5/hour

これまでの条件に合致したIPアドレスをssh_blacklistに追加する。
add @ssh_blacklist { ip saddr }

ログはおまけ

log prefix "SSH blocked due to excessive access:"

最後にこれらの条件にマッチしたパケットを落とす

drop

とこのようになっている。

考察

そもそもなんでwebにちゃんとした情報がないかを考察する。まずfirewallをCUIで設定している人が少ないのではないか、特にlimit rateの時間制限はまずくてこれで十分としている記事は非常に多いし、limit rateそのものの説明も非常に少ない。最終的に情報として頼れたのはman nftだけであった。hashlimitの採用例が少ない可能性もある。多くの場合過剰アクセスのログインの遮断は認証処理側で行われている場合も多い(webページなど)。
当然の帰結として、ChatGPTも嘘ばかり教えてくれた。役に立たんやつである。

0 件のコメント:

自己紹介

自分の写真
NetRadioDJ ...since 2003, Programer ...since 1994