Cato Client を用いた通信における MTU の調査

MTU とは

MTU (Maximum Transmission Unit) は、ネットワーク上で一度に送信できるデータの最大サイズのことを指します。一般的なイーサネットの MTU は1500バイトであり、イーサネットでIP通信を行う場合、IPパケットの最大サイズは1500バイトということになります。これより大きなデータを送信したい場合は、複数のパケットに分割する必要があります。

MTU の値はネットワーク接続の種類によって変わってきます。例えば PPPoE (PPP over Ethernet) を用いて通信を行っている場合、PPPoE でカプセル化されたデータがイーサネット上で送信されます。PPPoE のカプセル化に必要なオーバーヘッドは合計8バイトですので、PPPoE 接続の MTU は1492 (1500 – 8) バイトとなります。また、NTT東西のフレッツ光回線で PPPoE 接続を行う場合の MTU は1454バイトであり、v6プラス (IPoE 接続) 上で MAP-E または DS-Lite 方式による IPv4 通信を行う場合の MTU は1460バイトであるように、ネットワーク接続の種類によって MTU の値は異なります。

利用するネットワークの MTU の値を把握しておくことは、効率的な通信を行うために不可欠です。MTU よりも大きなサイズのデータを送信すると、ネットワーク上のどこかでパケットがフラグメント化または破棄されてしまいます。また、MTU よりも小さなサイズのデータを送信すると、パケットの数が増えることになるため通信処理のオーバーヘッドやパケット損失が増えることにもなります。

Cato クラウドを利用する場合においても、Socket や Cato Client と PoP 間の暗号化通信や、Cato クラウドのバックボーンネットワーク内の通信方式により、MTU は1500バイトよりも小さな値となっています。しかし、Cato クラウドにおける MTU の値はドキュメント上では公表されていませんでしたので、今回調査・検証してみました。

調査・検証環境

今回は AWS の Amazon EC2 上で主として Linux マシンを利用し、Cato Client を用いてインターネット経由で PoP に接続して調査・検証しました。実施のしやすさを優先して Linux マシンを用いていますが、後述の通り Windows マシンであっても同様の結果となります。

  • AWS リージョン : 東京 (ap-northeast-1)
  • OS : Ubuntu 22.04 LTS
  • Cato Client : 5.1.0.21 (deb 版)
  • 接続先 PoP : Tokyo_DC2

マシン起動直後は、インターネットにも繋がる ens5 というネットワークインターフェースと、ローカルループバックインターフェースの2つのがある状態です。

$ ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: ens5: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP group default qlen 1000
    link/ether 0a:b6:b1:e1:3d:c3 brd ff:ff:ff:ff:ff:ff
    inet 172.31.3.80/20 metric 100 brd 172.31.15.255 scope global dynamic ens5
       valid_lft 3479sec preferred_lft 3479sec
    inet6 fe80::8b6:b1ff:fee1:3dc3/64 scope link
       valid_lft forever preferred_lft forever

Amazon EC2 ではジャンボフレームが利用可能なのでインターフェースの MTU は9001バイトとなっていますが、Amazon EC2 とインターネットとの通信時の MTU は1500バイトです。

Cato Client 接続直後の状態

それでは、Cato Client を用いて PoP に接続してみます。 

$ cato-sdp start --user SDPユーザアカウント --account テナント名 --reset-cred

PoP に接続すると、tun0 というインターフェースが新たに作られ、デフォルトルートとしても設定されていました。150.195.209.225 は PoP のIPアドレスです。

$ ip addr show dev tun0
4: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1370 qdisc fq_codel state UNKNOWN group default qlen 500
    link/none
    inet 100.67.0.168/32 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 fe80::84e8:ac2b:6e3b:4f84/64 scope link stable-privacy
       valid_lft forever preferred_lft forever

$ ip route
default dev tun0
default via 172.31.0.1 dev ens5 proto dhcp src 172.31.3.80 metric 100
8.8.8.8 dev tun0
10.254.254.1 dev tun0
150.195.209.225 via 172.31.0.1 dev ens5
172.31.0.0/20 dev ens5 proto kernel scope link src 172.31.3.80 metric 100
172.31.0.1 dev ens5 proto dhcp scope link src 172.31.3.80 metric 100
172.31.0.2 dev ens5 proto dhcp scope link src 172.31.3.80 metric 100

