TCP/UDP

【図解】TCP window size の仕組み〜MSS(MTU)との違い,calculated window size,unknown factor,受信バッファの設定変更~

TCP window size とは

TCP ウィンドウサイズとは、クライアントやサーバ等のホストが TCP 接続する際にどのくらいのパケットを受け入れられるかを示す値です。

受信バッファとも呼ばれます。

TCP ヘッダにある Window フィールドを使って、「自分のメインメモリがどれくらいの Byte 数の通信を受け入れられるか」を相手に示す仕組みになっています。

MSS は経路途中の NW 機器が「1 パケット当たりどのくらいのサイズなら受け入れられるか」を示すのに対し、Window Size は TCP 通信の端末間が「ACK 無しにどのくらいの TCP ペイロード (MSS) を受信できるか」を示します。

以下に Window Size と MSS (≒MTU) との違いを示します。

MTU は Ethernet インタフェースの1パケットあたりの最大サイズです。MSS は TCP セグメンテーションによる分割時の最大サイズを意味しますが、これは多くの場合、MTU から計算されます。(ルータに adjust-mss の設定があるとルータによって最適なものに書き換えられる)

※ MTU と MSS の違いについては以下を参照して下さい。

【図解】MTUとMSS, パケット分割の考え方 ~IPフラグメンテーションとTCPセグメンテーション~
MTUとMSSの違いMTU(MaximumTransmissionUnit)MT...

一方、Window サイズはアプリケーションのプログラミングによってそのサイズが決まります。

例えば上図の場合、ファイルサービスを行うアプリケーションがパケット受信のためにどれくらいメモリにバッファを設けるかを基準に、開発者が決めます。

また、この Window サイズはパケット送受信の中で変更することができます。

つまり、アプリケーションが「もう空き容量が 1460 Byte しか無いよ」というときは Window=1460 にして送信します。受け取った相手は状況を察し、1460 Byte 以上は送らないようにします。

このように Window を動的に変化させる仕組みを窓の開け閉めになぞらえスライディングウィンドウと呼びます。

【図解】TCPのフロー制御と輻輳制御とその違い 〜スライディング ウィンドウ サイズ, スロースタート, AIMD〜
TCPのフロー制御の実装TCPではデータ(セグメント)を受信したことをACKで相...

Calculated window size とは?

Window サイズは TCP ヘッダフォーマットとして 16 bit 用意されています。

単位は Byte ですので、2の16乗=64 KB 分用意されています。TCP が生まれた 1981 年においてはこの値はそんなに悪くなかったかもしれませんが、現代の技術レベルにおいては全然足りません。

1988 年でその問題が予測されていたようで、この年に RFC 1072 として TCP オプションという形で Window Scale が追加されました。

これは Window サイズを何倍するかを決める値です。

TCP syn および TCP syn/ack の際にこのオプションを付けて相手に送ることで、その TCP コネクション内の通信はその倍数分だけ Window サイズを掛け算します。

例えば TCP syn で Window Scale を 256 にして送信した場合、以降の通信で Window=250 とした場合、相手は 250 * 256 = 64,000 Bytes と解釈します。

この掛け算の結果を、Wireshark では [Calculated window size ] と表示します。

以下の例だと、"Window size value" が Window フィールドの値、"Window size scaling factor" が TCP syn 時の Window Scale の値、Calculated window size はそれらの掛け算です。

RFC 7323 にも書かれていますが、Window Scale は 2 の 14 乗が上限です。Window Size が 2 の 16 乗なのでこれと合わせて 2 の 30 乗 = 1 GBytes までを Window Size として使うことができるようになります。

Window size scaling factor: -1 (unknown) とは?

Window Scale オプションは TCP syn, syn/ack の時にしか使うことができません。

なので TCP syn や syn/ack の送受信が終わった後からパケットキャプチャを開始した場合は Window Scale が分からないので、[Window size scaling factor: -1 (unknown) ] と表示します。

Windows での受信バッファ(TCP Window Size)の設定

XP 以前はレジストリの変更により任意にサイズ変更が出来たようですが、Vista 以降は "Receive Window Auto-Tuning" 機能に一任され、利用者によるサイズ変更はできないようです。

以下の MS のブログページによると、

A word about AutoTuningLevel - TCP Receive Window Auto-Tuning Level explained

Window サイズの決定については 2 つの要因があるそうです。

  1. その通信を行うアプリケーション側からの指定(つまりプログラマによって決定)
  2. もしアプリケーション側からの指定が無い場合はインタフェースのリンク速度によって決定

