2020/11/18

ngrokでSSHサーバを外部公開

自宅や会社で検証用のサーバを構築しても、一般的にはセキュリティの関係上、社外ネットワークからアクセスはできません。とはいえ、昨今はクラウドサービスを利用することが多くなってきおり、このクラウドサービスと自分のローカルPC上に構築した検証環境間で検証しなければならない場合も増えてきていると思います。

これを可能にしてくれるサービスがngrokです。ngrokを使うことで、ローカルPC上で稼働しているサービス、例えばWebサーバやSSHサーバを外部公開できます。つまり、インターネットからローカルPC上で稼働しているサービスにアクセスできるということです。

本記事では、ngrokのインストール、設定、およびLinux上で稼働するサービスへのアクセス確認までを説明します。

※本記事ではSSH単体サービスの外部公開について説明しています。1サーバから複数サービス(例:SSHとHTTP)の外部公開を行う方法は別の記事「ngrokで複数トンネルの設定」をご参照ください。


ngrokのインストール

ngrokを不便なく利用するにはngrok公式サイトからユーザ登録を行う必要があります。私はGoogleアカウントで登録しました。

ユーザ登録をすると認証トークンが払い出されるのですが、この認証を行わずにngrokを利用していると8時間でセッションが切られてしまうとのことです。よって、ここでは、ユーザ登録を行い、認証トークンを取得する前提とします。

さて、ユーザ登録を済ませると、早速ngrokのダッシュボードにアクセスできるようになります。


ダッシュボード上のダウンロードページ、またはダウンロードサイトから利用環境のOSに合ったngrokのパッケージをダウンロードします。私の環境ではwgetコマンドを用いてLinux版をダウンロードしました。

wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
--2020-11-18 03:55:16--  https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip
Resolving bin.equinox.io (bin.equinox.io)... 54.164.74.108, 52.6.97.115, 52.73.16.193, ...
Connecting to bin.equinox.io (bin.equinox.io)|54.164.74.108|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 13773305 (13M) [application/octet-stream]
Saving to: ngrok-stable-linux-amd64.zip

ngrok-stable-linux-amd64.zip         100%[====================================================================>]  13.13M  2.46MB/s    in 6.4s

2020-11-18 03:55:24 (2.04 MB/s) - ngrok-stable-linux-amd64.zip saved [13773305/13773305]

$ ls
ngrok-stable-linux-amd64.zip

ダウンロードしたngrokパッケージをunzipコマンドで解凍します。ngrokパッケージは実行ファイルなどを圧縮ファイルとして格納しただけのものなので、取り急ぎ任意の場所(私の環境ではユーザのルートディレクトリ配下)に解凍します。

unzip ngrok-stable-linux-amd64.zip
Archive:  ngrok-stable-linux-amd64.zip
  inflating: ngrok
$ ls
ngrok  ngrok-stable-linux-amd64.zip

このまま任意の場所で利用してもよいのですが、Linux系の例にならって、ngrokフォルダを/usr/binへコピーします。コピー後は圧縮ファイルとコピー元のフォルダを削除できます。

sudo cp ngrok /usr/bin/
$ rm -rf ngrok ngrok-stable-linux-amd64.zip

最後に、ngrokコマンドを実行し、バージョン番号が表示することを確認することで、ngrokが正常にインストールできたことを確認します。

ngrok version
ngrok version 2.3.35


ngrokの設定

次に、ngrokユーザ登録時に発行された認証トークンを設定ファイルに登録します。ngrok authtokenコマンドでngrokの設定ファイルへ認証トークンを登録してくれます。

なお、ngrokのダッシュボードの左メニューから「Your Authtoken」をクリックすることで、認証トークンを確認できます。(以下xxxの個所に認証トークンを指定)

ngrok authtoken xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

このコマンドの実行後、実行ユーザのホームディレクトリに隠しフォルダ.ngrok2が作成され、ngrok.ymlという設定ファイルに認証トークンが保管されます。


動作確認

さて、ここまででngrokの設定は完了です。ここでは1つのサービスを外部公開し、インターネットから公開したサービスにアクセスしてみます。

私の環境では、SSHサーバを外部公開したいと思います。SSHサーバはデフォルトポートである22/tcpをリッスンして稼働しています。よって、tcp 22番ポートを指定して、ngrokコマンドを実行します。

ngrok tcp 22

実行すると、コマンドターミナルがクリアされて、ngrokの状態画面が表示されます。

ngrok by @inconshreveable

Session Status        online
Account               xxxxx@xxxxx (Plan: Free)
Version               2.3.35
Region                United States (us)
Web interface         http://127.0.0.1:4040
Forwarding            tcp://4.tcp.ngrok.io:19134 -> localhost:22

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

これでngrokが通信を仲介してくれます。それでは、クライアントからインターネット越しにこのサーバ(この例では4.tcp.ngrok.io:19134)へアクセスしてみます。

まずは、SSHクライアント(私の環境ではPuTTY)でngrokの中継サーバのサーバアドレスとポート番号を入力します。


Openボタンを押下すると・・・
少し経ってからログインプロンプトが表示されました。ngrokを経由して検証環境へアクセスできたということになりますね。


続いて、ログインIDとパスワードを入力すると・・・


おおっ!SSHサーバに接続・ログインできました!


補足

ngrokコマンドを発行したコンソールは、相変わらずngrokの状態画面のままです。


ここで、Ctrl+Cを押下すると、ngrokのセッションが切れてしまいます。そこでバックグラウンドで実行することを検討してみました。

&(アンパサンド)を最後につけて・・・

ngrok tcp 22 &

確かにコンソールに制御が戻ってきたのですが、ngrokのサーバとポート情報はどこでしょう。


ngrokのドキュメントを参考にしたところ、以下のcurlコマンドで取得できるとのこと。

curl -s http://localhost:4040/api/tunnels | jq -r .tunnels[0].public_url


ところが、反応が何もありません。入力も受け付けない。仕方なくCtrl+Cで強制的にコマンドを終了します。

結局、解決の糸口がつかめないままWebをさまよっていたところ、とある英語サイトで気になる内容のディスカッショントピックがありました。標準出力に問題があると。すでに起動しているngrokのプロセスを強制終了し、コマンドの実行方法を変えてもう一度やってみます。


実行するコマンドはこちらです!

ngrok tcp 22 > /dev/null &


コマンド制御も戻ってきて、かつngrokのサーバとポート情報も無事に取得できるようになりました。


おわりに

最後はハマりましたが、間違いなくngrokは今後の効率的なデモ、開発、検証を支援してくれるツールです。ngrokでWebサーバやアプリケーションサーバの公開、ドメインを使った中継などもできるようなので、引き続き試してみようと思います。

なお、今回はSSHサービスのみの外部公開でしたが、フリープランで複数のサービス(例:SSHとHTTP)を公開したい要求もあると思います。その方法は別の記事「ngrokで複数トンネルの設定」で説明します。