$ ethtool -i tun0 | grep driver
driver: tun

tun0 は Linux の TUN デバイス機能を用いて実現された仮想的なインターフェースであり、tun0 に書き込まれたIPパケットは Cato Client のプロセスがいったん受け取り、DTLS でカプセル化されて ens5 を通して PoP に送信されていきます。

tun0 の MTU が1370と設定されていますので、マシン上で動作するアプリケーションが PoP 経由で行う通信では1370バイト以下のIPパケットしか送信できないよう制限されています。

PoP 接続におけるオーバヘッドの確認

マシンから送信されるIPパケットは、DTLS プロトコルを用いた暗号化通信によってカプセル化されて PoP に送信されます。

まず、DTLS のカプセル化によるオーバーヘッドを確認してみます。インターネット側にあるターゲットマシンに ping で1000バイトのデータを送信し、tcpdump でパケットを確認しました。

$ sudo tcpdump -i any -nn not port 22
05:45:27.868003 tun0 Out IP 100.67.0.168 > 35.78.XXX.XXX: ICMP echo request, id 2, seq 1, length 1008
05:45:27.868066 ens5 Out IP 172.31.3.80.52292 > 150.195.209.225.443: UDP, length 1073
05:45:27.872783 ens5 In IP 150.195.209.225.443 > 172.31.3.80.52292: UDP, length 1073
05:45:27.872860 tun0 In IP 35.78.XXX.XXX > 100.67.0.168: ICMP echo reply, id 2, seq 1, length 1008

結果の1行目 (tun0 Out) は ping コマンドによって送信されたパケットを表しており、そのパケット長は1028バイト (IPヘッダ20バイト、ICMPヘッダ8バイト、データ1000バイト) です。

2行目 (ens5 Out) は Cato Client のプロセスから PoP に送信された DTLS のパケットであり、そのパケット長は1101バイト (IPヘッダ20バイト、UDPヘッダ8バイト、データ1073バイト) です。

3行目と4行目は上記の逆向きのパケットです。

アプリケーションが送信したパケットに対し、PoP に送信されたパケットは73バイト大きくなっており、これが PoP 接続におけるオーバーヘッドであると言えます。

なお、Cato Client と PoP との間では暗号スイート “TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 ” を用いて DTLS v1.2 接続が確立しており、DTLS によるカプセル化単体のオーバーヘッドは57バイトですので、Cato Client が16バイトの何らかのデータを付加していることがわかります。

 

PoP 経由のインターネット通信における MTU の調査

さて、PoP 接続におけるオーバーヘッドが73バイトであるのに対し、MTU が1370バイトに制限されているのは小さすぎるように感じます。インターネットとの通信部分の MTU が1500バイトですので、tun0 インターフェースの MTU は1427であることを期待したいです。

そこで、tun0 の MTU を手動で変更し、実際に何バイトのIPパケットを送受信できるか確認してみました。

$ sudo ip link set dev tun0 mtu 1427

$ ip addr show dev tun0
4: tun0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1427 qdisc fq_codel state UNKNOWN group default qlen 500
    link/none
    inet 100.67.0.168/32 scope global tun0
       valid_lft forever preferred_lft forever
    inet6 fe80::84e8:ac2b:6e3b:4f84/64 scope link stable-privacy
       valid_lft forever preferred_lft forever

ping コマンドで1427バイトのIPパケット (ICMPデータ長 1399) を送信したところ、PoP に対してフラグメンテーションを起こさずに送信はできるものの、同じサイズの受信したパケットではフラグメンテーションが発生していました。インターネット側にあるターゲットマシン上では受信・送信ともにフラグメンテーションは発生していませんでした。

$ sudo tcpdump -i any -nn not port 22
05:49:32.968442 tun0 Out IP 100.67.0.168 > 35.78.XXX.XXX: ICMP echo request, id 6, seq 1, length 1407
05:49:32.968501 ens5 Out IP 172.31.3.80.52292 > 150.195.209.225.443: UDP, length 1472
05:49:32.973275 ens5 In IP 150.195.209.225.443 > 172.31.3.80.52292: UDP, length 1425
05:49:32.973275 ens5 In IP 150.195.209.225.443 > 172.31.3.80.52292: UDP, length 112
05:49:32.973362 tun0 In IP 35.78.XXX.XXX > 100.67.0.168: ICMP echo reply, id 6, seq 1, length 1360
05:49:32.973381 tun0 In IP 35.78.XXX.XXX > 100.67.0.168: ip-proto-1

