私は、クライアントが100万個弱の個別のIPアドレス(サブネットなし)のセットをブラックリストに登録する必要があり、ネットワークパフォーマンスが問題になる状況に遭遇しました。 IPTablesルールはルートよりもパフォーマンスへの影響が少ないと推測しますが、それは単なる推測です。
IPアドレスの長いリストをブラックリストに登録するためのソリューションとして、IPTablesまたはnullルーティングのいずれかを支持する確固たる証拠またはその他の正当化がある人はいますか?この場合、すべてが自動化されているため、使いやすさは特に問題になりません。
いくつかのテストと開発の後、これらのオプションはどれも機能しないようです。ルートのルックアップとiptablesの両方がルールセットを介して線形検索を行い、この多くのルールを処理するには時間がかかりすぎるようです。最近のハードウェアでは、1Mアイテムをiptablesブラックリストに入れると、サーバーの速度が毎秒約20ダースに低下します。したがって、IPTablesとnullルートは使用できません。
ipset
は、Jimmy Hedmanによって推奨されていますが、セット内で65536を超えるアドレスを追跡できないことを除いて、すばらしいと思います。 。
明らかに、これだけ多くのIPをブロックするための唯一のソリューションは、アプリケーション層でインデックス付きルックアップを行うことです。そうではありませんか?
詳しくは:
この場合の使用例は、IPアドレスの「既知の違反者」リストがWebサーバー上の静的コンテンツにアクセスできないようにすることです。 FWIW、ApacheのDeny from
はリニアスキャンも行うため、速度は同じくらい遅くなります(そうでない場合でも)。
参考までに:最終的な解決策は、Apacheのmod_rewriteをberkeley DBマップと組み合わせて使用して、ブラックリストに対してルックアップを行うことでした。バークレーDBのインデックス化された性質により、リストはO(log N)パフォーマンスに合わせて拡張できました。
iptablesを使用してマルチレベルツリーを構築し、ルックアップの数を減らしてみてください。
iptables -N rules_0_0_0_0_2
iptables -N rules_64_0_0_0_2
iptables -N rules_128_0_0_0_2
iptables -N rules_192_0_0_0_2
iptables -N rules_0_0_0_0_4
iptables -N rules_16_0_0_0_4
iptables -A INPUT -p tcp --dport 80 -s 0.0.0.0/2 -j rules_0_0_0_0_2
iptables -A INPUT -p tcp --dport 80 -s 64.0.0.0/2 -j rules_64_0_0_0_2
iptables -A INPUT -p tcp --dport 80 -s 128.0.0.0/4 -j rules_128_0_0_0_2
iptables -A INPUT -p tcp --dport 80 -s 192.0.0.0/4 -j rules_192_0_0_0_2
iptables -A rules_0_0_0_0_2 -s 0.0.0.0/4 -j rules_0_0_0_0_4
iptables -A rules_0_0_0_0_2 -s 16.0.0.0/4 -j rules_16_0_0_0_4
など-ネストレベルを追加します。当然、ルールを自動的に構築する方法が必要であり、違反者が1人以上いるネットワークにのみチェーンが必要です。このようにして、実行する必要のあるルックアップの数を大幅に減らすことができます。実際に動作します。
これがまさにipset
の目的です。
そのウェブサイトから http://ipset.netfilter.org/ :
あなたがしたい場合は
次に、ipsetが適切なツールとなる場合があります。
これは、netfilterコアチームメンバーのJozsef Kadlecsik(REJECTターゲットも書いた)によって書かれたので、これは私が考えることができる最良の選択です。
最近のカーネルにも含まれています。
私はこれを自分でテストしませんでしたが、問題の説明を聞いたとき、私はすぐに「pf
」と思いました(OpenBSDから)。
pf
には、- アドレステーブル という概念があります。これは、まさにあなたが探しているものかもしれません。
私が行ったveryの大まかな研究によると、これはipset
よりもスケーリングが向上する可能性があるようです。 ランタイムオプションに関するPF FAQの章 によると、チューニングなしでそのままの状態で、pfは合計1,000テーブルをサポートし、デフォルトですべてのテーブルにわたって合計200,000エントリをサポートします。 (システムに100MB未満の物理メモリがある場合は100,000)。これは、これをテストして、何らかの有用なレベルで機能するかどうかを確認することを検討することは、少なくとも検討する価値があると私に思わせます。
もちろん、私はLinuxでサーバーを実行していることを想定しているため、pfを備えた一部のOS(OpenBSDやFreeBSDなど)を実行する別のファイアウォールボックスを用意する必要があります。また、あらゆる種類のステートフルパケットフィルタリングをまったく行わなくても、スループットを改善できる可能性があります。
後世の場合:ipset
docsに従って、セットのデフォルトサイズは65536で、これはオプションで変更できます。
maxelemこのパラメーターは、すべてのハッシュタイプセットのcreateコマンドに有効です。セットに格納できる要素の最大数を定義します。デフォルトは65536です。例:
ipset create test hash:ip maxelem 2048.
まだコメントできないのでここに入れておきます。
FIB_HASHの代わりにFIB_TRIEを使用して調査しましたか?.
FIB_TRIEは、接頭辞の数に合わせてより適切にスケーリングする必要があります。 (/ 32s nullルートは依然としてプレフィックスであり、非常に具体的です)
使用するために独自のカーネルをコンパイルする必要があるかもしれませんが、それは役に立ちます。
将来この問題に遭遇した人のためのいくつかの役立つメモ:
まず、必要のないトラフィックを分析しないでください。たとえば、TCP=トラフィックをブロックしている場合は、SYNパケットのみをフィルタリングするため、接続ごとに1回だけフィルタにヒットします。必要に応じて-m state
を使用できますが、接続追跡には独自のオーバーヘッドがあり、パフォーマンスが問題になる場合は回避する必要があります。
第2に、100万のルールをiptablesに入力するには、数分という長い時間がかかります。その多くのエンティティを追跡する必要がある場合は、おそらくnetfliterから除外することをお勧めします。ルールセットの純粋なサイズが違いを生みます。
第三に、目標は線形スキャンを回避することです。しかし残念ながら、iptablesとiproute2はどちらも本質的に線形です。ルールをバイナリツリースタイルから多数のチェーンに分割して、参照する必要のあるルールの数を制限できますが、それでも、iptablesはこのサイズの問題にはあまり適していません。それはうまくいくですが、貴重なリソースの無駄遣いです。
第4に、そして最も重要なこととして、ワークロードをユーザースペースにプッシュすることは悪い考えではありません。これにより、独自のタイトなコードを記述したり、問題セットに合わせて調整された既製のソリューションを使用したりできます。前述のように、この問題に対する私自身の解決策は、Apacheのmod_rewriteシステムを介してトリガーされるBDBルックアップを使用することでした。これには、有効なリクエストが送信された後にのみ、セッションごとに1つのルックアップのみをトリガーするという追加の利点がありました。この場合、パフォーマンスは非常に速く、ブロックリストのコストはほとんど無視できました。
-j QUEUE
ターゲットとlibnetfilter_queue
を組み合わせて使用することにより、iptablesで同様のユーザー空間操作を行うことができます。このツールは強力でシンプルであり、文書化が不十分です。公式ドキュメントには含まれていない興味深い資料がウェブ全体に散在しているため、できるだけ多くのソースから可能な限り多くの資料を読むことをお勧めします。