gost - GO Simple Tunnel がすごい

# gostってなに？
- goで書かれた多機能プロトコル変換中継simple tunnelソフトウェア
- 一言で言うと、stoneの多機能プロトコル版
- squidとかみたいにconfigはいらず、コマンドラインで完結できるシンプル設計
- WindowsとLinuxに対応
- goで書かれているので公式サイトのバイナリを落としてすぐ使える
- 公式github: https://github.com/ginuerzh/gost/blob/master/README_en.md
- 公式wiki: https://docs.ginuerzh.xyz/gost/en/

# gostでできること
- 指定したIPアドレス、ポート番号、プロトコル、トランスポートで接続を受付および中継する
- 多彩なプロトコル、トランスポートを選べる。プロトコルはたとえばプロキシサーバとして機能し、トランスポートはgost同士のデータ転送に使用できる。
- 普通に使うならhttp、安定性なら(?)socks5、匿名性ならss、新しもの好きならquic
- gost同士で中継する場合は、プロトコルとトランスポートを'+'でつなぐことで、任意のプロトコルを任意のトランスポートでカプセル化指定することができる（一部の組み合わせのみ）　https://docs.ginuerzh.xyz/gost/en/configuration/

# 対応プロトコル（アプリケーションプロトコル）
- http
- http/2
- socks5
- ss (shadow socks)
- etc...

# 対応トランスポート（トランスポートプロトコル）
- tcp
- tls
- kcp #udp
- quic #udp
- h2
- etc...

# 使い方

```bash:./gost
  -C string
        configure file
  -D    enable debug log
  -F value
        forward address, can make a forward chain
  -L value
        listen address, can listen on multiple ports
  -V    print version
  -obfs4-distBias
        Enable obfs4 using ScrambleSuit style table generation
```

`gost -L=http://:8080 -D`
localhostでport:8080にてhttp proxy接続を受付し、デバッグログを出力

`gost -L=http://:8080 -L=socks5://:8081 -F=h2://relay.net:9000`
localhostでport:8080でhttp proxyとport:8081でsocks5 proxy接続を受付し、h2トランスポートでrelay.net:9000へ中継

`gost -L http+tls://:443 -F socks5+wss://:1443`
プロトコルとトランスポートを組み合わせる

`nohup nice -n -10 ./gost -L="http2://:8386?cert=/etc/letsencrypt/live/relay.net-0001/cert.pem&key=/etc/letsencrypt/live/relay.net-0001/privkey.pem" -L=socks5://:8387 -D &`
nohupでログアウトしても稼働するようにして、nice値を上げてgost起動、http2プロトコルでport:8386で接続受付し証明書と秘密鍵を指定、socks5でport:8387にて接続を受付

`./gost -L=ss://chacha20:hoge1234@:8386 -D`
shadowsocksで接続受付

# 構成例
- browser[http]---[http]gost---(internet)
- browser[http2]---(internet)---[http2]gost---(internet)
- browser[socks5]---[socks5]gost[h2]---(internet)---[h2]gost[http]---[http]squid---(internet)


# ブラウザから接続するときの設定方法

## chrome

```conf:http_proxy
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --proxy-server=relay.net:3128 --proxy-bypass-list=<local>;192*
```

```conf:socks5_proxy
`"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --proxy-server=socks5://relay.net:8387 --proxy-bypass-list=<local>;192*
```

```conf:http2_proxy
` "C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --proxy-server=https://relay.net:8386 --proxy-bypass-list=<local>;192*;ws://*;150*;*163*
```

## firefox

```conf:http_proxy
オプション　→　ネットワーク設定の詳細設定　→　HTTPプロキシ
```

```conf:socks5_proxy
// proxy.pacを用意する
function FindProxyForURL(url, host)
  {
  return "SOCKS5 relay.net:8387";
  }
```

```conf:http2_proxy
// proxy.pacを用意する
function FindProxyForURL(url, host)
  {
  return "HTTPS relay.net:8386";
  }
```

