VPSにTCP BBRなhttp/2 Proxyを構築してMVNOなiPhoneから使う


# はじめに

　自宅のインターネット環境として、レオネットからOCNへ抜ける環境を使っています。
　しかし、IPv6とのデュアルスタックがないこと、AbemaTVなど動画を見ているとしばしばバッファが発生することがありました。
　これらをVPS上のProxyで改善できないか、あわよくばMVNOの通信環境も改善できないかと思いました。

# 対象読者

- MVNOを混雑する時間帯も快適に使いたい人
- pingでロスがある、rttが2桁ms以上ある環境からもっとスループットが欲しい人

# 前提条件

- VPSにはChonoha VPSの1GBプラン、Ubuntu 16.04 (64bit)を使っています。
- 固定回線は20時台にPingが1%ほど落ち、rttが50msあるアクセス環境です。
- MVNOは4G、iPhone 7 plusを使っています。

# 1. Proxyの構築

　Proxyサーバには、Squidを利用します。

## 1-1. Squidのインストール

Squidをインストールするには、次のコマンドを入力します。

```
apt-get install squid
```

　インストールができたら、設定ファイルを編集し、次の内容を先頭に挿入します。

```
vi /etc/squid/squid.conf
```

```
acl localnet src 127.0.0.1/32 ::1
acl localdomain srcdomain .hiroshima.ocn.ne.jp
acl localdomain srcdomain .mineo.jp
http_access allow localnet
http_access allow localdomain

visible_hostname unknown
#forwarded_for off
#request_header_access X-FORWARDED-FOR deny all
#request_header_access Via deny all
#request_header_access Cache-Control deny all
#reply_header_access X-Forwarded-For deny all
#reply_header_access Via deny all
#reply_header_access Cache-Control deny all

client_persistent_connections off
server_persistent_connections off

negative_ttl 0 minutes
shutdown_lifetime 0 seconds

acl NOCACHE src all
cache deny NOCACHE
```

　aclの節では、許容する接続元に自分の利用するプロバイダのドメインを指定しています。これは、IPアドレスが変わるためです。利用する環境と許容するセキュリティレベルに合わせて設定してください。「#」でコメントアウトしているのは、プロキシ特有の情報を隠す設定ですが、隠す必要がない場合は無効にしたほうがキャッシュコントロールが効いて早いです。また、squidのキャッシュは無効にしています。

　設定を反映させるために、サービスを再起動します。

```
service squid restart
lsof -i | grep squid
squid    2939    proxy    6u  IPv6  26526      0t0  UDP *:40851 
squid    2939    proxy    8u  IPv4  26527      0t0  UDP *:57064 
squid    2939    proxy   11u  IPv6  26530      0t0  TCP *:3128 (LISTEN)
squid    2939    proxy   14u  IPv6  26533      0t0  UDP localhost:33861->localhost:59409 
```

## 1-2. Chromeからの動作確認

　では、ChromeからProxyを利用してアクセスできるか確認してみましょう。
　Chromeは、利用するProxyサーバを設定するにはWindowsの設定画面を利用するのが一般的ですが、それではシステムの設定も変わってしまいます。しかし、Chromeの起動スクリプトを利用すれば、Chromeのみ指定したProxyサーバを利用することができます。

以下は、起動ショートカットの設定例です。--proxy-server= の次にsquidを起動しているサーバのIPアドレスを、--proxy-bypass-list=の次に、Proxyを介さずにアクセスしたいIPアドレスを入力します。

```
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --proxy-server=111.111.111.111:3128 --proxy-bypass-list=localhost;127.0.0.1;192.168.*
```

　これでProxyを介したインターネットアクセスになっているはずです。デュアルスタックになっていることを確認するために、IPv6テストサイトへアクセスしてみましょう。

```
https://test-ipv6.jp/

一般のインターネット上で見えるあなたの IPv4 アドレスは 111.111.111.111

	一般のインターネット上で見えるあなたの IPv6 アドレスは 2400:8500:1302:847:111:111:111:111

	ご利用のインターネットサービスプロバイダ (ISP): INTERQ GMO Internet,Inc

	あなたはIPv6接続に対応しているため、他のIPv6サイトへの到達性の状況を示すタブを表示します。

	このWebサイトではベータ版のHTTPSをサポートしています。

	あなたの DNS サーバ (おそらくお使いのプロバイダが運用) は、IPv6 インターネットアクセスがあるように思われます。
あなたの事前対応点
10/10	コンテンツ側が IPv6 のみになった際の、あなたの IPv6 の安定性と準備状況
```