データ長を少しずつ小さくしていったところ、最終的に1383バイト以下のIPパケットであればフラグメンテーションは発生しないという結果が得られました。

また、TCP 接続を試したところ、クライアントから提示した MSS (Maximum Segment Size, 通常は MTU – 40) は1387バイトであるのに対し、サーバから提示された MSS は1343バイトとなっていました。

このことから、PoP 経由でインターネットと通信する際の実質的な MTU は1383バイトであり、tun0 インターフェースの MTU を1383に増やせば、より効率的に通信できるようになる可能性があると言えます。また、1383バイトを超えるとクライアントまたは PoP 内部でフラグメンテーションが発生するものと推測できます。

PoP の違いによる MTU の差異の確認

ここまでは Tokyo_DC2 PoP に接続して試していましたが、PoP によって違いがあるか確認しました。

AWSの大阪リージョンでマシンを用意して Osaka_DC2 PoP に接続してみると、PoP 経由のインターネット通信の実質的な MTU は1383であり、Tokyo_DC2 PoP と同じ結果となりました。

一方、AWSのバージニア北部リージョンでマシンを用意して Ashburn_DC2 PoP に接続して同様に試したところ、この PoP 経由のインターネット通信の実質的な MTU は1367であることがわかりました。Cato PoP は世界各地に存在し、PoP ごとに物理ネットワークの特性がおそらく異なるものと考えられます。

Ashburn_DC2 PoP に接続した場合も tun0 インターフェースの MTU は1370として作られていましたので、PoP に合わせて MTU を1367に変更すれば、TCP 以外の通信において僅かですがフラグメンテーションが発生しにくくなり、効率的に通信できるようになる可能性があります。

WAN 通信における MTU の調査

Tokyo_DC2 PoP に接続したマシンを2台用意し、PoP 経由で行う Cato Client 間の WAN 通信についても確認してみました。

ping コマンドで確認した MTU は想定通り1383となっていましたが、TCP 接続の MSS は1250で確立していました。 (100.67.0.74 がクライアント、100.67.0.214 がサーバです。)

$ ## TCP クライアント側
$ sudo tcpdump -i any -nn not port 22
01:44:42.218685 tun0 Out IP 100.67.0.74.32958 > 100.67.0.214.30000: Flags [S], seq 487546713, win 65189, options [mss 1387,sackOK,TS val 2662317462 ecr 0,nop,wscale 6], length 0
01:44:42.218844 ens5 Out IP 172.31.3.80.42447 > 103.203.222.69.443: UDP, length 105
01:44:42.223744 ens5 In IP 103.203.222.69.443 > 172.31.3.80.42447: UDP, length 105
01:44:42.223837 tun0 In IP 100.67.0.214.30000 > 100.67.0.74.32958: Flags [S.], seq 1022880092, ack 487546714, win 64625, options [mss 1250,sackOK,TS val 3972244012 ecr 2662317462,nop,wscale 6], length 0
01:44:42.223863 tun0 Out IP 100.67.0.74.32958 > 100.67.0.214.30000: Flags [.], ack 1, win 1019, options [nop,nop,TS val 2662317467 ecr 3972244012], length 0
01:44:42.223899 ens5 Out IP 172.31.3.80.42447 > 103.203.222.69.443: UDP, length 97


$ ## TCP サーバ側
$ sudo tcpdump -i any -nn not port 22
01:44:42.221845 ens5 In IP 103.203.222.130.443 > 172.31.26.144.56542: UDP, length 105
01:44:42.221930 tun0 In IP 100.67.0.74.32958 > 100.67.0.214.30000: Flags [S], seq 487546713, win 65189, options [mss 1250,sackOK,TS val 2662317462 ecr 0,nop,wscale 6], length 0
01:44:42.221961 tun0 Out IP 100.67.0.214.30000 > 100.67.0.74.32958: Flags [S.], seq 1022880092, ack 487546714, win 64625, options [mss 1387,sackOK,TS val 3972244012 ecr 2662317462,nop,wscale 6], length 0
01:44:42.221995 ens5 Out IP 172.31.26.144.56542 > 103.203.222.130.443: UDP, length 105
01:44:42.226638 ens5 In IP 103.203.222.130.443 > 172.31.26.144.56542: UDP, length 97
01:44:42.226682 tun0 In IP 100.67.0.74.32958 > 100.67.0.214.30000: Flags [.], ack 1, win 1019, options [nop,nop,TS val 2662317467 ecr 3972244012], length 0