## iPhone (safari)

```conf:socks5_proxy
// proxy.pacを用意する
function FindProxyForURL(url, host)
  {
  return "SOCKS relay.net:8387";
  }
```



# Wiresharkで見てみる

本当に指定したプロトコルが使われているのか見てみる。

## キャプチャ環境

- VPS(remote)上でhttp2とsocks5を待ち受けポートに設定してgostを起動
`nohup nice -n -10 ./gost -L="http2://:8386?cert=/etc/letsencrypt/live/relay.net-0001/cert.pem&key=/etc/letsencrypt/live/relay.net-0001/privkey.pem" -L=socks5://:8387 -D &`

- クライアント(local)はChromeの起動オプションでプロキシ設定して以下のサイトを開いたときのパケットをキャプチャ
  http://www.umin.ac.jp/http-man/http1.0jp.txt

## キャプチャ結果のスクリーンショット

### socks5
<img width="1768" alt="socks.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/163842/abd6c6e2-2925-795d-0631-199a93ac6d01.png">
<img width="442" alt="socks2.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/163842/0d8c4234-a4ec-2d84-235c-35b3ad99e8cd.png">

Socks5の認証ネゴシエーションして、平文でGETリクエストしている。

### http/2
<img width="1402" alt="http2.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/163842/f69558a3-d364-c379-9ef8-1e62609562b0.png">

TLSv1.2でハンドシェイクして、暗号化したデータをやり取りしている。


# いろんなプロトコルを使って転送速度を比較してみる

スピードテストでプロトコルごとの特性を比較してみる。

## 測定環境
- Google Chrome 64bit version 71.0.3578.44
- Windows 10 Pro version 1809 64bit
- 土曜夜19時台100Mフレッツ固定回線
- 測定サイトは　https://fast.com

結論から言うと、なんとSocks5が速度、安定性(bufferbloat)ともに一番バランスがよく優秀な結果になった。
暗号化処理などしていないため当然かもしれない。


## 素（プロキシ設定なし）

24 Mbps
レイテンシ
アンロード済み　18 ms
ロード済み　26 ms
アップロード　78 Mbps
<img width="500" alt="su_.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/163842/2c343ba2-b22d-d888-bd87-c81b7d64ad3c.png">


## socks5 on conoha vps

```conf:browser_chrome
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --proxy-server=relay.net:8187 --proxy-bypass-list=<local>;192*
```
```bash:server
nohup nice -n -10 ./gost -L=socks5://:8387 -D
```

87 Mbps
レイテンシ
アンロード済み　20 ms
ロード済み　33 ms
アップロード　71 Mbps
<img width="500" alt="socks5_.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/163842/95fbcb8f-06d9-7c51-8468-688245cf8f66.png">


## http/2 on conoha vps

```conf:browser_chrome
"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe" --proxy-server=https://relay.net:8387 --proxy-bypass-list=<local>;192*
```

```bash:server
nohup nice -n -10 ./gost -L="http2://:8386?cert=/etc/letsencrypt/live/relay.net-0001/cert.pem&key=/etc/letsencrypt/live/relay.net-0001/privkey.pem" -D
```

84Mbps
レイテンシ
アンロード済み　20 ms
ロード済み　210 ms
アップロード　38 Mbps
<img width="500" alt="http2_.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/163842/db82ea25-3037-5d9a-ef28-fa50d4a726bc.png">


## squid on vps　（参考）

89 Mbps
レイテンシ
アンロード済み　21 ms
ロード済み　32 ms
アップロード　77 Mbps
<img width="500" alt="squid_.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/163842/b9c7fd54-54d0-f1af-fadb-dc64a7cbb954.png">


# 追試

クライアントとサーバ間のgostをいろんなトランスポートでつなぐ追試をしてみる。

## h2 (http/2)

- レイテンシの幅がやや大きめ。
- パケットはTLSv1.2で暗号化されている。

```bash:client
gost -L=socks5://:8080 -F=h2://relay.net:8386 -D
```

