好奇心person盛な人として、小規模ネットワークのシェーピングを構成するプロセスを簡単にすることができるかどうかは常に興味深いものでしたか? 重要なトラフィックを少なくとも大まかに検出し、 重要でないトラフィックとDPIおよび署名分析なしで分離することは可能ですか? 擬似インターフェースを作成したり、カーネルにモジュールを追加したりせずに、あらゆる方向のトラフィックをシェーピングできますか? それで、いくつかの考えとguglezhの後、私はユーザー空間で単純なシェーパーを書くことに決めました。 実験で質問に答えようとします。
実験の結果、そのようなことがgithub.com/vmxdev/damperに判明しました
これは次のように機能します。
起動時に、2つのプログラムスレッドが作成されます。 最初に、NFQUEUEはパケットをキャプチャし、分析し、各パケットに「重み」(または優先度)を割り当て、優先度キューに格納します。 キューがいっぱいになると、低優先度のパケットは高優先度のパケットで上書きされます。 別のスレッドが、最も高い重みを持つパッケージを選択し、送信用にマークします。 このため、実際にはシェーピングが取得されるため、送信は限られた速度で行われます。
NFQUEUEメカニズムに関する小さな余談
このメカニズムにより、処理のためにネットワークパケットをユーザー空間にコピーできます。 適切なキューをリッスンするアプリケーションは、パケットに関する判定をレンダリングする必要があります(スキップまたは破棄)。 さらに、パッケージの変更が許可されます。 このメカニズムは、SnortやSuricataなどのIDS / IPSで使用されます。 パケットはiptablesで処理するためにマークされ、ターゲットはNFQUEUEです。 つまり、任意の方向(着信トラフィック、発信、トランジット、またはポート666からポート13へのUDPなど)を選択してシェーパーに送信できます。 そこで、パケットが分析され、その順序を変更することができます。制限を超えた場合、優先順位が最も低いパケットは破棄されます。
シェーパーの最初の動作バージョンでは、パケットをキャプチャし、キューに入れてから、未加工のソケットに再注入しました。 StackOverflowおよび他のいくつかの記事では、これが再送前にパケットを遅延させる唯一の方法であると書いています。 設計は機能しましたが、仲間のVelがNFQUEUEでパケットを直接遅延させることができる場所を説明し、シェーパーのセットアップが簡素化されました。
モジュール
シェーパーは実験的なものであるため、モノリシックではなく「モジュラー」にしました。 各モジュールでは、異なる基準に従ってパケットの重みが計算されます。 すぐに使える4つのモジュールがありますが、簡単に別のモジュールを作成できます。 モジュールは一緒に使用することも、別々に使用することもできます。
モジュール:
- prevent_big_flows-大きなスレッドを抑制します。 2つのIPアドレス間で送信されるバイトが多いほど、パケットの「重み」は小さくなります。 つまり、大きな重いセッションからのパケットが破棄される可能性が高くなります。 情報は循環バッファーに格納されるため、時々恩赦が発生し(監視対象セッションの数は構成で設定されます)、ストリームはより新しいものに置き換えられます
- bymark-パッケージの重量はブランドごとに設定されます。 iptablesは、いくつかの基準に従ってマークをスローします。これらのパケットには、構成で指定された係数が適用されます。 マークされたトラフィックの優先度を手動で上げたり下げたりできます
- エントロピー -重みは、フローのエントロピー(より正確には、シャノンエントロピーの測定値)に応じて考慮されます。 ストリームは、プロトコル番号と参加者のアドレスによって識別されます。 TCP / UDPの場合、送信元ポートと宛先ポートも考慮されます。 エントロピーが高いほど、重みは小さくなります。 つまり マルチメディア、暗号化、圧縮されたトラフィックは、他よりも廃棄される可能性が高くなります。
- また、非常に原始的なランダムモジュール-パケットのドロップと並べ替えのプロセスにランダム性を追加するだけです(このモジュールのみを使用すると、クラシックREDが得られます)。
各モジュールで測定されたパケットの重みは、係数で乗算され(各モジュールに独自に割り当てることができます)、合計されます。 結果の重量が取得されます。
統計とグラフ
Shaperは、統計を保持し、グラフを描画できます。 ライブは、 amper.xenoeye.comのようになります。 緑-スキップされるバイト/パケットの数、赤-ドロップされるバイト数。 チャートを拡大/縮小できます。
2番目のグラフ(configのwchart yesディレクティブに含まれる)は、1秒あたりの平均パケット重量であり、正規化され、モジュール別に分類されています。
デモはあまり高速ではないARM(Scalewayベアメタル、32ビットARMv7)で動作しますが、わずかに固執する場合があります。
デバッグ
prevent_big_flowsおよびエントロピーモジュールには、設定で有効になっているデバッグモードがあります。 このモードでは、モジュールはN秒ごとに重み付きで現在のフローをダンプします。
さらに、速度制限のないモードがあります(構成の「制限なし」)。 このモードでは、すべてのパケットがスキップされます(モジュールでの分析は行われません)が、過去のパケット/バイトの統計を保持したり、チャネルのロードスケジュールを瞑想したりできます。
結果
シェイパーは非常にシンプルであることがわかりました(まあ、私の意見では、ぼやけた外観です)。 使用するには、シェーピングする方向を選択し、iptablesルールを追加し、設定で目的の速度を設定して実行する必要があります。
重いエントロピーの強いセッションが決定され、優先度が下げられますが、奇跡は起こりません。チャンネルが非常に狭い場合、快適なサーフィンは機能しません。
高速で多数のユーザーがいる場合はテストしませんでしたが、数十メガビットで複数のユーザーがいる場合、シェーパーを使用しない場合よりも主観的には良い結果が得られました。 CPUをロードしますが、NFQUEUEの使用だけでなく、コードの一般的な不器用さ(およびclock_nanosleep()の特性から少し)からも、最適化および最適化できます。
もちろん、これは概念の証明にすぎず、コードは場所が乱雑で、実際にはくしませんでした。
誰かがそれについての考え、希望、提案を持っているなら、読むのは面白いでしょう。