WAN 通信ではどうやら MSS が MTU よりもかなり小さくなるよう調整されているようです。クライアント側とサーバ側で見える TCP 通信の送信元・宛先IPアドレスやポート番号が同一であることから、PoP 側で TCP の終端は行われていないように見えますし、Network Rules 設定で TCP Acceleration を有効・無効のどちらにしても同じ結果でした。

また、Tokyo_DC2 PoP および Ashburn_DC2 PoP に接続したマシンを1台ずつ用意し、Cato クラウドのバックボーンネットワークを経由した WAN 通信についても確認したところ、MTU 1383、TCP MSS 1250 で通信でき、同一 PoP に接続した場合と同じ結果となりました。

WAN 通信であれば、どの PoP に接続していたとしても MTU 1383、TCP MSS 1250 で通信できると言えると思います。

回線の MTU が小さい場合の検証

ここまでインターネット回線の MTU が 1500 である環境で Cato Client を起動して試していましたが、実際の MTU はそれよりも小さい場合が多いです。そこで、試しに今回の検証マシンのインターネットと繋がるインターフェースの MTU を1400に変更し、Cato Client の振る舞いを検証しました。

$ sudo ip link set dev ens5 mtu 1400

Cato Client で改めて Tokyo_DC2 PoP に接続してみると、相変わらず MTU 1370 の tun0 インターフェースが作られましたので、インターネット回線側の MTU を考慮しない動作となっていることがわかります。

また、インターネット上のマシンに ping コマンドで1370バイトのIPパケットを送信すると、DTLS パケットがフラグメント化されて送信されていました。IPパケットの DF (Don’t Fragment) ビットを立てても結果は同じです。

$ sudo tcpdump -i any -nn not port 22 
06:30:50.768469 tun0 Out IP 100.67.0.195 > 35.78.XXX.XXX: ICMP echo request, id 12, seq 1, length 1350
06:30:50.768526 ens5 Out IP 172.31.3.80.45201 > 150.195.209.226.443: UDP, length 1415
06:30:50.768529 ens5 Out IP 172.31.3.80 > 150.195.209.226: ip-proto-17
06:30:50.773356 ens5 In IP 150.195.209.226.443 > 172.31.3.80.45201: UDP, length 1415
06:30:50.773416 tun0 In IP 35.78.XXX.XXX > 100.67.0.195: ICMP echo reply, id 12, seq 1, length 1350

tun0 インターフェースの MTU が1370の場合、PoP に送信される DTLS パケットは最大で1443バイトとなり、インターネット回線の MTU を超えるとフラグメンテーションが発生します。そのため、MTU が 1443 バイト未満のインターネット回線を利用している場合は tun0 インターフェースの MTU を小さくしたほうが良く、その値は “インターネット回線の MTU – 73” とするのが良いと言えます。

なお、日本のお客様のインターネット回線であれば通常は問題となりませんし、仮に MTU が小さなインターネット回線を利用していたとしても、フラグメンテーションが発生して非効率的ではあるものの通信できないわけではありませんので、気にしすぎる必要はありません。

TLS で PoP に接続した場合

Cato Client から PoP に対して DTLS (over UDP) ではなく TLS (over TCP) で接続することもできます。

$ cato-sdp start --user SDPユーザアカウント --account テナント名 --reset-cred --tcp 2

TLS で接続した場合も MTU が1370バイトの tun0 インターフェースが作られました。

Cato Client と PoP との間の TCP 接続の MSS は1460バイトで確立しており、これはインターネット回線の MTU が1500バイトであることから期待通りの結果です。

また、インターネット側にあるターゲットマシンに ping で1000バイトのデータを送信したときの tcpdump の結果は次の通りです。

