Slack製VPNのNebulaをOpenVPNと速度比較をしてみた

# Nebulaとは

Slackが公開したパフォーマンス重視のスケーラブルなオーバーレイネットワークツールです．

> Nebula is a scalable overlay networking tool with a focus on performance, simplicity and security. It lets you seamlessly connect computers anywhere in the world. Nebula is portable, and runs on Linux, OSX, and Windows. (Also: keep this quiet, but we have an early prototype running on iOS). It can be used to connect a small number of computers, but is also able to connect tens of thousands of computers. 
引用: https://slack.engineering/introducing-nebula-the-open-source-global-overlay-network-from-slack-884110a5579

参考：[Slackの「Nebula」--オープンソースのオーバーレイネットワークツール - TechRepublic Japan](https://japan.techrepublic.com/article/35146749.htm)

# 動作検証

## 環境

Google Compute Engineでf1-micro(vCPU x 1, メモリ 0.6 GB, HDD 30GB)を使って検証しました．

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103672/2553ac32-343a-b9d3-2f4a-6249d9fd7ad3.png)

クライアントとサーバーともにUbuntu 18.04です．

## 構築

### ダウンロード

以下のURLからプラットフォームごとに適したパッケージをダウンロードします．
https://github.com/slackhq/nebula/releases

```bash
$ wget https://github.com/slackhq/nebula/releases/download/v1.1.0/nebula-linux-amd64.tar.gz
```

### マシンの準備

ルーティング可能な固定IPアドレスをもつ1台のディスカバリノードを用意します．このノードはlighthouse(灯台)とよぶそうです．

今回はGCEのインスタンスを使用します．nebulaで使用するデフォルトポート`udp/4242`をVPCネットワークのファイアウォール ルールを作成して開放します．
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103672/7541ab74-1e32-eaee-5221-85ea501e4a98.png)

### マシンで作業

ダウンロードしたパッケージを展開します．

```shell
$ tar -xvf nebula-linux-amd64.tar.gz

$ ls -F
nebula*  nebula-cert*  nebula-linux-amd64.tar.gz
```

Nebula認証局を作成します．カレントディレクトリに `ca.key` と `ca.cert` が作成されます．`ca.key` は個々のノード，ホストの証明書へ署名するために使われるので厳重に取り扱います．安全な強固な暗号化されたストレージへの保管がオススメだそうです．

```shell
$ ./nebula-cert ca -name "Cloud and Distributed Systems Laboratory"

$ ls -F
ca.crt  ca.key  nebula*  nebula-cert*  nebula-linux-amd64.tar.gz
```

Nebulaのホスト鍵と証明書を前述の認証局から生成します．ノードに名前付けができます．IPアドレスと所属するサブネットの指定ができます．今回はサンプルとして `192.168.30.x/24` をNabulaのネットワーク範囲として指定します．

```shell
$ ./nebula-cert sign -name "lighthouse1" -ip "192.168.30.1/24"
$ ./nebula-cert sign -name "mylaptop" -ip "192.168.30.3/24"

$ ls -F
ca.crt  ca.key  mylaptop.crt  mylaptop.key  nebula*  nebula-cert*  nebula-linux-amd64.tar.gz
```

ホスト毎の設定ファイルを作成します．以下のリンクから設定例をダウンロードします．lighthouseノードは `am_lighthouse: true` を設定します．それ以外のノードは`static_host_map`に `lighthouse` を追加します．また，個々のノードをlighthouseノードの `hosts` セクションに記述します．

[nebula/config.yml at master · slackhq/nebula](https://github.com/slackhq/nebula/blob/master/examples/config.yml)

```shell
$ wget https://raw.githubusercontent.com/slackhq/nebula/master/examples/config.yml
```

Nebulaのクレデンシャルと設定，バイナリを各ホストにコピーします．**ただし，`ca.key` は絶対にコピーしないでください．**

- config.yaml
- ca.crt
- {ホスト名}.crt
- {ホスト名}.key

設定ファイルをlighthouseノードとクライアント(mylaptop)のそれぞれで編集します．`pki:`の`cert`と`key`は個別に編集してください．`lighthouse:`の`hosts`をlighthouseノード側には記述しないでください．

```yaml:設定例(mylaptop)
pki:
  ca: ./ca.crt
  cert: ./mylaptop.crt
  key: ./mylaptop.key
static_host_map:
  "192.168.30.1": ["35.199.175.192:4242"]
lighthouse:
  am_lighthouse: false
  interval: 60
  hosts:
    - "192.168.30.1"
punchy: true
tun:
  dev: nebula1
  drop_local_broadcast: false
  drop_multicast: false
  tx_queue: 500
  mtu: 1300
  routes:
  unsafe_routes:
logging:
  level: info
  format: text
firewall:
  conntrack:
    tcp_timeout: 120h
    udp_timeout: 3m
    default_timeout: 10m
    max_connections: 100000
  outbound:
    - port: any
      proto: any
      host: any
```

```yaml:設定例(lighthouse)
pki:
  ca: /opt/nebula/ca.crt
  cert: /opt/nebula/lighthouse1.crt
  key: /opt/nebula/lighthouse1.key
static_host_map:
  "192.168.30.1": ["35.199.175.192:4242"]
lighthouse:
  am_lighthouse: true
  interval: 60
listen:
  host: 0.0.0.0
  port: 4242
punchy: true
tun:
  dev: nebula1
  drop_local_broadcast: false
  drop_multicast: false
  tx_queue: 500
  mtu: 1300
  routes:
  unsafe_routes:
logging:
  level: info
  format: text
firewall:
  conntrack:
    tcp_timeout: 120h
    udp_timeout: 3m
    default_timeout: 10m
    max_connections: 100000
  outbound:
    - port: any
      proto: any
      host: any
  inbound:
    - port: any
      proto: icmp
      host: any
    - port: 443
      proto: tcp
      host:
        - mylaptop
    - port: any
      proto: udp
      host: any
```

Nebulaを各ホストで実行します．

```shell
$ ./nebula -config /path/to/config.yaml
```

接続する様子：
[![youtube](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103672/71cbd4eb-c406-772a-66b1-6d2cc7a5d86c.png)](https://youtu.be/iTih485_Nq4)

## 速度測定

### 環境・方法

laptop→インターネット
![_IFgG1Sa.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103672/183e45d2-c223-6496-6ee3-9de24ad12a1b.png)

ツールにはiperfを使用しました．

```
$ iperf  -v
iperf version 2.0.10 (2 June 2018) pthreads
```

lighthouse側(GCP)は以下の記事をもとにiperfコマンドを実行しました．
[ネットワーク測定ツールiperfの使い方 - Qiita](https://qiita.com/takish/items/bff7a1df712d475432df)

```
iperf -s -u -i 1
```

クライアント側(mylaptop)は以下のiperfコマンドを実行しました．以下は`192.168.30.1`宛に`30`秒間，`2`秒おきに`500Mb`を送信する場合のコマンドです．

```
iperf -c 192.168.30.1 -u -b 500M -t 30 -i 2
```

測定する様子：
[![youtube](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/103672/71cbd4eb-c406-772a-66b1-6d2cc7a5d86c.png)](https://youtu.be/LYCPZM9aLoE)

### 結果

||nebula|openvpn|
|---|---|---|
|400M|417 Mbps|418 Mbps|
|500M|509 Mbps|523 Mbps|
|600M|561 Mbps||
|700M|516 Mbps||

### 付録

サーバ側

```
$ iperf -s -u -i 1
```