この記事は SFC-RG Advent Calendar 2017 の18日目の記事です。
今回の目標
Conoha の VPS を簡単に設定し、中国の GFW (Great Firewall) を避けることができる。
VPN を使わない理由
中国の App Store ではほとんどの VPN アプリがブロックされた。2017年1月以降、中国企業が VPN を扱う場合には政府のよる認可が必須となっている。そのため、アップルのオフィシャルアナウンスに基づいて、同年11月、アップルは中国政府と合意し、App Store にある600以上の VPN アプリを削除した。
HTTPS のトラフィックの場合には, SSL のパケットが VPN のコンテナに内包されていたとしても、GFW の DPI システムは簡単に主流の VPN のトラフィックを検知し、ドロップできる。既存の OSS を例にすれば、nDPI という DPI フレームワークを使って、OpenVPN や Cisco VPN などの VPN プロトコルのパケットを監視・検知できる。したがって、
今回使うツール: Shadowsocks + KCP
Shadowsocks とは
Shadowsocks は SOCKS 5 プロキシに基づくアプリケーション層プロトコルだ。中国政府の圧力によって、以前の repo は保守することができなくなった。今回使うバージョンは shadowsocks-libev だ。
主流のブラウザが DNS リモート引き出し機能をサポートするため、 SOCKS5 プロキシまで有効な DNS ポイズニングを防止ことができる。
機能
- 多端末対応 (Linux, macOS, Windows, iOS, Android)
- TCP & UDP の両方ともをサポート
- TCP Fast Open
- 多様な暗号化アルゴリズムを提供(AES、RC4-MD5、Salsa20、Chacha20など)
KCP および kcptun とは
KCP は @skywind3000 氏作った信頼できるトランスポート層 ARQ プロトコルだ。TCPと比べ、KCPは 10%-20% のバンド幅を浪費する代わりに、平均レイテンシは 30%-40% も下がる。
GFW は DPI 技術を取り扱っているため、中国から海外へのアウトバウンドトラフィックのパケットロス率が極めて高い。TCP の特性がパケットロス率が高い環境にあれば、ストリーミングは当然遅くなる。KCP が上述した問題を解決することを目指している。
KCPの特徴
- TCP の再送タイムアウト(RTO)は最大限の制限を達する前にほとんど倍増している。一方、KCP は RTT を *1.5 に変更した。実験により、この数値は速さと安定性のトレードオフを成し遂げると言うことができる。TCP の RTO については rfc6298 を参照。
(2.2) When the first RTT measurement R is made, the host MUST set
SRTT <- R
RTTVAR <- R/2
RTO <- SRTT + max (G, K*RTTVAR)
where K = 4.
選択的な再送
TCPでパケット損失が発生すると、すべてのデータが再送信される一方、KCPは選択的な再送信を行い、実際に失われたデータパケットのみが再転送される。
上述以外の特徴はこちら。
しかし、KCP そのものには暗号化・データ圧縮の機能がない。したがって、kcptun は KCP の上に、Google の snappy 圧縮ライブラリ 圧縮ライブラリに従い、ストリーム圧縮の機能を加えた。
設定の流れ
ホストサーバー (VPS)
作業環境
- Ubuntu 16.04 Linux kernel version 4.4.0
- Docker 17.09.0 CE
$ docker pull kakugirai/sskcp
# ポートフォワーディング
$ docker run -d -p 8000:8000 -p 8000:8000/udp -p 9000:9000/udp kakugirai/sskcp
Dockerfile の中身
テストの結果により、以下の数値を設定することで、よりパフォーマンスできる。
# Shadowsocks の設置
ENV SS_PORT 8000 # コンテナを listen しているポート
ENV SS_LOCAL_PORT 1080 # クライアントを listen しているポート
ENV SS_PASSWORD 123456 # パスワード
ENV SS_METHOD chacha20 # 暗号化アルゴリズム
ENV SS_TIMEOUT 600 # default timeout
ENV SS_SERVER 0.0.0.0 # Docker コンテナの IP
# KCPTUN の設置
ENV KCP_PORT 9000 # コンテナを listen しているポート
ENV KCP_MODE fast # fast3, fast2, fast, normal (default: "fast")
ENV KCP_MTU 1350 # maximum transmission unit
ENV KCP_SNDWND 1024 # send window size
ENV KCP_RCVWND 1024 # receive window size
ENV KCP_DATASHARD 10 # reed-solomon erasure coding - datashard
ENV KCP_PARITYSHARD 0 # reed-solomon erasure coding - parityshard
クライアント
Shadowsocks に対応するクライアントはこちらでダウンロードできる。
macOS の場合には、
例のパスワード: 123456
を設定したら完了。
GitHub から私の repo をダウンロードしたら、Dockerfile にあるパスワードを修正できる。
WIP
- TCP の 部分は Google BBR Congestion Control Algorithm を使ってみる。
Reference
- TCP BBR congestion control comes to GCP – your Internet just got faster
- Shadowsocks Over KCP
- QUIC
- Benchmark of UDP reliable frameworks
- Route-based IPsec VPN on Linux with strongSwan