GFWを完全にバイパス

この記事は 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 フレームワークを使って、OpenVPNCisco VPN などの VPN プロトコルのパケットを監視・検知できる。したがって、

    • より複雑な VPN 環境を設定しなければならない。IKEv2 という秘密対称鍵を管理するプロトコルを使用すれば、監視されているかもしれない通信路を暗号化することができる。詳しい IPsec と StrongSwan IKEv2 の設定に関してはこちらを参照。

今回使うツール: Shadowsocks + KCP

Shadowsocks とは

ShadowsocksSOCKS 5 プロキシに基づくアプリケーション層プロトコルだ。中国政府の圧力によって、以前の repo は保守することができなくなった。今回使うバージョンは shadowsocks-libev だ。

主流のブラウザが DNS リモート引き出し機能をサポートするため、 SOCKS5 プロキシまで有効な DNS ポイズニングを防止ことができる。

機能

  • 多端末対応 (Linux, mac OS, Windows, iOS, Android)
  • TCP & UDP の両方ともをサポート
  • TCP Fast Open
  • 多様な暗号化アルゴリズムを提供(AES、RC4-MD5、Salsa20、Chacha20など)

KCP および kcptun とは

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 に対応するクライアントはこちらでダウンロードできる。

mac OS の場合には、

mac

例のパスワード: 123456

を設定したら完了。

GitHub から私の repo をダウンロードしたら、Dockerfile にあるパスワードを修正できる。

WIP

Reference

Show Comments