2 については以下のルールになるそうです。

Below 1 megabits per second (Mbps): 8 kilobytes (KB)
1 Mbps to below 100 Mbps: 17 KB
100 Mbps to below 10 gigabits per second (Gbps): 64 KB
10 Gbps or higher: 128 KB

ただし、そこから前述した "Receive Window Auto-Tuning" 機能による調整が入ります。デフォルトでは Tuning-Level は [ normal ] に設定されており、このルールの値よりそれなりに大きな値を取ることが出来ます。

もし「出来る限り大きな値を取れるようにしたい!」というのであれば、Tuning-Level を [ experimental ] に設定します。

C:\> netsh interface tcp set global autotuninglevel=experimental

逆に、控えめにしたい場合は [ restricted ] , 非常に控えめにしたい場合は
[ highlyrestricted ] を使います。

C:\> netsh interface tcp set global autotuninglevel={restricted | highlyrestricted}

また、常にルール通りの固定値にしたいのであれば [ disabled ] を使います。

C:\> netsh interface tcp set global autotuninglevel=disabled

なお、MS のブログでは、これらの設定により Window Scale が以下のようになったことをレポートしています。

  • experimental : Window Scale = 14
  • normal : Window Scale = 8
  • restricted : Window Scale = 4
  • highly restricted : Window Scale = 2
  • disabled : Window Scale オプション無し

Linux での受信バッファ(TCP Window Size)の設定

Linux の TCP Window Size の制御は Kernel Parameter により設定されています。

[root@localhost ~]# sysctl -a | grep rmem
net.core.rmem_default = 212992
net.core.rmem_max = 212992
net.ipv4.tcp_rmem = 4096        87380   6291456
net.ipv4.udp_rmem_min = 4096
[root@localhost ~]#

net.core.rmem_default および net.core.rmem_max が基本的に利用される Window Size です。単位は Byte で、default は初期値、max は最大値を意味します。

ですが実は Linux にも Windows のように Auto-Tuning 機能があり、この機能が無効の場合は上記2つにより決まりますが、有効の場合はこれ以外のパラメータも効いてきます。

Auto-Tuning 有効無効は net.ipv4.tcp_moderate_rcvbuf パラメータで決まります。1 が有効でデフォルトは 1 です。

[root@localhost ~]# sysctl -a | grep rcvbuf
net.ipv4.tcp_moderate_rcvbuf = 1

これが有効である場合、前述の net.ipv4.tcp_rmem や udp_rmem の設定が効いてくるわけです。

net.ipv4.tcp_rmem の値は [ min , default , max ] という並びになっています。min は最小値、default は初期値、max は最大値ですが、ややこしいことに初期値 (default) は net.core.rmem_default よりもこちらが優先なのですが、最大値 (max) は net.core.rmem_max が優先されます。

tcp(7): TCP protocol - Linux man page
TCPsupportsurgentdata.Urgentdataisusedtosignalthereceiverthatsomeimportantmessageispartofthedatastreamandthatitshouldbeprocessed...

nesukeの推薦図書

以下に該当する人なら熟読することを強く推奨します。

  • 周りのネットワークエンジニアよりも一歩抜き出た存在となり、価値を高めたい!
  • サーバエンジニアだけどネットワークも含めた総合的なセキュリティへの理解も深めていきたい!
本書は、ベストセラーの『マスタリングTCP/IP 入門編』を時代の変化に即したトピックを加え、内容を刷新した第6版として発行するものです。豊富な脚注と図版・イラストを用いたわかりやすい解説により、TCP/IPの基本をしっかりと学ぶことができます。プロトコル、インターネット、ネットワークについての理解を深める最初の一歩として活用ください。
本書は、日々更新されていくネットワークセキュリティ技術にキャッチアップしていくために必要となる基礎を体系的に網羅した「マスタリングTCP/IP シリーズ」の一冊です。基本的な暗号技術、それらのセキュリティプロトコルへの応用、認証技術、Web アプリケーションへの多様化する攻撃手法の理解と対策などを扱っています。
ブラウザにURLを入力してからWebページが表示されるまでの道筋をたどりながら、その裏側で働くTCP/IP、LAN、光ファイバなどの技術を説明していきます。インターネットを通ってサーバーまで行って帰ってくる道筋の途中には、今のネットワークの主要な技術要素が全部あります。そこでの機器やソフトウエアがどのように動き連携しているのかを探検すればネットワーク全体の動きがわかります。

コメント

タイトルとURLをコピーしました