$ sudo tcpdump -i any -nn not port 22 
05:14:50.812285 tun0 Out IP 100.67.0.252 > 35.77.117.11: ICMP echo request, id 18, seq 1, length 1008
05:14:50.812530 ens5 Out IP 172.31.3.80.53346 > 150.195.209.236.443: Flags [P.], seq 828:1886, ack 607, win 17546, options [nop,nop,TS val 3527218244 ecr 1214912535], length 1058
05:14:50.815134 ens5 In IP 150.195.209.236.443 > 172.31.3.80.53346: Flags [.], ack 1886, win 65535, options [nop,nop,TS val 1214913289 ecr 3527218244], length 0
05:14:50.817393 ens5 In IP 150.195.209.236.443 > 172.31.3.80.53346: Flags [.], seq 607:1687, ack 1886, win 65535, options [nop,nop,TS val 1214913291 ecr 3527218244], length 1080
05:14:50.817454 tun0 In IP 35.77.117.11 > 100.67.0.252: ICMP echo reply, id 18, seq 1, length 1008
05:14:50.859427 ens5 Out IP 172.31.3.80.53346 > 150.195.209.236.443: Flags [.], ack 1687, win 17546, options [nop,nop,TS val 3527218291 ecr 1214913291], length 0

1028バイトのIPパケットが TLS でカプセル化されて1110バイトのIPパケットとして送信されていますので、オーバーヘッドは82バイトと言えます。

さらに、ターゲットマシンに TCP 接続を行うと MSS は1036バイトで確立し、ping による確認でも1076バイトを超えるIPパケットでは受信時にフラグメンテーションが発生しましたので、PoP 内部で MTU が1076バイトとなっているものと推測できます。そのため、tun0 インターフェースの MTU を1076に変更すると TCP 以外の通信において効率的に通信できるようになる可能性があります。

なお、PoP との間では暗号スイート “TLS_AES_256_GCM_SHA384” を用いた TLS v1.2 接続が確立しており、TLS によるカプセル化単体のオーバーヘッドは81バイト (IPヘッダ20バイト、TCPヘッダ20バイト、TCPオプション12バイト、TLSヘッダ5バイト、ノンス8バイト、認証タグ16バイト) ですので、Cato Client が1バイトの何らかのデータを付加しているようです。

Windows 版 Cato Client で接続した場合

多くの方が利用している Windows 版の Cato Client でも同様に確認しました。利用したバージョン 5.8.15 です。

まず、Cato Client をインストールした時点で、2つのネットワークインターフェース (下記例の36番と31番) が新たに作成されました。

c:\>netsh interface ipv4 show interfaces

Idx     Met         MTU          状態                 名前
---  ----------  ----------  ------------  ---------------------------
  1          75  4294967295  connected     Loopback Pseudo-Interface 1
 36           5        1380  disconnected  CatoNetworks
  6          15        1500  connected     Ethernet 3
 31          35        1380  disconnected  Ethernet 4

どちらも MTU は1380バイトとなっており、PoP に接続すると36番のインターフェースが connected に変化して通信で利用されました。

PoP との接続は Linux 版と同じ暗号スイートで DTLS v1.2 で行われ、73バイトのオーバーヘッドがありました。また、MTU を手動で変更して試したところ、PoP 経由のインターネット通信における MTU も同様に1383バイトでした。

このことから、Linux 版で調査・検証した結果は Windows 版でも同じように適用できるものと考えられます。

まとめ

Cato Client を利用して PoP に接続した場合の通信の MTU について調査・検証したところ、推測を含むものの、次の結果が得られました。

  • DTLS で PoP に接続して通信する場合の MTU は1383である。ただし、PoP によってインターネット通信の MTU は異なる場合がある。
  • WAN 通信では TCP の MSS は1250にまで小さく調整される。
  • TLS で PoP に接続して通信する場合の MTU は1076である。
  • Cato Client の仮想的なネットワークインターフェースの MTU のデフォルト値は1380 (Windows) または1370 (Linux) である。
  • Cato Client はインターネット回線の MTU を考慮しない。

これらの結果から、PoP に合わせて MTU の値を大きくしたり、あるいはインターネット回線に合わせて小さくしたりすれば、より効率的に通信できる可能性があり、スループットの増加やレイテンシの減少が見込まれます。ただし、その実測値までは評価できておらず、効果は微々たるものかもしれません

Socket や vSocket で接続した場合については調査・検証していませんが、Cato Client と同様に PoP との間で DTLS 接続を行っていますので、MTU はおそらく同じなのではないかと思います。Socket や vSocket の LAN 側 MTU は変更できませんので、効率化の余地もほとんど無いように思います。

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