ngrokを使ってローカル環境上で実行するWebアプリケーションにインターネットからアクセスする

# 概要

[ngrok (エングロック)] (https://ngrok.com/)は、ローカル環境上で実行しているアプリケーション(http/https/tcp)をインターネットからアクセスできるようにするサービスです。
特にスマホなどの実機で動作確認をしたい場合に便利です。
Free Planと有償プラン(Basic,Pro,Business、月額課金)があります。

ngrokの発音は[FAQ] (https://ngrok.com/faq)に書かれています。

> How do I pronounce ngrok?
> 
> en-grok

**環境**

* Windows10 Professional
* ngrok 2.1.18 (Free Plan)


**参考**

* [ngrok - Docs] (https://ngrok.com/docs)
* [ngrokトンネルのリージョンを選択する] (http://dev.classmethod.jp/tool/ngrok-regions/)


# インストールと設定

## アーカイブファイルをダウンロードする

https://ngrok.com/download よりアーカイブファイルをダウンロードします。
インストールは不要で、アーカイブファイルを適当な場所へ展開するだけで済みます。
展開するとWindows版の場合はngrok.exeという実行ファイルが手に入ります。

## 動作確認

動作確認としてversionコマンドでバージョンを表示してみます。

```bat:version
> ngrok.exe version
ngrok version 2.1.18
```

## サインアップとAuthtokenの取得

Authtokenはngrokのサイトでサインアップすると発行されます。
（Authtokenを取得（サインアップ）しなくてもngrokを使用することはできます。）

### dashboard

サインアップするとAuthtokenの発行と共にdashboardが使えるようになります。

![ngrok_dashboard.png](https://qiita-image-store.s3.amazonaws.com/0/22772/525e3fd9-7bdc-5740-0ae3-1e4d15e1a288.png)

**Statusタブ**

![ngrok_status.png](https://qiita-image-store.s3.amazonaws.com/0/22772/6f98c89a-bb9d-8b44-4caf-287599a3fbc4.png)

**Reservedタブ**

有償プランを利用するとドメインをカスタマイズすることができるようになるようです。（未確認です。）

![ngrok_reserved.png](https://qiita-image-store.s3.amazonaws.com/0/22772/e67fa534-8a5f-b898-26c6-80c2ed854850.png)


### Authtokenの登録

発行されたAuthtokenは下記のauthtokenコマンドで登録します。
Authtokenはngrokのサイトから再発行することができます。

```bat:authtoken
> ngrok.exe authtoken <Authtoken>
Authtoken saved to configuration file: C:\Users\Username\.ngrok2\ngrok.yml
```

登録したAuthtokenはngrok.ymlという設定ファイルに書き込まれます。
下記は自動生成された初期のngrok.ymlの内容です。

```yaml:ngrok.yml
authtoken: <Authtoken>
json_resolver_url: ""
dns_resolver_ips: []
```


# 実行

## 簡単な使い方

例えばローカル環境上(localhost)のポート9000番でWebアプリケーションが動作している場合、下記のコマンドを実行すると、ngrokが提供するURL(http(s))を通してローカル上のWebアプリケーションにアクセスすることができます。
ngrokを停止するにはコンソール上で<kbd><kbd>Ctrl</kbd> + <kbd>C</kbd></kbd>を押します。


```bat:http
> ngrok.exe http 9000
```

```bat:console
ngrok by @inconshreveable

Session Status                online
Account                       <ACCOUNT_NAME> (Plan: free)
Version                       2.1.18
Region                        United States (us)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://fcfe9071.ngrok.io -> localhost:9000
Forwarding                    https://fcfe9071.ngrok.io -> localhost:9000

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00
```

* Free Planだと、`https(ngrok) ---> http(local)`は出来ますが、`https(ngrok) ---> https(local)`はできません。
* ngrokのURLは、ngrokの起動のたびにランダムに変わります。


### リージョンの指定

regionを指定しないとデフォルトのUnited States (us)が使用されますが、コマンドラインのオプションかngrok.ymlでAsia Pacific (ap)を指定することができます。

```bat:http
> ngrok.exe http --region ap 9000
```

```bat:console
ngrok by @inconshreveable

Session Status                online
Account                       <ACCOUNT_NAME> (Plan: free)
Version                       2.1.18
Region                        Asia Pacific (ap)
Web Interface                 http://127.0.0.1:4040
Forwarding                    http://f819df02.ap.ngrok.io -> localhost:9000
Forwarding                    https://f819df02.ap.ngrok.io -> localhost:9000

Connections                   ttl     opn     rt1     rt5     p50     p90
                              0       0       0.00    0.00    0.00    0.00
```

### basic認証をかける

authオプションでbasic認証を設定することができます。

```bat:auth
> ngrok.exe http --region ap --auth=falken:joshua 9000
```

### ログファイルを出力する

```bat:log
ngrok.exe http --region ap --log /tmp/ngrok.log --log-format json --log-level info 9000
```


## Web Interface

ngrokを実行すると、localhost:4040でWeb Interfaceというアプリケーションが起動します。ここで通信の内容やメトリクス、ngrokの設定を確認することができます。

![ngrok_web_if.png](https://qiita-image-store.s3.amazonaws.com/0/22772/c3974737-abf6-5488-daa0-dfbb1ec6954f.png)


## 設定ファイル

ngrok.ymlという設定ファイルに、コマンドラインのオプションや通信の設定をtunnelsセクションに指定することで実行時のパラメータを省くことができます。
設定ファイルのデフォルトの場所は、ユーザーのホームディレクトリ下の.ngrok2というディレクトリです。
コマンドラインのconfigオプションで任意の場所にある設定ファイルを指定することもできます。

* [The ngrok configuration file] (https://ngrok.com/docs#config)

tunnelsセクションには複数の設定を記述することができ、それぞれに任意の名前（下記の例でいえばdevapp）をつけることができます。

```yaml:ngrok.yml
authtoken: <Authtoken>
json_resolver_url: ""
dns_resolver_ips: []

region: ap
log_level: info
log_format: json
log: /tmp/ngrok.log

tunnels:
 devapp:
   addr: 9000
   proto: http
   auth: falken:joshua
```

この設定でngrokを起動する場合は下記のようにstartオプションを使用します。

```bat:command
> ngrok.exe start devapp
```

![ngrok_web_if_2.png](https://qiita-image-store.s3.amazonaws.com/0/22772/79b38c00-59f2-ba1d-4f69-9c726e96562d.png)


# 補足

## help

### helpコマンド

```
> ngrok.exe help
```

<details>
<summary>help</summary>
<pre>
DESCRIPTION:
    ngrok exposes local networked services behinds NATs and firewalls to the
    public internet over a secure tunnel. Share local websites, build/test
    webhook consumers and self-host personal services.
    Detailed help for each command is available with 'ngrok help <command>'.
    Open http://localhost:4040 for ngrok's web interface to inspect traffic.
　
EXAMPLES:
    ngrok http 80                    # secure public URL for port 80 web server
    ngrok http -subdomain=baz 8080   # port 8080 available at baz.ngrok.io
    ngrok http foo.dev:80            # tunnel to host:port instead of localhost
    ngrok tcp 22                     # tunnel arbitrary TCP traffic to port 22
    ngrok tls -hostname=foo.com 443  # TLS traffic for foo.com to port 443
    ngrok start foo bar baz          # start tunnels from the configuration file
　
VERSION:
   2.1.18
　
AUTHOR:
  inconshreveable - <alan@ngrok.com>
　
COMMANDS:
   authtoken    save authtoken to configuration file
   credits      prints author and licensing information
   http         start an HTTP tunnel
   start        start tunnels by name from the configuration file
   tcp          start a TCP tunnel
   tls          start a TLS tunnel
   update       update ngrok to the latest version
   version      print the version string
   help         Shows a list of commands or help for one command
</pre>
</details>

### authtokenコマンド

```
> ngrok.exe help authtoken
```

<details>
<summary>authtoken - save authtoken to configuration file</summary>
<pre>
USAGE:
   ngrok authtoken [command options] [arguments...]
　
DESCRIPTION:
   The authtoken command modifies your configuration file to include
   the specified authtoken. By default, this configuration file is located
   at $HOME/.ngrok2/ngrok.yml
　
   The ngrok.com service requires that you sign up for an account to use
   many advanced service features. In order to associate your client with
   an account, it must pass a secret token to the ngrok.com service when it
   starts up. Instead of passing this authtoken on every invocation, you may
   use this command to save it into your configuration file so that your
   client always authenticates you properly.
　
EXAMPLE:
    ngrok authtoken BDZIXnhJt2HNWLXyQ5PM_qCaBq0W2sNFcCa0rfTZd
　
OPTIONS:
   --config             save in this config file, default: ~/.ngrok2/ngrok.yml
   --log "false"        path to log file, 'stdout', 'stderr' or 'false'
   --log-format "term"  log record format: 'term', 'logfmt', 'json'
   --log-level "info"   logging level
</pre>
</details>

### httpコマンド

```
> ngrok.exe help http
```

<details>
<summary>http - start an HTTP tunnel</summary>
<pre>
USAGE:
   ngrok http [command options] [arguments...]
　 
DESCRIPTION:
   Starts a tunnel listening for HTTP/HTTPS traffic with a specific hostname.
   The HTTP Host header on incoming public requests is inspected to
   determine which tunnel it matches.
　
   HTTPS endpoints terminate TLS traffic at the ngrok server using the
   ngrok.io certificates. The decrypted, HTTP traffic is then forwarded
   through the secure tunnel and then to your local server. If you don't want
   your TLS traffic to terminate at the ngrok server, use a TLS or TCP tunnel.
　
EXAMPLES:
   ngrok http 8080                      # forward ngrok.io subdomain to port 80
   ngrok http example.com:9000          # forward traffic to example.com:9000
   ngrok http -subdomain=bar 80         # request subdomain name: 'bar.ngrok.io'
   ngrok http -hostname=ex.com 1234     # request tunnel 'ex.com' (DNS CNAME)
   ngrok http -auth='falken:joshua' 80  # enforce basic auth on tunnel endpoint
   ngrok http -host-header=ex.com 80    # rewrite the Host header to 'ex.com'
　
OPTIONS:
   --auth               enforce basic auth on tunnel endpoint, 'user:password'
   --authtoken          ngrok.com authtoken identifying a user
   --bind-tls "both"    listen for http, https or both: true/false/both
   --config             path to config files; they are merged if multiple
   --host-header        set Host header; if 'rewrite' use local address hostname
   --hostname           host tunnel on custom hostname (requires DNS CNAME)
   --inspect            enable/disable http introspection
   --log "false"        path to log file, 'stdout', 'stderr' or 'false'
   --log-format "term"  log record format: 'term', 'logfmt', 'json'
   --log-level "info"   logging level
   --region             ngrok server region [us, eu, au, ap] (default: us)
   --subdomain          host tunnel on a custom subdomain
</pre>
</details>

### startコマンド

```
> ngrok.exe help start
```

<details>
<summary>start - start tunnels by name from the configuration file</summary>
<pre>
USAGE:
   ngrok start [command options] [arguments...]
　
DESCRIPTION:
   Starts tunnels by name from the configuration file. You may specify any
   number of tunnel names. You may start all tunnels in the configuration
   file with the --all switch.
　
EXAMPLES:
   ngrok start dev        # start tunnel named 'dev' in the configuration file
   ngrok start web blog   # start tunnels named 'web' and 'blog'
   ngrok start --all      # start all tunnels defined in the config file
　
OPTIONS:
   --all                start all tunnels in the configuration file
   --authtoken          ngrok.com authtoken identifying a user
   --config             path to config files; they are merged if multiple
   --log "false"        path to log file, 'stdout', 'stderr' or 'false'
   --log-format "term"  log record format: 'term', 'logfmt', 'json'
   --log-level "info"   logging level
   --none               start running no tunnels
   --region             ngrok server region [us, eu, au, ap] (default: us)
</pre>
</details>


## 有償プランで出来ること

* Custom Subdomains
* Reserved domains
* Tunnels on your own domains
* End-to-End TLS Tunnels
* Reserved TCP Addresses
* TLS Client Termination
* Wildcard domains
* IP Whitelisting