　これで、デュアルスタックのインターネットアクセス環境が整いました。

## 1-3. iPhoneからのProxy利用

　せっかくProxyを構築したので、スマホからも利用したいと思いませんか？
　Wifiからのproxy設定は簡単にできるのでいいとして、モバイル回線からProxyを利用する場合は、プロファイルに手を入れる必要があります。

　ご自身の利用するMVNOからプロファイルを入手して、以下の内容を追記します。

```
<key>APNs</key>
<array>
  <dict>
    ~~~ ここから ~~~
	<key>ProxyServer</key>
	<string>111.111.111.111</string>
	<key>ProxyPort</key>
	<integer>3128</integer>
    ~~~ ここまで ~~~
  </dict>
</array>
```

　編集したプロファイルを利用するには、iPhoneに読み込ませる必要があります。編集前のオリジナルのプロファイルと編集後のプロファイルをまとめてiCloud等のメールに送信しておけば、もしVPSの障害などで接続できない場合も切り戻しが容易になります。

　プロファイルを切り替え後は、iPhoneから先ほどのIPv6テストサイトへアクセスして、VPSのプロバイダが表示されるか確認してみましょう。

  squidのログをみて確認するのも良いでしょう。less /var/log/squid/access.logで開いたあと、Gで最下段、shift+fで順次表示に設定したあと、safariでgoogleを開いてみましょう。googleを開いたログが見えましたか？

# 2. Secure Proxyの構築

　ここまでで、Squid経由でインターネット接続できるようになりました。しかし、ブラウザからSquidまではhttp 1.1で接続されているため、通信内容は暗号化されません。どうせSSL化するなら、http/2に対応したSecure Proxyを構築してみましょう。

　nghttpxを、Squidと連携して動作させます。
　ここまでは、次のような接続構成でした。

```
　PC ---(IPv4 Internet, http 1.1)--- Squid ---(IPv4/IPv6 Internet)
```

　nghttpx を利用すると、ProxyまでのアクセスをSSLで暗号化できます。

```
  PC ---(IPv4 Internet, http/2 SSL)--- nghttpx - Squid ---(IPv4/IPv6 Internet)
```

## 2-1. ドメイン取得、SSL証明書の入手

　ドメインを取得してDNSにIPアドレスを設定し、Let's Encryptで証明書を取得します。ここでは、説明を省略します。

## 2-2. nghttpxのインストール

　nghttpxをパッケージからインストールします。

```
apt-get install nghttp2
```

　インストールが終わったら、設定ファイルを開き、既存の設定をコメントアウトして、http/2プロキシとして動作させるためのの設定を入力します。
　private-key-file、certificate-fileには、取得した証明書のフルパスを入力します。

```
vi /etc/nghttpx/nghttpx.conf
```

```
frontend=0.0.0.0,3127
backend=127.0.0.1,3128
private-key-file=/etc/letsencrypt/live/example.net/privkey.pem
certificate-file=/etc/letsencrypt/live/example.net/fullchain.pem
http2-proxy=yes
workers=1

#accesslog-file=/var/log/nghttpx/access.log
#errorlog-file=/var/log/nghttpx/error.log

verify-client=no
add-x-forwarded-for=yes
no-via=yes
no-ocsp=yes
no-host-rewrite=yes
tls-proto-list=TLSv1.2
ciphers=ECDHE+AES128
```

　ログを出力する場合は、保存先ディレクトリを作成後、コメントを外しましょう。
　設定が終わったら、nghttpxを再起動します。

```
service nghttpx restart
```

　では、Chromeからnginxにアクセスしてみましょう。
　起動オプションは、--proxy-server=https://に変更します。

```
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --proxy-server=https://example.net:3127 --proxy-bypass-list=localhost;127.0.0.1;192.168.1.*
```