```bash:server
nohup nice -n 10 ./gost -L=h2://:8386 -D
```

74 Mbps
レイテンシ
アンロード済み 21 ms
ロード済み 270 ms
アップロードスピード 67 Mbps

<img width="964" alt="h2.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/163842/2328d312-c902-b022-619c-f2e14d5ead82.png">
<img width="500" alt="h2_.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/163842/a5b51e21-79ce-c74d-26a8-6aa8d7593627.png">


## KCP

- UDPベースのスループットを犠牲にして低遅延を試みるプロトコル (A Fast and Reliable ARQ Protocol)
- だが、デフォルト設定のためか遅延は普通より大きめ
- アップロードが100Mbps回線なのに130Mbpsとかいっちゃってて怒られるやつ
- https://github.com/skywind3000/kcp/blob/master/README.en.md

```bash:client
gost -L=socks5://:8080 -F=kcp://relay.net:8386 -D
```

```bash:server
nohup nice -n 10 ./gost -L=kcp://:8386 -D
```

55 Mbps
レイテンシ
アンロード済み 20 ms
ロード済み 92 ms
アップロードスピード 56 Mbps

<img width="964" alt="kcp.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/163842/f5b46e6f-e81c-0f26-8d5f-a5e67ac6eca7.png">
<img width="500" alt="kcp_.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/163842/018444e6-b69e-5421-8742-24b673c008c6.png">


## QUIC

- UDPベースのTCP+TLS+http2の機能を含む次世代プロトコル (Quick UDP Internet Connections) 
- レイテンシ、スループットともに優秀（アップロードが振り切れているが。。。）
- https://www.chromium.org/quic

```bash:client
gost -L=socks5://:8080 -F=quic://relay.net:8386 -D
```

```bash:server
nohup nice -n 10 ./gost -L=quic://:8386 -D
```

79 Mbps
レイテンシ
アンロード済み 20 ms
ロード済み 35 ms
アップロードスピード 120 Mbps

<img width="964" alt="quic.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/163842/2ea6e0d7-e607-c72f-51d3-dbfabf7d4a04.png">
<img width="500" alt="quic_.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/163842/696bbf5d-289f-d3d7-cfc8-a401ce244a39.png">


## Shadowsocks

- 金盾超えに使われているらしいSecureなSocks5プロトコル
- 暗号化されているのにレイテンシもスループットも素のSocks5と変わらずすごい
- https://shadowsocks.org/en/index.html

```bash:client
gost -L=socks5://:8080 -F=ss://chacha20:hoge1234@relay.net:8386 -D
```

```bash:server
nohup nice -n 10 ./gost -L=ss://chacha20:hoge1234@:8386 -D
```

88 Mbps
レイテンシ
アンロード済み 21 ms
ロード済み 39 ms
アップロードスピード 72 Mbps

<img width="964" alt="ss.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/163842/0dbc6a4e-7e5d-ffe3-5d2b-a115dab410e2.png">
<img width="500" alt="ss_.PNG" src="https://qiita-image-store.s3.amazonaws.com/0/163842/b2855491-1bc9-2eb7-3409-ef762ade850b.png">


# そのためも
- chromeはhttp/2 proxyにするとWebSocket(ws://*)が死ぬ、一部サイト(sekai-kabuka.com)のグラフの中身が出ない　→　起動オプション　--proxy-bypass-list=ws://*;http://1*　で対応
- firefoxはhttp2 proxyにすると安定性がいまいち（スループットが上下運動する）
- ネット上に設置するときは、誰かに勝手に使われないように注意する（iptablesでアドレス制御するとか、squidに落として認証するなど）
- プロセスの優先度を上げると少しスループットが上がる
- chromeで使うならhttp/2 Proxy Modeがおすすめ（サイトをクリックしてから表示されるまでの体感が早く感じた） https://docs.ginuerzh.xyz/gost/en/http2/

# まとめ
gostすごい（面白い）