Linuxゲートウェイ上のTorrentクライアント-神話か現実か?

Intel Atom上のMini-ITXマザーボードをなんとかしてランダムに管理し、すぐに思いついた「静かなホームサーバー!..」(電源はラップトップ+受動冷却を備えたはんだ付けプロセッサに適しています)。 考えた-完了!



ケース、メモリ、1台の2.5 HDD(数か月以内にミラー用に同じものを用意する予定)、およびインターネットをローカルネットワークに配布するための2つ目のネットワークカードを購入しました。今では、ほとんどのサーバーに(当時の)新しいDebian Squeezeがあります。



私はこのサーバーに何が欲しいのか考え始めました、そして私はすべてを少し絞ろうとする人々のカテゴリーから来たので、ウェブ、メール、ジャバーサーバー(白い静的があります)を上げることに決めました「そしてもう少し」急流ロッキングチェアを年中無休で手に入れましょう。



ゲートウェイ上のトレントクライアントである1つのBUTがなければ、すべてがうまくいきます。 ゲートウェイ上のトレントクライアントに向かうトレントトラフィックがインターネットチャネル全体を詰まらせ 、ローカルネットワークデバイスに鼻を残してしまうので、多くの妄想に聞こえます。 しかし、結論に急がないでください。そのようなナンセンスは生命に対する権利を持っています。 さらに、ロッキングチェアが同じサーバー上の他のサービスと平和的に共存し、ローカルネットワーククライアントに干渉しない実用的なソリューションが見つかりました。 しかし、まず最初に...



1.ちょっとした理論



「着信トラフィックをシェーピングすることは意味がありません。なぜなら、 彼はすでに到着しています。つまり、彼はあなたのチャンネルの幅全体に、より高い配信者(プロバイダーなど)から参加しています。」 この声明は真実ですが、部分的には 説明が必要:



TCP / IPのコンテキストで


TCP接続の場合、「 スロースタート 」があります。 これは、ホスト間のパケットが最大速度ですぐに送信を開始しないことを意味します。 代わりに、パケット受信の確認と損失の存在の結果に基づいて、速度(速度)が徐々に増加/減少します。 つまり、パケット送信速度は「変動」し、ホスト間のチャネル帯域幅に調整されます。



この動作を考慮すると、ホスト間のどこかで人為的にtcp接続のパケットの速度を下げることができ、それによりホストに伝送速度を下げる必要性を課すことができます。



しかし、udpパッケージの場合、すべてがやや悲しくなります。 送信側は、パケットの損失または通過時間を考慮せずに単に「スロー」します(UDP-アフリカUDPにもあります:すべての結果を伴う非保証配信...)。 そして、これにはすでに次のような問題があります:udp-trafficがプロバイダーによって保証された帯域全体を使い果たした場合、パケットは単純にドロップし始め、どのようなパケットがインターネットサービスプロバイダーに残されますが、送信側は引き続き送信しますそのようなトラフィックがあります。



悲しい はい、しかし、それほど急ではなく、24/7で動作する自宅の唯一のコンピューターに急流ロッキングチェアを運転するという考えを放棄しました。そのため、急流クライアントは、すぐに配信のすべてのコンテンツをダウンロードしないように要求します私のすべてを1つのスレッドで)。 代わりに、サイズが16キロバイトから4メガバイトまで変化するいくつかのチャンクに対して要求が送信されます。 配布のダウンロードされた部分を遅延させることにより、当社側が他の部分をダウンロードする要求の頻度を減らすことができ、その結果、torrentクライアントが消費するチャネル幅を減らすことができます。



したがって、提供側にパケットの送信速度を強制的に下げることができる場合、プロバイダーによって割り当てられた最大値から消費する幅がより合理的に使用されます。



Linuxルーターを通過するパケットのコンテキストで


GNU / Linuxネットワークスタックを介してパケットを渡すための完全なスキームは次のとおりです。





簡単にするために、パケットがインターネットの広大な領域からLinuxルーターの背後にあるデバイスにルーティングされ、このパケットが既にプロバイダーの機器を離れている状況を見てみましょう。 次のポイントはWANインターフェイスです。



