
NFtablesまたはIPtables上でQ-Feedsを直接実装するスクリプト
Linux サーバー向けの自動マルウェア IP ブロックリスト — nftables と iptables+ipset をサポート
tip.qfeeds.com で無料の API キーを取得してください。
git clone https://github.com/Q-Feeds/NFtables-IPtables-integration-script.git
cd NFtables-IPtables-integration-script
chmod +x qfeeds-installer.sh qfeeds-uninstaller.sh
sudo ./qfeeds-installer.sh
インストーラーは以下を実行します:
サーバーは保護されました。cron ジョブは 20 分ごと(設定可能)に更新を確認し、実際の API 呼び出しはライセンスが許可する場合にのみ行われます。
このソリューションは、Q-Feeds から最新の脅威インテリジェンスフィードを定期的にダウンロードし、ファイアウォールルールとして適用します(ステップバイステップガイド:NFtables/IPtables セットアップ)。これにより、以下が可能になります:
インストーラーは利用可能なファイアウォールバックエンドを自動検出します:
| 優先度 | 検出 | バックエンド |
|---|---|---|
| 1 番目 | nft コマンドが見つかる | nftables |
| 2 番目 | iptables コマンドが見つかる | iptables+ipset |
| — | どちらも見つからない | エラー(終了) |
検出されたバックエンドは設定ファイルに保存されます。アップデーターとアンインストーラースクリプトはこれを使用して正しいファイアウォールコマンドを実行します。
両方のバックエンドは最大パフォーマンスのために同じ分割セット戦略を使用します:
nftables バックエンド:
┌─────────────────────────────────────────────────────────┐
│ table ip qfeeds │
│ │
│ ┌─────────────────────────┐ ┌───────────────────────┐ │
│ │ qfeeds_blacklist_v4 │ │ qfeeds_blacklist_v4 │ │
│ │ (hash set) │ │ _nets (interval set) │ │
│ │ │ │ │ │
│ │ Individual IPs │ │ CIDR ranges │ │
│ │ ~99% of entries │ │ ~1% of entries │ │
│ │ O(1) lookup & insert │ │ O(log n) lookup │ │
│ └─────────────────────────┘ └───────────────────────┘ │
│ │
│ ┌─────────────────────────┐ │
│ │ qfeeds_whitelist_v4 │ │
│ │ (interval set) │ │
│ │ Your allowed IPs/CIDRs │ │
│ └─────────────────────────┘ │
│ │
│ chain input-chain (hook input, priority 0, accept) │
│ → ip saddr @qfeeds_whitelist_v4 accept │
│ → ip saddr @qfeeds_blacklist_v4 drop │
│ → ip saddr @qfeeds_blacklist_v4_nets drop │
│ │
│ chain output-chain (if enabled) │
│ → ip daddr @qfeeds_whitelist_v4 accept │
│ → ip daddr @qfeeds_blacklist_v4 drop │
│ → ip daddr @qfeeds_blacklist_v4_nets drop │
└─────────────────────────────────────────────────────────┘
iptables+ipset バックエンド:
┌──────────────────────────────────────────────────────────┐
│ ipset sets │
│ │
│ ┌─────────────────────────┐ ┌────────────────────────┐ │
│ │ qfeeds_blacklist_v4 │ │ qfeeds_blacklist_v4 │ │
│ │ (hash:ip) │ │ _nets (hash:net) │ │
│ │ maxelem 1000000 │ │ maxelem 65536 │ │
│ │ │ │ │ │
│ │ Individual IPs │ │ CIDR ranges │ │
│ └─────────────────────────┘ └────────────────────────┘ │
│ │
│ ┌─────────────────────────┐ │
│ │ qfeeds_whitelist_v4 │ │
│ │ (hash:net) │ │
│ └─────────────────────────┘ │
│ │
│ iptables: INPUT/OUTPUT jump to a dedicated chain │
│ (jump rule tagged -m comment "qfeeds"): │
│ │
│ chain QFEEDS_INPUT (rebuilt each run, in order): │
│ -m set --match-set whitelist_v4 src -j ACCEPT │
│ -m set --match-set blacklist_v4 src -j DROP │
│ -m set --match-set blacklist_v4_nets src -j DROP │
│ (QFEEDS_OUTPUT mirrors this with dst, if enabled) │
└──────────────────────────────────────────────────────────┘
IPv6 でも同じ構造が存在します(ip6 qfeeds テーブル、または ip6tables + family inet6 の ipsets)。
なぜ 2 種類のセットを使うのか?
┌──────────────────────────────────────────────────────┐
│ 1. Check license schedule (licenses.php API) │
│ → Skip run if not yet time for next update │
│ 2. Determine sync mode (full or diff) │
│ 3. Fetch IPv4 feed (ipv6=0) and IPv6 feed │
│ (ipv6=only) separately │
│ 4. Separate IPs from CIDRs in awk │
│ 5. Batch-load into hash set (IPs) and net/interval │
│ set (CIDRs) │
│ 6. Update whitelist sets from config │
│ 7. Persist rules │
└──────────────────────────────────────────────────────┘
| モード | 実行タイミング | 動作内容 |
|---|---|---|
| フルシンク | 初回実行時、強制更新時、差分失敗後、ローカルセットがベースラインを失った場合(空または予想よりはるかに小さい場合)、または最後のシンクが FULL_SYNC_MAX_AGE(デフォルト24時間)より古い場合 | 各フィードを最初に取得して検証し、その後ブラックリストセットをフラッシュして再ロードします。セットは有効なデータを取得した後にのみフラッシュされるため、フェッチが失敗しても保護が失われることはありません |
| 差分シンク | 以降の実行(malware_ip フィードのみ)で、ローカルセットが正常な場合 | 最後のプル以降の追加(+)と削除(-)のみを取得します |
差分シンクは APIキーごと です — APIは最後の成功したプルを追跡し、それ以降の変更のみを返します。差分が失敗した場合、スクリプトは自動的にフルシンクにフォールバックします。
自己修復: 差分更新は既存のセットにのみパッチを適用します。そのセットが失われたり切り詰められたりした場合 — 例えば、ファイアウォールルールが永続化されなかった再起動、手動フラッシュ、または以前の部分的なシンク — アップデーターは欠落したベースライン(ライブ要素数が0または最後に記録された数よりはるかに少ない)を検出し、空のセットに差分を適用する代わりに完全な再構築を強制します。追加の安全策として、定期的なフルシンクも強制します(デフォルトでは
FULL_SYNC_MAX_AGEにより24時間ごと)。
アップデーターは毎回の実行前にQ-FeedsライセンスAPI(licenses.php)をチェックします。ライセンスの next_update タイムスタンプにまだ達していない場合、スクリプトは不要なAPI呼び出しを行わずに早期終了します。cronジョブは頻繁に実行されます(デフォルト:20分ごと)が、実際の更新はライセンスが許可した場合にのみ行われます。
インストール前に、以下を確認してください:
api.qfeeds.com に到達できる必要があります