VPSでCentOS 7を実行しており、特定のポートの帯域幅を制限したいと思います。私は広く調査し、私が見つけることができる解決策は、インターフェイスの制限事項であるか、CentOS 6でのみ試されたように見えるiptable設定があいまいに説明されていることです。
私の場合、Shadowsocks(プロキシアプリケーション)サーバー側のポート1080
と1081
。無制限の帯域幅を許可したいのですが、帯域幅を約1MBpsに制限したいと思います。プロキシアプリケーションなので、インバウンドトラフィックとアウトバウンドトラフィックはほぼ同じです。これは、3つのポートでリッスンするShadowsocksの単一インスタンスです。1082
eth0
1080
1081
1082
いいえ3つのインスタンスはそれぞれ1つのポートをリッスンするため、プロセス固有の帯域幅制限は適用されません。
しかし、それ以外の場合は、すぐに利用可能なCentOSサポートであるか、中間監視層の種類に関係なく、すべてのソリューションを検討できます。仕事が完了する限り、私は喜んでそれをします。
よろしくお願いします。
答え1
次の方法でのみトラフィックを制限できます。Linuxフロー制御。
もう一度確認するために、シャドウソックス一方がSOCKS5プロキシとして機能するトンネルを作成します(sslocal
、私はこれが与えられたポートが与えられたOPのサーバーで実行されていると仮定しており、リモートエンドポイントと通信します(ssserver
)それ自体が実際のターゲットサーバーと通信します。 Shadowsocks は SOCKS5 UDP ASSOCIATE を処理し、(SOCKS5) TCP ポートと同じポートで (SOCKS5) UDP を使用します.
このソリューションはTCPとUDPの両方で動作しますが(注1を参照)、 UDPは追加の問題を示す可能性があります。ソースが "MTU より大きい" サイズの UDP パケットを生成する場合 (おそらく善良に動作するクライアントでは使用しないでください) またはサーバー) 断片化されます。TC、効率的なより早いWebフィルタ存在する入り口そしてそれより後でWebフィルタ存在する出口、フラグメントが表示されます。 UDPポートはフラグメントとして使用できないため、フィルタはそれをキャプチャできず、制限はほとんどありません。当然、MTUを使用してパケットサイズを制限し、とにかくパスMTU検索を実行するTCPは、ほとんどの設定でこの問題は発生しません。
以下はパケットストリームのASCII図です(全体図は通常、2つのストリーム(エージェントの左右に1つずつ)を発生させるクライアントアクティビティを示しています)。
traffic controlled TCP self-adjusting / no UDP control
-------------> <-------------
/ \ / \
clients | | proxy | | remote ====== real servers
\ / (sslocal) \ / (ssserver)
<------------- ------------->
traffic controlled already rate limited
リモートサーバートラフィックに必要または心配する必要はありません。
- もちろん、プロキシからリモートサーバーへの出口は、クライアントの受信によって制限されます。
- リモート/サーバーからプロキシを転送する
- TCPは通常、クライアントトラフィックのように調整して動作します。
- UDPには、アプリケーションプロトコルがこれを実行できない限り、この可能性はありません。例:単純UDPを介して2つのビデオソースがサーバー側から到着し、クライアント制限を超えると、両方のクライアントストリームが破損する可能性があります。帯域幅を減らすためのアプリケーションフィードバックが必要です。これはこの範囲外です。
それにもかかわらず、リモート/サーバー側のトラフィックをクライアントに接続するには、Shadowsock内で変更が必要になり、より複雑になります。TC使用法。
データのみを送信するSOCKS5クライアントの場合、制限は入り口データのみを受信するSOCKS5クライアントの場合、帯域幅を制限する必要があります。出口帯域幅を制限する必要があります。使用されるアプリケーションがよく知られていない限り、両方の方法でトラフィック制御を受ける必要があります。
交通管理は私がほとんど扱いにくい複雑なトピックです。二つの回答をさせていただきます。単純なポリシー(余分なデータの削除)と整形(削除前の遅延を含む)を実行し、IFBインターフェイスを使用して次の制限を解決するより複雑な答えです。入り口。
概念とLinuxの実装を理解するには、次の記事を読む必要があります。
http://www.tldp.org/HOWTO/Traffic-Control-HOWTO/
また、シェルスクリプトで実装されたこのコマンドは、(そしてこの答えに似たメカニズムを使用して)次のような驚くべき結果をもたらします。
https://github.com/magnific0/wondershaper
シンプル
ㅏ警察アクションはポートに一致する超過パケットを破棄するために使用されます(おおよそのアプローチです)。それは一般的に使用されます入り口しかし、次に適用されます出口また。トラフィックは制限されていますが、制限されているさまざまなクライアント間で変動や不公平な共有がある可能性があります(特にUDPとTCPが関係している場合)。
出口(発信パケット)
最も単純なキューディスク追加のフィルタを許可する例プリオ キューディスク、特定の機能は実際には使用されません。
tc qdisc add dev eth0 root handle 1: prio
TCPおよびUDPのフィルタリングは、各ポート(「ソースポート」を意味)に次のフィルタ(8mbits / s <=> 1MBytes / s)を追加することによって簡単に行わ
u16 at 0 layer transport
れます(注2を参照)。tc filter add dev eth0 parent 1: protocol ip basic match 'cmp(u16 at 0 layer transport eq 1081)' action police rate 8mibit burst 256k tc filter add dev eth0 parent 1: protocol ip basic match 'cmp(u16 at 0 layer transport eq 1082)' action police rate 8mibit burst 256k
私が間違って理解した場合に備えて、1081と1082には1つの共通の制限しかありません。上記の2つの制限の代わりにそれを使用して同じ操作にグループ化します(使いやすい)。基本的な/電子マッチングフィルタ)は、単一のトークンバケットで処理されます。
tc filter add dev eth0 parent 1: protocol ip basic match 'cmp(u16 at 0 layer transport eq 1081) or cmp(u16 at 0 layer transport eq 1082)' action police rate 8mibit burst 256k
受信(受信パケット)
入り口比較する出口(できない形成)、しかし、どんな場合でも単純なケースでは実行されません。これを使用するには、
ingress
qdiscを追加するだけです(注3を参照)。tc qdisc add dev eth0 ingress
対応するフィルタ(
u16 at 2 layer transport
「ターゲットポート」を意味):tc filter add dev eth0 ingress protocol ip basic match 'cmp(u16 at 2 layer transport eq 1081)' action police rate 8mibit burst 256k tc filter add dev eth0 ingress protocol ip basic match 'cmp(u16 at 2 layer transport eq 1082)' action police rate 8mibit burst 256k
または上記の2つの代わりに単一の制限の場合:
tc filter add dev eth0 ingress protocol ip basic match 'cmp(u16 at 2 layer transport eq 1081) or cmp(u16 at 2 layer transport eq 1082)' action police rate 8mibit burst 256k
クリンテック
出口、入り口あるいは、両方の設定を以下の改良版に置き換えることもできます。前の設定を最初に消去する必要があります。
以前に適用されたTC設定を削除するには、単に削除してください。根そして入り口 キューディスク。その下のすべての項目(フィルタを含む)も削除されます。基本インタフェースルートディレクトリキューディスクスケジュールされたハンドル0:再配置されます。
tc qdisc del dev eth0 root
tc qdisc del dev eth0 ingress
より複雑な設定のために、qdiscに似たIFBインタフェースを使用してください。
何かの目的を指します。形成これはパケットが廃棄される前に遅延し、全体的な結果を改善する。階層トークンバケット(HTB)、帯域幅を処理するクラスqdiscがあり、その下にはランダムなプロセスキュー(SFQ)は、クライアントが限られた帯域幅内で競合するときの公平性を向上させます。
出口
次の設定を説明するASCIIイメージは次のとおりです。
root 1: HTB classful qdisc | / | \ / | \ / | \ / | \ / 1:20 1:30 HTB classes / 8mibit 8mibit / | \ / | \ / 20: 30: / SFQ SFQ still 1: default port port incl. port 1080 1081 1082
制限された帯域幅は追加の使用可能なトラフィックを借用しません(OPは要求しません)。これが、「利用可能な全帯域幅」の基本カテゴリのサブクラスではない理由です。ポート1080を含む残りのデフォルトトラフィックは、特別な処理なしで1:にとどまります。クラスが利用可能な帯域幅を借りることができるさまざまな設定では、これらのクラスは、利用可能な最大帯域幅の正確な値に設定された親クラスの下に配置され、借り先を知ることができます。したがって、各状況に合わせて構成を微調整する必要があります。私はそれを簡単に保ちます。
htbにはqdiscクラスがあります。
tc qdisc add dev eth0 root handle 1: htb
htbクラス、添付sfq、およびそれを指すフィルタ:
tc class add dev eth0 parent 1: classid 1:20 htb rate 8mibit tc class add dev eth0 parent 1: classid 1:30 htb rate 8mibit tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10 tc qdisc add dev eth0 parent 1:30 handle 30: sfq perturb 10 tc filter add dev eth0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 0 layer transport eq 1081)' flowid 1:20 tc filter add dev eth0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 0 layer transport eq 1082)' flowid 1:30
または上記の6つのコマンドの代わりに単一の制限の場合:
tc class add dev eth0 parent 1: classid 1:20 htb rate 8mibit tc qdisc add dev eth0 parent 1:20 handle 20: sfq perturb 10 tc filter add dev eth0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 0 layer transport eq 1081)' flowid 1:20 tc filter add dev eth0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 0 layer transport eq 1082)' flowid 1:20
入り口
入り口qdisc は次のようには使用できません。形成(遅延パケットなど)単純な場合と同様に、フィルタを使用して破棄します。より良い制御のためのヒントは次のとおりです。中間機能ブロック、人工的だと思います。出口インターフェイスはどこにありますか?入り口交通は大丈夫ですリダイレクトフィルタを使用しますが、残りのネットワークスタックとのやり取りはほとんどありません。いったん席をつかむと、出口着信トラフィックの実際の制御が受信システムにないことを考慮すると、一部の機能が常に役に立たない場合でも、特定の機能をここに適用できます。だからここで
ifb0
インターフェースを設定し、上記の内容をコピーしました(出口)一種の受信形成が単純な治安よりも優れた性能を発揮するように設定します。作るb0 (注4参照)前と同じ設定を適用します。出口:
ip link add name ifb0 type ifb 2>/dev/null || : ip link set dev ifb0 up tc qdisc add dev ifb0 root handle 1: htb
クラスとフィルタを指します。
tc class add dev ifb0 parent 1: classid 1:20 htb rate 8mibit tc class add dev ifb0 parent 1: classid 1:30 htb rate 8mibit tc qdisc add dev ifb0 parent 1:20 handle 20: sfq perturb 10 tc qdisc add dev ifb0 parent 1:30 handle 30: sfq perturb 10 tc filter add dev ifb0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 2 layer transport eq 1081)' flowid 1:20 tc filter add dev ifb0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 2 layer transport eq 1082)' flowid 1:30
または単一の制限の場合、上記の6つのコマンドを使用する場合:
tc class add dev ifb0 parent 1: classid 1:20 htb rate 8mibit tc qdisc add dev ifb0 parent 1:20 handle 20: sfq perturb 10 tc filter add dev ifb0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 2 layer transport eq 1081)' flowid 1:20 tc filter add dev ifb0 parent 1: protocol ip prio 1 basic match 'cmp(u16 at 2 layer transport eq 1082)' flowid 1:20
次からリダイレクトされましたイーサネット0~の入り口到着b0 出口以下が行われます。最適化のために、すべてのトラフィックの代わりに予想されるポートのみをリダイレクトします。実際のフィルタリングおよび形成は上記で行われる。b0それでも。
tc qdisc add dev eth0 ingress tc filter add dev eth0 ingress protocol ip basic match 'cmp(u16 at 2 layer transport eq 1081)' action mirred egress redirect dev ifb0 tc filter add dev eth0 ingress protocol ip basic match 'cmp(u16 at 2 layer transport eq 1081)' action mirred egress redirect dev ifb0
メモ:
1. 一部のネットワークネームスペースを使用して Debian 10/kernel 5.3 でテストされました。コマンド構文はCentOS 7.6コンテナ/カーネル5.3(3.10以外)でもテストされています。
2.u32 match ip sport 1081 0xffff
送信元ポート 1081 を一致させるために使用された可能性があります。ただし、IPオプションの存在を処理することはできません。u32 match tcp src 1081 0xffff
処理できますが、実際には複雑な使用が必要ですサム u32フィルタの説明は以下にありますマニュアルページ。だからbasic match
結局選びました。
3.指定されているかどうかに関係なく、予約されたingress
ハンドルffff:
(指定されたハンドル値は無視されます)があるため、指定しないことをお勧めします。参照受信は、私が選択しただけparent ffff:
で置き換えることができます。ingress
4. IFBインターフェイスが最初に作成されると、ifbモジュールがロードされ、デフォルトで自動的に生成されます。b0そしてもしb1初期名前空間のインターフェースは、実際にはコマンドの結果として生成されましたが、インターフェース名ifb0を要求するとエラーが発生します。同時にモジュールのみをロードすると、インターフェイスはネットワークネームスペース(コンテナなど)に表示されないため、インターフェイスは依然として必要です。したがって、追加すると、2>/dev/null || :
両方のケースを解決できます。もちろん、実際にはIFBサポートが可能であると仮定します。