強力なIptablesを手に入れる前に、パッケージはイングレスの分野を通過し、すでにこの分野で保証された最大速度を記述するクラスを「ハングアップ」することができますが、このqdiscには2つの重要な制限があります:

  1. このディシプリンに追加されたクラスには子クラスを含めることはできません。つまり、親からの子クラスによる未使用の幅の借用は失敗します。
  2. IPに基づいてローカルネットワークに向かうクラスを「分散」する可能性はありません。 まだNATに到達していません。


一般に、イングレスディシプリンは、本格的なダイナミックシェーピングには適していません。



入力後、パケットはIptablesに送信され、そこでフィルタリング/ NAT /ラベリング/ ...が行われます。その後、パケットはLANインターフェイスのegres規律に送信されます。



次の事実に注意を喚起したいと思います。



そして今、あなたは着信トラフィックのシェーピングに関するステートメントを再定式化することができます: GNU / Linuxでは、デバイスの発信インターフェース上で着信トラフィックを正しくシェーピングしますが、このデバイスは個人のニーズのためにトラフィックを消費すべきではありませんが、これは、シェーパーでクラスを形成するときに考慮する必要があります)。



2.制限を回避します



すでにわかったように、トラフィックのシェーピングは、出力の分野でより正確です。 ルータを通過するパケットの方向に関して、発信インターフェイス上で。 これは、ルーター自体でトレントクライアントを実行すると、クライアント向けのパッケージが出口規則に決して入らず、それらを「遅延」できないことを意味します。



インターネットをローカルネットワークに配信するルーターで、それで消費されるチャネル幅に厳しい制限なしでトレントクライアントを起動することを実現しました-風水を使わないで、ローカルネットワークに行くかのようにこのトラフィックを形成する方法を考えました、つまり 最初は「与える」インターフェースに送信されますが、最終的にはトレントクライアント自体に送信されるため、これらはすべて同じ鉄の中で発生しますか?



最初は仮想化に目を向け始めましたが、ハードウェアが弱すぎて準仮想マシンを持ち上げることができず、ハードウェア仮想化ではできなかったため、問題は悪化しました。 しかし、Endlessの広がりを長々と歩き回るだけで、すべての記事に適したソリューションが見つかりました-OpenVZ



openvzカーネルをインストールすると、共同ホストの分離に加えて、ホストシステムでvenetインターフェイスを取得し、L3レベルで動作し(L2ではvethデバイスを使用できます)、その前にコンテナーに飛んでいるすべてのipトラフィックがvenetに行きます、つまり 発信インターフェイスを取得します。 医者が注文したもの!



ホストにVZコンテナーを展開し、トレントクライアントと他のサービスをホストに拡散すると、次のようなスキームが得られました。

Openvz








WAN-世界を覗く物理インターフェイス

VENET-コンテナに向かうすべてのトラフィックが通過する仮想L3インターフェイス(サブネット192.168.254.0/24)

LAN-ローカルネットワークを見る物理インターフェース(サブネット192.168.0.0/24)



トラフィックの動的シェーピングに参加できるインターフェイス1つだけであることを除いて、ほぼ準備完了です。 この場所で疑問が生じるかもしれないと感じて、私はより詳細に説明しようとします。



私の世界へのチャンネル幅は100 Mb / sであり、絶対に予想通り、次のように利己的な目的ではなく可能な限りそれを使用したかったのです。

  1. 一定期間、トレントクライアント(BitTorrentコンテナー)によって外部から何かだけがプルされた場合、利用可能な帯域全体を彼に与える必要があります。
  2. トレントクライアントのダウンロード中に、コンテナのローカルネットワークまたはサブネットから何かがhttpを介してダウンロード/監視を開始する場合、トレントトラフィックは、たとえば32Kb / sにクランプされる必要があり、残りの幅はhttpで指定される必要があります
  3. 最も重要なのは、LANインターフェースの背後またはVENETインターフェースの背後にあるサブネットに関係なく、すべてのデバイスがチャネル幅全体を使用できることです。


いいですね。 そして、2番目のポイントのhttp-trafficを使用した例が要件のごく一部であることを考慮すると、「急流が実行され、pingが実行され、youtubeが見える」というidilllを達成することで達成できます。



