
NFtablesまたはIPtables上でQ-Feedsを直接実装するスクリプト
無料のAPIキーを tip.qfeeds.com で取得します。
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
### ステップ3: インストーラをrootとして実行する```bash
sudo ./qfeeds-installer.sh
インストーラーは以下の処理を行います:
これでサーバーが保護されました。cronジョブは20分ごとに(設定可能)更新を確認し、実際のAPI呼び出しはライセンスが許可する場合にのみ行われます。
このソリューションは、定期的にQ-Feedsから最新の脅威インテリジェンスフィードをダウンロードし、ファイアウォールルールとして適用することで、以下を可能にします:
インストーラーは自動的にどのファイアウォールバックエンドが利用可能かを検出します:
| 優先順位 | 検出条件 | バックエンド |
|---|---|---|
| 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 ipset)。
なぜ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 │ └──────────────────────────────────────────────────────┘
### フル同期 vs 差分同期
| モード | タイミング | 動作 |
|------|------|-------------|
| **フル同期** | 初回実行、強制更新、差分失敗後、ローカルセットのベースラインが失われた場合(空または想定より大幅に小さい)、または最終同期が `FULL_SYNC_MAX_AGE`(デフォルト24時間)より古い場合 | まず各フィードを取得して検証し、その後ブラックリストセットをフラッシュして再読み込みする。有効なデータが確保された後にのみセットがフラッシュされるため、取得に失敗しても保護が失われることはない |
| **差分同期** | 以降の実行(`malware_ip` フィードのみ)で、ローカルセットが正常な場合 | 最後のプル以降の追加(`+`)と削除(`-`)のみを取得する |
差分同期は **APIキーごと** に行われる。APIは最後に成功したプルを追跡し、それ以降の変更のみを返す。差分が失敗した場合、スクリプトは自動的にフル同期にフォールバックする。
> **自己修復:** 差分更新は既存のセットにのみパッチを適用する。そのセットが失われたり切り詰められたりした場合(例えば、ファイアウォールルールが永続化されなかった再起動、手動フラッシュ、以前の部分同期など)、アップデーターはベースラインの欠落(ライブ要素数が0または最後に記録された数よりはるかに少ない)を検出し、空のセットに差分を適用する代わりに完全な再構築を強制する。追加の安全策として、定期的なフル同期(デフォルトでは24時間ごと、`FULL_SYNC_MAX_AGE` 経由)も強制する。
### ライセンスベースのスケジューリング
アップデーターは実行前に毎回 Q-Feeds ライセンスAPI(`licenses.php`)をチェックする。ライセンスの `next_update` タイムスタンプにまだ達していない場合、スクリプトは不要なAPI呼び出しを行わずに早期終了する。cronジョブは頻繁に(デフォルト:20分ごと)実行されるが、実際の更新はライセンスが許可した場合にのみ発生する。
---
## ✅ 前提条件
インストール前に、以下を確認してください:
- [x] **Linuxサーバー**(**nftables** または **iptables** 対応:Debian、Ubuntu、CentOS、Fedora、Arch、Alpine)
- [x] **rootアクセス** — インストーラーとアップデーターはrootとして実行する必要があります
- [x] **Q-Feeds APIトークン** — [tip.qfeeds.com](https://tip.qfeeds.com/) で無料で取得できます
- [x] **インターネットアクセス** — サーバーが `api.qfeeds.com` に到達できる必要があります