なぜそのような問題があるのですか?
そのため、「終了」方向のネットワークストリームの速度しか制御できません。 すでにインターフェイスに来ているもの、多くのボトルネックが既に通過している、このトラフィックを破棄または遅延することは意味がないように思われます。 ただし、ほとんどのプロトコル(TCPおよびUDPに基づいて構築されたプロトコル、または独自の実装を持つプロトコル)には、クライアントの実際の帯域幅を考慮して送信速度を変更できる送信ストリームを制御するメカニズムがあります。 そのような状況では、私たちの側でクライアントに流れるフローを制御することは理にかなっています。 これを実装するメカニズムは多数ありますが、そのうちのいくつかを検討します。
典型的な状況と問題
インターネットとローカルエリアネットワークの1つのインターフェイスに、トンネルはありません
最も単純で最もトラブルのない状況。 以下、(単純化するために)当然のことと考えます。ゲートウェイ自体はトラフィックを生成せず、単に送信します。
そのため、ここではすべてが簡単です。両方のインターフェイスでキューを停止し、ローカルネットワーク(送信ストリーム)に見えるインターフェイスで、クライアント(受信)の速度を制御します。 それぞれ、外部インターフェイスで発信。 すべてがうまくいき、面白いことは何もありません。
別の内部インターフェイスを追加する
今、すべてがそんなに良いわけではありません。 内部ネットワーク間で「着信」ストリームを分割する方法は? 隣接インターフェイスのキューは、チャネルの実際の負荷について何も知りません。 ここでは、速度全体を半分に分割し、各ネットワークに半分を与えることができます。 その結果、2番目のネットワークがチャネルを使用せず、2番目のネットワークが最大値を必要とする場合、その半分しか受信しません...
ifbのアイデアは、実際のインターフェイスの前に擬似インターフェイスを配置することです。したがって、実際のインターフェイスの「着信」ストリームの制御を開始します。 残念ながら、このバレルにはタールが多すぎます。 ifbは非常に特殊であるため、iptablesユーティリティのラベル付けおよびフィルタリングメカニズムを適用できないため、tcでのみ可能です。 なぜtcが悪いのですか? そして、フィルタリングとラベル付けの観点から、彼はほとんど知識がなく、構文はすでに完全に異なっているという事実。
tcがどれほど悪いものであっても、彼はタスクを非常にうまく解決し、着信インターフェースにそれを置くことができます。そして、内部ルールからルールを削除します。
次に、トンネルを使用して2つのオフィスを接続します
今、すべてが本当に悪くなっています。 通常のインターフェイスと同じように機能する新しいインターフェイスがありますが、他のインターフェイスの中でも「静かに」別のインターフェイスの帯域幅を使用します。
現在、トラフィックを効率的に分散することはできません。ifbはここでも役に立ちません。 ソリューションは「額」のままです。トンネルに固定レーンを割り当て、トンネルのコンテンツを通常のインターフェイスとして管理します(ifbと通常のキューをハングさせることにより)。
すべてが「悪くない」ものであり、トンネルや通常のネットワークに与えられた速度(見方)を失うことができるのは無駄なことです。
LXCが役立ちます!
一般に、netnsを使用する主なアイデアは、コンテナを使用する方が簡単だということです(ただし、より多くのリソース、主にディスク領域を消費します)。
そのため、「外部」インターフェイスと「内部」インターフェイスの間のインターフェイスの中間チェーンが必要です。 すべてのトラフィックのQoSを簡単に作成できるのはこのチェーン上にあり、そこから失われる最大値は4.5%です(ここではオーバーヘッドをカウントします。ここではIPSec \ GREを使用します)。車線、私達は私達を出入りするすべてのトラフィックがトンネルから来ると仮定します)。
誰でもLXCでコンテナを作成できると思うので、必要になる可能性のあるいくつかの詳細だけを検討します。
したがって、コンテナ構成では次が必要です。
実際の外部インターフェイスをコンテナに追加します(コンテナに「プッシュ」するため、メインのネームスペースから「消えます」)。
lxc.network.type = phys lxc.network.flags = up lxc.network.link = enp3s6
または同様にvlanの場合:
lxc.network.type = vlan lxc.network.flags = up lxc.network.link = enp2s0 lxc.network.vlan.id = 603
メインシステムとの通信に使用するインターフェイスを追加します(スクリプトはメインシステムのインターフェイスを起動します。構成は事前に設定する必要があります)。
lxc.network.type = veth lxc.network.flags = up lxc.network.veth.pair = route0 lxc.network.name = eth1 lxc.network.hwaddr = 02:b2:30:41:30:25 lxc.network.script.up = /usr/bin/nmcli connection up route0
コンテナを起動/停止するときに、メインシステムのインターフェイスの自動起動と自動停止を追加します。
lxc.hook.pre-start = /var/lib/lxc/route0/pre-start.sh lxc.hook.post-stop = /var/lib/lxc/route0/post-stop.sh
/var/lib/lxc/route0/pre-start.sh
#!/bin/sh /usr/bin/nmcli connection down vlan603 >/dev/null 2>&1 exit 0
/var/lib/lxc/route0/post-stop.sh
#!/bin/sh /usr/bin/nmcli connection up vlan603 >/dev/null 2>&1 exit 0
tun \ tapインターフェイスを使用する機能を追加します。
lxc.hook.autodev = /var/lib/lxc/route0/autodev.sh
/var/lib/lxc/route0/autodev.sh
#!/bin/bash cd ${LXC_ROOTFS_MOUNT}/dev mkdir net mknod net/tun c 10 200 chmod 0666 net/tun
いくつかのルーティングパラメータを制御しましょう(より「狭い」アクセス許可を作成する方法を知っている人は、ヒントを求めます)。
lxc.mount.auto = proc:rw sys:ro
必要に応じて、コンテナを自動起動します。
メインシステムでは、コンテナの起動時に表示されるroute0インターフェイスのプロファイルが必要です。NetworkManagerを使用していると想定しています。
まだ設定する必要があるもの:
- メインシステムでroute0インターフェイスのIPアドレスを設定します。例:192.168.20.22/30およびデフォルトルート192.168.20.21
- コンテナで、たとえば192.168.20.21/30および192.168.20.22を介した内部ネットワーク192.168.21.0/24へのルートなど、eth1インターフェイスのIPアドレスを設定する必要があります
- コンテナでは、「外部」インターフェース、マスキングおよび転送を設定する必要があります。
- メインシステムでは、ほとんどの場合転送のみが必要になります。
- 外部ネットワーク(トンネルを含む)に移動する必要のあるものはすべて、コンテナに配置します。
ここで、メインシステムとコンテナを接続するインターフェイスの発信フローにキューを設定します。 これで、トラフィックの宛先の決定に問題はなくなり、プロバイダーから利用可能な帯域全体を使用できます(トンネルからのオーバーヘッドの割合を考慮に入れて)。
PS Linuxでインターネットを配布する「流域」の時代は急速に消滅し、ハードウェアルーターのコストはより魅力的になり、その能力と柔軟性は「大きな」兄弟に劣らず、同じMikrotikはこの「問題」を問題なく解決します。