tc シェイパー1つだけで各 VPN クライアントを制限できるわけではない
クライアントごとの制限には、計測用の識別子、2つの方向、分類ポイントが要る。トンネル上のシェイパー1つは、利用者ごとの割り当て1つではない。
指示は完全に聞こえる——すべての VPN クライアントを 20 Mbit/s に制限せよ、というものだ。しかし完全ではなく、トンネルインターフェース上の単一のキュー規律ではそれを実現できない。クライアントごととは、トンネルアドレスごと、端末ごと、アカウントごとのいずれかを意味しうるし、どの選択でもパケットの分類方法は変わる。ルールを書く前に、要件が実際にどれを指しているのかを決めよう。
以下の内容はすべて、その一文と動作するものとの間の隔たりについての話だ。
「クライアントごと」がまず意味すべきこと
トンネルアドレスは分類しやすく、再利用もしやすい。端末はもっと難しく、一つのアカウントが複数の端末を持ちうるし、一つの端末が複数のアドレスを持ちうるからで、とくに IPv6 ではそうなる。公平性のポリシーではアカウントが最も意味のある単位であり、パケットヘッダーから最も見つけにくい。どの定義もそれぞれ固有の計測キーを伴うので、その間で揺れるポリシーは説明どおりには動かない。
方向は二つ目の欠けた言葉だ。アップロード、ダウンロード、合算は三つの別の要件であり、一つのインターフェース上の下りルール一本で両方の経路をまかなえることはめったにない。
クライアントがまだ見える地点を選ぶ
どの方向もインターフェースに対して定義される。サーバーのトンネルから遠隔のクライアントへ出ていくものは、そのクライアントにとってのダウンロードであり、クライアントが送るものはトンネルに入ってから宛先へ向けて出ていく。方向ごとにスケジューリング地点を選び、そこでどのフィールドが存在するかを問おう。送信元 NAT より前なら、アップロードはまだクライアントの内部アドレスを運んでおり、変換後は単純な送信元一致では識別できなくなることがある。
暗号化された経路ではヘッダーが VPN の転送に属するので、内部アドレスに一致させるフィルターには一致させる対象がない。設計によってはもっと早く分類し、後段のスケジューラーにマークを渡せるが、その受け渡しは意図的でなければならない——パケットマーク、接続マーク、スケジューラークラスは別々の状態であり、一つの値が引き回されるわけではない。
バケットはひとりでに現れない
インターフェースに結び付いたトークンバケットは、それを使うトラフィックを整形するだけで、送信元アドレスごとに新しいバケットを作り出すわけではない。クラスベースの設計では代わりに選んだトラフィックをクラスに振り分け、フィルターが所属を決め、HTB のマニュアルは親に余った帯域があるときクラスのレートと上限を分けている。狙いが厳格な上限なら上限を設定し、借り入れの挙動を意図的に決めるべきで、すべてのレート数値を絶対的な最大値として扱ってはいけない。
要件がクライアントごとであるなら、同時に走る二つの転送は一つの割り当てを分け合うべきだ。各フローに全レートを与えるのは別のポリシーであり、ダウンロード一つだけを見るテストならどちらでも通ってしまう。
二台の端末、一つのアカウント、一つの割り当て?
二つの端末アドレスを別々に制限しても、両方の端末が同じ人物としてログインしていても、アカウント全体の割り当て一つには決してならない。一つのピアの背後で変換される LAN 全体や、分類器が想定しなかった追加の IPv6 アドレスも同じだ。アドレスと識別子の対応を最新に保ち、安定したアドレスは対応表を単純にするが持ち主を認証するわけではないことを覚えておこう。
バーストとキューの挙動も定義しよう。トークンバケットは平均を超える短いバーストを許し、バッファリングは遅延を加えるが、超過をポリシングすることと後回しにするためにキューに入れることは症状の異なる別の判断だ。
検証には、一つのクライアントから二つの転送を走らせ、二台目のクライアントを追加し、各方向でクラスのカウンターを読む。