要件のポイント3に関連する問題を回避する方法を考え始めました。なぜなら、他のネットワークネットワークから未使用の幅を借りることができないからです。2つのインターフェイスで動的シェーピングを実現できない場合、すべてのトラフィックcをラップした後、ifbデバイスでシェーピングします出口はLANとVENETを制御します。



3.原因のために!



ボンネットの下を見る前に、私が自分で選んだトラフィック分類の原理についていくつかの言葉で説明したいと思います。



それでは、始めましょう。



パラメータを決定し、規律をクリアし、ifbデバイスをロードします
#!/bin/bash IPT="/sbin/iptables" TC="/sbin/tc" IP="/bin/ip" DEV_LAN="eth1" # ,     DEV_VENET="venet0" # ,    DEV_IFB_LAN="ifb0" #        CEIL_IN="95mbit" #     5% CEIL_IN_BULK="90mbit" #     #    $TC qdisc del dev $DEV_LAN root >/dev/null 2>&1 $TC qdisc del dev $DEV_LAN ingress >/dev/null 2>&1 $TC qdisc del dev $DEV_VENET root >/dev/null 2>&1 $TC qdisc del dev $DEV_VENET ingress >/dev/null 2>&1 #  ifb-    rmmod ifb >/dev/null 2>&1 modprobe ifb numifbs=1 $IP link set $DEV_IFB_LAN up
      
      







分野、クラス、フィルターを作成します
 #   htb-  ifb- $TC qdisc add dev $DEV_IFB_LAN root handle 1: htb default 80 #      ,    $TC class add dev $DEV_IFB_LAN parent 1: classid 1:1 htb rate $CEIL_IN #  ,        $TC class add dev $DEV_IFB_LAN parent 1:1 classid 1:10 htb rate 5mbit ceil 5mbit prio 0 $TC class add dev $DEV_IFB_LAN parent 1:1 classid 1:20 htb rate 10mbit ceil $CEIL_IN prio 1 $TC class add dev $DEV_IFB_LAN parent 1:1 classid 1:30 htb rate 10mbit ceil $CEIL_IN prio 2 $TC class add dev $DEV_IFB_LAN parent 1:1 classid 1:40 htb rate 10mbit ceil $CEIL_IN prio 3 $TC class add dev $DEV_IFB_LAN parent 1:1 classid 1:50 htb rate 10mbit ceil $CEIL_IN prio 4 $TC class add dev $DEV_IFB_LAN parent 1:1 classid 1:80 htb rate 50kbit ceil $CEIL_IN_BULK prio 7 #    $TC qdisc add dev $DEV_IFB_LAN parent 1:10 handle 10: sfq perturb 10 $TC qdisc add dev $DEV_IFB_LAN parent 1:20 handle 20: sfq perturb 10 $TC qdisc add dev $DEV_IFB_LAN parent 1:30 handle 30: sfq perturb 10 $TC qdisc add dev $DEV_IFB_LAN parent 1:40 handle 40: sfq perturb 10 $TC qdisc add dev $DEV_IFB_LAN parent 1:50 handle 50: sfq perturb 10 $TC qdisc add dev $DEV_IFB_LAN parent 1:80 handle 80: sfq perturb 10 #       ip,    $TC filter add dev $DEV_IFB_LAN parent 10: protocol ip handle 110 flow hash keys dst divisor 512 $TC filter add dev $DEV_IFB_LAN parent 20: protocol ip handle 120 flow hash keys dst divisor 512 $TC filter add dev $DEV_IFB_LAN parent 30: protocol ip handle 130 flow hash keys dst divisor 512 $TC filter add dev $DEV_IFB_LAN parent 40: protocol ip handle 140 flow hash keys dst divisor 512 $TC filter add dev $DEV_IFB_LAN parent 50: protocol ip handle 150 flow hash keys dst divisor 512 $TC filter add dev $DEV_IFB_LAN parent 80: protocol ip handle 180 flow hash keys dst divisor 512 #    TC_A_F="$TC filter add dev $DEV_IFB_LAN parent 1:" # ,     $TC_A_F prio 10 protocol ip u32 match ip protocol 6 0xff \ match u8 0x05 0x0f at 0 \ match u16 0x0000 0xffc0 at 2 \ match u8 0x10 0xff at 33 \ flowid 1:10 # ack < 64b $TC_A_F prio 1 protocol ip u32 match ip protocol 1 0xff flowid 1:10 # icmp $TC_A_F prio 1 protocol ip u32 match ip protocol 6 0xff match ip sport 53 0xffff flowid 1:10 # dns $TC_A_F prio 1 protocol ip u32 match ip protocol 17 0xff match ip sport 53 0xffff flowid 1:10 # dns $TC_A_F prio 2 protocol ip u32 match ip protocol 17 0xff match ip tos 0x68 0xff flowid 1:20 # voip $TC_A_F prio 2 protocol ip u32 match ip protocol 17 0xff match ip tos 0xb8 0xff flowid 1:20 # voip $TC_A_F prio 2 protocol ip u32 match ip protocol 6 0xff match ip sport 8000 0xffff flowid 1:20 # icecast $TC_A_F prio 3 protocol ip u32 match ip protocol 6 0xff match ip sport 22 0xffff flowid 1:30 # ssh $TC_A_F prio 3 protocol ip u32 match ip protocol 6 0xff match ip sport 3389 0xffff flowid 1:30 # rdp $TC_A_F prio 3 protocol ip u32 match ip protocol 6 0xff match ip sport 5222 0xffff flowid 1:30 # jabber c2s $TC_A_F prio 3 protocol ip u32 match ip protocol 6 0xff match ip sport 5223 0xffff flowid 1:30 # jabber c2s $TC_A_F prio 3 protocol ip u32 match ip protocol 6 0xff match ip sport 5269 0xffff flowid 1:30 # jabber s2s $TC_A_F prio 4 protocol ip u32 match ip protocol 6 0xff match ip sport 80 0xffff flowid 1:40 # http $TC_A_F prio 4 protocol ip u32 match ip protocol 6 0xff match ip sport 443 0xffff flowid 1:40 # https $TC_A_F prio 4 protocol ip u32 match ip protocol 6 0xff match ip sport 143 0xffff flowid 1:40 # imap $TC_A_F prio 4 protocol ip u32 match ip protocol 6 0xff match ip sport 993 0xffff flowid 1:40 # imaps $TC_A_F prio 4 protocol ip u32 match ip protocol 6 0xff match ip sport 25 0xffff flowid 1:40 # smtp $TC_A_F prio 4 protocol ip u32 match ip protocol 6 0xff match ip sport 465 0xffff flowid 1:40 # smtps $TC_A_F prio 4 protocol ip u32 match ip protocol 6 0xff match ip sport 587 0xffff flowid 1:40 # smtps $TC_A_F prio 4 protocol ip u32 match ip protocol 6 0xff match ip sport 21 0xffff flowid 1:40 # ftp $TC_A_F prio 5 protocol ip u32 match ip protocol 6 0xff match ip sport 20 0xffff flowid 1:50 # ftp
      
      