　Firefoxからnghttpxを利用する場合は、proxy.pacファイルを用意します。
　以下の内容で作成し、適当なサーバに配置後、ブラウザに設定します。

```
    function FindProxyForURL(url, host) {
        return "HTTPS example.net:3127";
    }
```

　うまくいったでしょうか。

　なお、Chromeがhttp/2通信しているか確認するには、拡張機能を利用するか、デバッグ用の画面を利用します。
　httpのサイトでも、ブラウザからProxyまではhttp/2で通信していることが確認できます。

　- [HTTP/2 and SPDY Indicator](https://chrome.google.com/webstore/detail/http2-and-spdy-indicator/mpbpobfflnpcgagjijhmgnchggcjblin) 
　- chrome://net-internals/#http2

```
Host	Proxy	ID	Negotiated Protocol	Active streams	Unclaimed pushed	Max	Initiated	Pushed	Pushed and claimed	Abandoned	Received frames	Secure	Sent settings	Received settings	Send window	Receive window	Unacked received data	Error
example.net:3127 	direct://	37	h2	4	0	100	27574	0	0	0	913769	null	null	null	36702	15728640	6739510	0
```

　ちなみに、iPhoneからssl proxyに接続できるか手動と自動の設定を試してみましたが、いまのところ未対応のようです。

# 3. TCP BBRをインストール

　TCP BBRはkernel 4.9以上でサポートされています。CUBICはloss-basedでパケットロスがあると帯域を半分に抑えるのに対し、BBRは速度と遅延をベースにしているため、パケットロスがある環境でもスループットの向上とレイテンシの低減が期待できるようです。
　- [輻輳制御の新アルゴリズム TCP BBR を GCP に導入](https://cloudplatform-jp.googleblog.com/2017/08/TCP-BBR-congestion-control-comes-to-GCP-your-Internet-just-got-faster.html)

　では、まずは現状の状態を確認します。

```bash
root@:~# uname -r
4.4.0-57-generic
root@:~# sysctl net.ipv4.tcp_available_congestion_control
net.ipv4.tcp_available_congestion_control = cubic reno
root@:~# sysctl net.ipv4.tcp_congestion_control
net.ipv4.tcp_congestion_control = cubic
root@:~# sysctl net.core.default_qdisc
net.core.default_qdisc = pfifo_fast
root@:~# lsmod | grep bbr
```

　bbrはkernel 4.9からサポートされるのに対し、現在使っているバージョンはkernel 4.4のため、まずはカーネルをアップデートする必要があります。最新カーネルとTCP BBRを簡単に導入するには、2つの方法があります。

1. シェルスクリプトを使う
 - [GoogleのTCP BBRでTCPを高速化しProxyもその恩恵にあずかる](https://qiita.com/fallout/items/92b2099ab5e16cfeb1f9)
 - [最新のカーネルをワンクリックでインストールし、BBRスクリプトを開く(中国語)](https://teddysun.com/489.html)
2. HWE (Hardware Enablement) カーネルを使う（Ubuntu 16.04以上限定）
 - [HWE (Hardware Enablement) カーネルを使う](https://www.talkwithdevices.com/archives/1240) 

　1番のシェルスクリプトは、最新のカーネルをインストールして、TCP BBRを設定するところまで自動で実施してくれます。CentOS 6+、Debian 7+ 、Ubuntu 12+をサポートしています。
　2番の方法は、Ubuntu公式の最新カーネルを導入後、手動でsysctl.confを編集してtcp bbrを有効化する必要があります。
　ここでは、1番のシェルスクリプトを使います。

```
wget https://github.com/teddysun/across/raw/master/bbr.sh && chmod +x bbr.sh && ./bbr.sh
```

　シェルスクリプトを実行してエンターを押すと、カーネルのダウンロードとインストールが実行されます。最後に [y] でリブートします。

```bash
root@:~# wget https://github.com/teddysun/across/raw/master/bbr.sh && chmod +x bbr.sh && ./bbr.sh

---------- System Information ----------
 OS      : Ubuntu 16.04.4 LTS
 Arch    : x86_64 (64 Bit)
 Kernel  : 4.4.0-57-generic
----------------------------------------
 Auto install latest kernel for TCP BBR

 URL: https://teddysun.com/489.html
----------------------------------------

Press any key to start...or Press Ctrl+C to cancel
--2018-04-08 00:30:26--  http://kernel.ubuntu.com/~kernel-ppa/mainline/v4.16/linux-image-4.16.0-041600-generic_4.16.0-041600.201804012230_amd64.deb
Resolving kernel.ubuntu.com (kernel.ubuntu.com)... 91.189.94.216
Connecting to kernel.ubuntu.com (kernel.ubuntu.com)|91.189.94.216|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 53088470 (51M) [application/x-debian-package]
Saving to: ‘linux-image-4.16-amd64.deb’

     0K .......... .......... .......... .......... ..........  0%  108K 8m0s
    50K .......... .......... .......... .......... ..........  0%  216K 6m0s
(略)
 51750K .......... .......... .......... .......... .......... 99% 35.6M 0s
 51800K .......... .......... .......... .......... ....      100% 38.6M=6.1s

2018-04-08 00:30:33 (8.34 MB/s) - ‘linux-image-4.16-amd64.deb’ saved [53088470/53088470]

Selecting previously unselected package linux-image-4.16.0-041600-generic.
(Reading database ... 126851 files and directories currently installed.)
Preparing to unpack linux-image-4.16-amd64.deb ...
Done.
Unpacking linux-image-4.16.0-041600-generic (4.16.0-041600.201804012230) ...
Setting up linux-image-4.16.0-041600-generic (4.16.0-041600.201804012230) ...
Running depmod.
update-initramfs: deferring update (hook will be called later)
Examining /etc/kernel/postinst.d.
run-parts: executing /etc/kernel/postinst.d/apt-auto-removal 4.16.0-041600-generic /boot/vmlinuz-4.16.0-041600-generic
run-parts: executing /etc/kernel/postinst.d/initramfs-tools 4.16.0-041600-generic /boot/vmlinuz-4.16.0-041600-generic
update-initramfs: Generating /boot/initrd.img-4.16.0-041600-generic
W: mdadm: /etc/mdadm/mdadm.conf defines no arrays.
run-parts: executing /etc/kernel/postinst.d/unattended-upgrades 4.16.0-041600-generic /boot/vmlinuz-4.16.0-041600-generic
run-parts: executing /etc/kernel/postinst.d/update-notifier 4.16.0-041600-generic /boot/vmlinuz-4.16.0-041600-generic
run-parts: executing /etc/kernel/postinst.d/x-grub-legacy-ec2 4.16.0-041600-generic /boot/vmlinuz-4.16.0-041600-generic
Searching for GRUB installation directory ... found: /boot/grub
Searching for default file ... found: /boot/grub/default
Testing for an existing GRUB menu.lst file ... found: /boot/grub/menu.lst
Searching for splash image ... none found, skipping ...
Found kernel: /boot/vmlinuz-4.4.0-119-generic
Found kernel: /boot/vmlinuz-4.4.0-57-generic
Found kernel: /boot/vmlinuz-4.4.0-31-generic
Found kernel: /boot/vmlinuz-4.16.0-041600-generic
Found kernel: /boot/vmlinuz-4.4.0-119-generic
Found kernel: /boot/vmlinuz-4.4.0-57-generic
Found kernel: /boot/vmlinuz-4.4.0-31-generic
Replacing config file /run/grub/menu.lst with new version
Updating /boot/grub/menu.lst ... done

run-parts: executing /etc/kernel/postinst.d/zz-update-grub 4.16.0-041600-generic /boot/vmlinuz-4.16.0-041600-generic
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.16.0-041600-generic
Found initrd image: /boot/initrd.img-4.16.0-041600-generic
Found linux image: /boot/vmlinuz-4.4.0-119-generic
Found initrd image: /boot/initrd.img-4.4.0-119-generic
Found linux image: /boot/vmlinuz-4.4.0-57-generic
Found initrd image: /boot/initrd.img-4.4.0-57-generic
Found linux image: /boot/vmlinuz-4.4.0-31-generic
Found initrd image: /boot/initrd.img-4.4.0-31-generic
done
removed 'linux-image-4.16-amd64.deb'
Generating grub configuration file ...
Found linux image: /boot/vmlinuz-4.16.0-041600-generic
Found initrd image: /boot/initrd.img-4.16.0-041600-generic
Found linux image: /boot/vmlinuz-4.4.0-119-generic
Found initrd image: /boot/initrd.img-4.4.0-119-generic
Found linux image: /boot/vmlinuz-4.4.0-57-generic
Found initrd image: /boot/initrd.img-4.4.0-57-generic
Found linux image: /boot/vmlinuz-4.4.0-31-generic
Found initrd image: /boot/initrd.img-4.4.0-31-generic
done

Info: The system needs to reboot.
Do you want to restart system? [y/n]
y
```

　再起動後、カーネルのバージョン、輻輳制御方式を確認します。

```bash
root@:~# uname -a
Linux 4.16.0-041600-generic #201804012230 SMP Sun Apr 1 22:31:39 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
root@:~# sysctl net.ipv4.tcp_available_congestion_control
net.ipv4.tcp_available_congestion_control = reno cubic bbr
root@:~# sysctl net.ipv4.tcp_congestion_control
net.ipv4.tcp_congestion_control = bbr
root@:~# sysctl net.core.default_qdisc
net.core.default_qdisc = fq
root@:~# lsmod | grep bbr
tcp_bbr                20480  4
```

　比較のために、bbrカーネル使用前後のspeedtestをしてみます。

- 使用前

```bash
root@:~# wget -O speedtest-cli https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py && chmod +x speedtest-cli && ./speedtest-cli 
--2018-04-08 00:52:53--  https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.72.133
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.72.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 59555 (58K) [text/plain]
Saving to: ‘speedtest-cli’

speedtest-cli                                  100%[====================================================================================================>]  58.16K  --.-KB/s    in 0.002s  

2018-04-08 00:52:53 (30.7 MB/s) - ‘speedtest-cli’ saved [59555/59555]

Retrieving speedtest.net configuration...
Testing from GMO Internet (163.44.169.216)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by IPA CyberLab (Bunkyo) [2.57 km]: 1.86 ms
Testing download speed................................................................................
Download: 125.73 Mbit/s
Testing upload speed................................................................................................
Upload: 135.56 Mbit/s
```

- 使用後

```bash
root@:~# ./speedtest-cli 
Retrieving speedtest.net configuration...
Testing from GMO Internet,Inc (150.95.146.127)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by IPA CyberLab (Bunkyo) [5.97 km]: 1.88 ms
Testing download speed................................................................................
Download: 125.40 Mbit/s
Testing upload speed................................................................................................
Upload: 101.06 Mbit/s
```

　使用後のほうが、VPSからスピードテストサーバまでのスループットは少し落ちてしまいました。これは、cubicがベルトコンベアにじゃんじゃんパケットを積み込むのに対して、bbrはrttが悪化しないよう様子を見ながら積み込むという特性があります。そのため、低遅延かつパケットロスのないネットワークでは、cubicよりも少し遅くなります。
  パケットロス環境下におけるcubicとbbrのスループットを比較したよい資料があります。下のスライドの13ページ目のグラフを参照してください。

https://www.janog.gr.jp/meeting/janog41/application/files/4615/1727/7615/janog41-sp09tcp-ishizaki-02.pdf

# 4. その他

　ここまでで、Secure Proxyを利用する準備ができました。ここからは、利用中に起こった問題と解決策を紹介します。

## 4-1. ChromeでWebSocketが利用できない

　ChromeでSecure Proxyを利用していると、WebSocketがうまく動きません。具体例としては、ニコニコ生放送のhtml 5対応ページで動画とコメントが再生されないません。ちなみにFirefoxではこの問題は起こりません。
　WebSocketの接続テストをできるページによると、SSL以外が失敗します。

- [The WebSockets test - 失敗](http://websocketstest.com/result/12450606)

```
Aggregated Test Results
WebSockets supported	Yes ✔
WebSocket protocol version	rfc-6455
HTTP Proxy	No
Browser	chrome 66.0.3359.81
Antivirus	No Data
WebSockets (Port 80)	No ✘
WebSockets (Port 443)	No ✘
WebSockets (Port 8080)	No ✘
WebSockets (Port 443, SSL)	Yes ✔
```

　この問題を回避するには、WebSocketとの通信のみProxyを経由せず直接接続すればよいです。Chromeの起動オプションのバイパスリストにWebSocketを加えましょう。

```
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --proxy-server=https://example.net:3127 --proxy-bypass-list=localhost;127.0.0.1;192.168.1.*;ws://*
```

　これで、先ほどのテストを実施すると、全て成功します。

- [The WebSockets test - 成功](http://websocketstest.com/result/12450606)

```
Aggregated Test Results
WebSockets supported	Yes ✔
WebSocket protocol version	rfc-6455
HTTP Proxy	No
Browser	chrome 66.0.3359.81
Antivirus	No Data
WebSockets (Port 80)	Yes ✔
WebSockets (Port 443)	Yes ✔
WebSockets (Port 8080)	Yes ✔
WebSockets (Port 443, SSL)	Yes ✔
```

　その他、VPSからのアクセスを許容しないサイトに遭遇したら、バイパスリストに加えればよいでしょう。

## 4-2. 輻輳時に通信が停止する問題

　自分の環境からAbemaTVなどを閲覧していると、しばしば止まることがあります。タスクマネージャのイーサネットのスループットグラフや連続Pingから想定すると、ネットワークが輻輳すると、途中のNWで一時的に転送を抑止しているように見えていました。
　このことから、自分のインターネットアクセス環境の最大ネットワーク速度で通信速度を抑えればいいと仮定しました。レオネットのカタログスペックは100Mbps、Chonoha VPSも100Mbpsですが、正確なところはどうでしょうか。
　まずは、レオネットのMTUを測定してみました。結果は、1426でした。

```
PS > ping 1.1.1.1 -f -l 1426

1.1.1.1 に ping を送信しています 1426 バイトのデータ:
1.1.1.1 からの応答: バイト数 =1426 時間 =16ms TTL=52
1.1.1.1 からの応答: バイト数 =1426 時間 =18ms TTL=52

1.1.1.1 の ping 統計:
    パケット数: 送信 = 2、受信 = 2、損失 = 0 (0% の損失)、
ラウンド トリップの概算時間 (ミリ秒):
    最小 = 16ms、最大 = 18ms、平均 = 17ms

PS > ping 1.1.1.1 -f -l 1428

1.1.1.1 に ping を送信しています 1428 バイトのデータ:
10.55.215.1 からの応答: パケットの断片化が必要ですが、DF が設定されています。
パケットの断片化が必要ですが、DF が設定されています。

1.1.1.1 の ping 統計:
    パケット数: 送信 = 2、受信 = 1、損失 = 1 (50% の損失)、
```

　MTUは、自宅環境のほうがEthernet標準の1500より小さいことがわかりました。このことから、VPSから自宅のPCにデータを送信するとき、VPSから送信する速度が早すぎて、途中のNWでキューが一杯になって輻輳していると想定しました。
　適切な通信帯域は、以下のように計算しました。

```
　100Mbps / 8bit / 1500byte * 1426byte * 8bit = 95.06Mbps
```

　これを、VPSに設定します。

```
tc qdisc add dev ens3 root handle 1: htb default 0
tc class add dev ens3 parent 1:0 classid 1:0 htb rate 95Mbit
```

　なお、削除するには、以下のコマンドを実行します。

```
tc qdisc del dev ens3 root
```

　起動時に実行するには、rc.localに設定します。

```bash
vi /etc/rc.local 
#!/bin/sh -e
#
# rc.local
#
# This script is executed at the end of each multiuser runlevel.
# Make sure that the script will "exit 0" on success or any other
# value on error.
#
# In order to enable or disable this script just change the execution
# bits.
#
# By default this script does nothing.

tc qdisc add dev ens3 root handle 1: htb default 0
tc class add dev ens3 parent 1:0 classid 1:0 htb rate 95Mbit

exit 0
```

　うまく帯域制御できているか確認します。

　tc実行前と実行後をスピードテストスクリプトで比較します。

- tc実行前

```
root@:~# ./speedtest-cli 
--2018-04-08 03:38:35--  https://raw.githubusercontent.com/sivel/speedtest-cli/master/speedtest.py
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 151.101.72.133
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|151.101.72.133|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 59555 (58K) [text/plain]
Saving to: ‘speedtest-cli’

speedtest-cli                                  100%[====================================================================================================>]  58.16K  --.-KB/s    in 0.002s  

2018-04-08 03:38:36 (25.4 MB/s) - ‘speedtest-cli’ saved [59555/59555]

Retrieving speedtest.net configuration...
Testing from GMO Internet,Inc (150.95.191.105)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by OPEN Project (via 20G SINET) (Tokyo) [0.16 km]: 1.725 ms
Testing download speed................................................................................
Download: 126.08 Mbit/s
Testing upload speed................................................................................................
Upload: 135.56 Mbit/s
```

- tc実行後

```
root@:~# ./speedtest-cli 
Retrieving speedtest.net configuration...
Testing from GMO Internet,Inc (150.95.191.105)...
Retrieving speedtest.net server list...
Selecting best server based on ping...
Hosted by OPEN Project (via 20G SINET) (Tokyo) [0.16 km]: 1.624 ms
Testing download speed................................................................................
Download: 117.34 Mbit/s
Testing upload speed................................................................................................
Upload: 91.64 Mbit/s
```

　帯域制御がUpload側、Proxyから自宅への送信方向にうまく効いていることが確認できました。

  しかし、この計算と対処が適切かどうかは、全く自信がありません...

　（2018.11.08追記）
　どうやら自宅のレオネットでは、UDP通信が大量に発生した場合に通信を一時的に停止する動作のようです。そのため、使用しているChromeからQUICをdisabledに設定することで、通信が一時停止する事象はなくなりました。
　よって、筆者は現在この設定は使用していません。

## 4-3. iPhoneからProxy例外設定

　一部のサイトはProxy経由のアクセスを許可していません。
　プロキシ自動構成(.pac)ファイルを準備して、該当のサイトを回避しましょう。
　ただし、この方法はWi-Fi経由での接続時しか利用できません。

``` proxy.pac
function FindProxyForURL(url, host) {

  // If the hostname matches, send direct.
  if (host == "abematv.akamaized.net") return "DIRECT";
 
 return "PROXY example.net:8387";
}
```
　こちらのファイルをhttpアクセスが可能なWebサーバに配置し、iPhoneの設定 - Wi-Fi - HTTPプロキシを構成から「自動」を選択し、URLに.pacファイルを配置したアドレスを入力すればOKです。

- [iPhoneでプロキシサーバーの例外設定をする](https://qiita.com/y_koh/items/91b3765778022338c0b8)

# 帯域テスト

　fast.comでPCから帯域テストしました。

- 設定なし

　38Mbps

- Squid

　80Mbps

- TCP BBR + Squid

　86Mbps

- TCP BBR + Squid + nghttpx

　83Mbps

- tc + TCP BBR + Squid + nghttpx

　81Mbps

　平日12時台にMVNOの4G回線からiPhoneのSpeedtestアプリでテストしました。

- 設定なし

　1Mbps

- TCP BBR + Squid

　2Mbps

  同じく平日12時台に、MVNOの4G回線から、fast.comで測定しました。

- 設定なし

  250kbps

- TCP BBR + Squid

  6.9Mbps

  30倍近く速くなりました。

# まとめ

  パケットロスや遅延があるアクセス回線、混雑時の4G回線に対して、TCP BBRを有効にしたProxyサーバを利用すると、3倍から30倍もスループットが改善されました。

  特に、平日昼間のスマホが劇的に快適になり、自宅の固定回線で夜に動画を見てもバッファがなくなりストレスがなくなりました。

  bbrの効果を肌で感じるには、カナダの某買い切りVPSをお持ちの方は、そこでbbrを試すとよいです。コンソールがぬるりと動きますよ。

# ANAの機内から試す(2019.5.12追記)

  ANAの機内から、インターネットにもつながる無料Wi-Fiサービスが利用できたので、効果を試してみました。

・8.8.8.8へのpingは、遅延が大体550 - 750ms、パケロスは4%くらいです。
・測定サイトは、traceroute6.net ( fast.com は測定が始まらず)

## 使用前(proxy設定なし)

703.9 kbps / 755.53 kbps

## 使用後(proxy設定あり)

2.66 mbps / 31.4 mbps

4倍近く速くなりました！