侵入防御
fail2ban のような侵入防御です。ログからブルートフォース攻撃を見つけ、使っていないポートにおとりを置き、ポートスキャンを数え、悪意のある IP をブロック一覧に追加して、システムファイアウォール(nftables)に同期し、カーネルでその通信をすべて破棄します。
機能
- ログルール:ログファイル、systemd ジャーナル、コマンド出力(OpenWrt の
logread -fなど)、Docker コンテナのログを読み、正規表現で失敗記録を見つけ、集計期間内に回数に達した IP をブロックします。SSH、Dropbear、Nginx、Vaultwarden、Home Assistant、Proxmox VE などのテンプレートを内蔵し、ルール編集時にログのサンプルを貼り付けてテストできます; - Gately イベント:管理画面のログイン失敗と WAF のブロックもルールのソースにでき、正規表現は不要です;
- おとりポート:このホストで使っていないポート(既定は 23、135、1433、3389、5900、6379 など)におとりを置き、接続してきた送信元をすぐにブロックします;
- ポートスキャン検出:同じ送信元が 1 分間にこのホストの開いていないポートへしきい値を超えて接続するとブロックします;
- 統一されたブロック一覧:手動ブロック(CIDR ネットワークと永久ブロックに対応)と Web サービスの認証失敗による自動ブロックをここで管理します。ブロックは保存され、再起動後に復元されます;
- 段階的ブロック:同じアドレスが 30 日以内に再びブロックされると期間が倍になります(上限あり);
- ホワイトリスト:LAN、ループバック、100.64.0.0/10(Tailscale)、このホストのインターフェースがある IPv6 /64 は既定で無視します(ブロックは /64 単位のため、同じ LAN のグローバル IPv6 機器が巻き添えになりません)。IP やネットワークを追加でき、ホワイトリストの単一の IPv6 アドレスはその /64 全体を保護します。
適用範囲
| 環境 | ブロックの効果 | おとりポート | ポートスキャン検出 |
|---|---|---|---|
Linux(root または CAP_NET_ADMIN、nftables をインストール済み) | SSH、他のプログラム、Docker コンテナや LAN 機器へ転送される通信も含め、すべてカーネルで破棄 | カーネルで処理し、SYN だけのスキャンも検出 | 利用可 |
Docker(host ネットワーク + cap_add: NET_ADMIN) | 同上。ルールはホストに書き込まれます | 同上 | 利用可 |
| fnOS パッケージ、OpenWrt 22.03 以降 | 同上(root で動作し、nftables は標準搭載) | 同上 | 利用可 |
| その他(Windows、macOS、FreeBSD、nftables や権限のない Linux) | Gately 自身のサービス(ポート転送、Web サービス、STUN、WebDAV、FTP、管理画面)にのみ適用 | Gately が待ち受け、ハンドシェイクを完了した接続のみ検出 | 利用不可 |
ページ上部にファイアウォール同期の状態が表示され、利用できない場合は原因と対処方法が表示されます。
ファイアウォールルール
「システムファイアウォールに同期」をオンにすると、Gately は nftables に専用の inet gately テーブルを作成し、システム既存のルール(fw4、Docker、ufw など)は変更しません:
preroutingチェーン(優先度 -190、コネクショントラッキングの後、宛先 NAT の前)でブロック中のアドレスから届くパケットを破棄します。このホスト宛ても、コンテナや LAN 機器への転送も破棄されます。このホストから開始した接続(DNS やパッケージミラーへのアクセスなど)の応答は、相手のアドレスがブロックされていても通常どおり通します。IPv6 は /64 単位でブロックします;inputチェーンはこのホスト宛ての新しい接続だけを見て、おとりポートとスキャン検出に使います。ホワイトリストのアドレスは対象外です;- 同期をオフにするか Gately を停止するとテーブルごと削除されます。他のプログラムに削除された場合は 10 秒以内に書き直します。
ページの「ルールを表示」で現在のルール全体を確認できます。
Docker でのデプロイ
ルールをホストに書き込むには network_mode: host と NET_ADMIN の付与が必要です:
network_mode: host
cap_add:
- NET_ADMIN付与しない場合も、ブロックは Gately 自身のサービスに適用されます。ホストのログを読むにはログのディレクトリをコンテナにマウントします。例えば - /var/log:/var/log/host:ro とし、ルールには /var/log/host/auth.log と入力します。systemd ジャーナルのソースはコンテナ内では使えません。
ログルール
| ソース | 入力内容 | 説明 |
|---|---|---|
| ログファイル | ファイルパス(1 行に 1 つ) | ファイル末尾から追加分を読み、ローテーション(名前変更や切り詰め)に追従 |
| systemd ジャーナル | ssh.service などのサービスユニット | journalctl -f で読み取り |
| コマンド出力 | logread -f などのコマンド 1 つ | 終了すると自動で再起動 |
| Docker コンテナ | コンテナ名 | Docker 管理モジュールの接続先 Docker から読み取り |
| Gately イベント | 管理画面のログイン失敗 / WAF ブロック | イベントに送信元 IP が含まれるため、フィルターは不要 |
フィルターは Go の正規表現(RE2 構文)で、1 行に 1 つ、<HOST> が送信元アドレスを表します。例:
Failed password for (?:invalid user )?\S* ?from <HOST>「除外」に一致した行は数えません。集計期間、失敗回数、ブロック期間はルールごとに設定でき、ブロック期間は既定・カスタム・永久から選べます。
ポートスキャン検出のトレードオフ
スキャン検出が数えるのは、このホストで待ち受けていないポートへの新しい接続です。待ち受け中の TCP ポートは 10 秒ごとに更新され、開放扱いになります。他のファイアウォールルールで転送されるポートは input チェーンを通らないため数えません。しきい値の既定は毎分 12 回です。通常のクライアントが閉じたポートを再試行するのは毎分約 5 回なので、10 未満にはしないでください。
おとりポートのうち待ち受け中のものは自動で除外され、正規の訪問者をブロックしないようにしています。
Web サービスとの関係
Web サービスの「認証失敗時のブロック」によるブロックも同じブロック一覧に入るため、ファイアウォール同期をオンにするとホスト全体に適用され、Web サイトだけに限られなくなります。「LAN アドレスを無視」がオンなら LAN のアドレスは自動でブロックされません。
Web サービスと WAF が実際のクライアントアドレスを知る手段は PROXY プロトコルだけです。CDN 経由で実 IP をヘッダーで渡すサイトでは、認証失敗ブロックと「WAF ブロック」ルールが CDN のノードをブロックしてしまうため、そのようなサイトでは有効にしないでください。
通知
ブロックすると「侵入防御:IP をブロックしました」イベントが発生し、通知センターで購読できます。おとりポートとスキャン検出が同じチェックでブロックした複数のアドレスは 1 件の通知にまとめられます。
検証
fnOS(Debian 12、nftables 1.0.6)と iStoreOS 24.10(nftables 1.1.1)の独立したネットワーク名前空間で検証しました。おとりポートとスキャン検出(IPv4 と IPv6)はカーネルでブロックしてブロック一覧に取り込まれ、ログファイル(ローテーションを含む)、systemd ジャーナル、Docker コンテナのログ、管理画面のログイン失敗のいずれでもブロックが発動しました。手動のネットワーク・永久ブロック、解除、段階的な期間、再起動後の復元、外部から削除されたテーブルの書き直し、停止時のルール削除も期待どおりでした。NET_ADMIN のない Docker コンテナは権限不足と判定され、ユーザー空間のおとりポートに切り替わります。