そして最後のコード:トラフィックを出力分野venet0およびeth1インターフェースからifbデバイスにリダイレクトします
  # DEV_LAN => DEV_IFB_LAN (ifb0) $TC qdisc add dev $DEV_LAN root handle 1: prio #    $TC filter add dev $DEV_LAN parent 1: prio 1 protocol ip u32 match ip src 192.168.8.253/32 action pass #  ip   . $TC filter add dev $DEV_LAN parent 1: prio 1 protocol ip u32 match ip src 192.168.254.0/24 action pass #  vz-  .  # ,   ingress DEV_LAN,   egress DEV_IFB_LAN (ifb0) $TC filter add dev $DEV_LAN parent 1: prio 2 protocol ip u32 match u32 0 0 action mirred egress redirect dev $DEV_IFB_LAN # DEV_VENET -> DEV_IFB_LAN (ifb0) $TC qdisc add dev $DEV_VENET root handle 1: prio #    $TC filter add dev $DEV_VENET parent 1: prio 1 protocol ip u32 match ip src 192.168.8.0/24 action pass #     vz- # ,   ingress DEV_VENET,   egress DEV_IFB_LAN (ifb0) $TC filter add dev $DEV_VENET parent 1: prio 2 protocol ip u32 match u32 0 0 action mirred egress redirect dev $DEV_IFB_LAN
      
      









以上です。 私が提示した解決策が誰かを助け、誰かがそれを改善するように私を押し進めると信じたいです。



All Articles