Cloudflareの機能を使って外部からセキュアにVNCアクセスしてみた

# TL;DR
* ボタンポチー + αくらいで、社外から社内システムを使いたい
 * セキュリティを担保したいけど、面倒なことをしたくない
 * セキュリティ担保をするために、運用工数などをかけたくない
 * 多少のお金は払っても良い
* 結論： テスト利用した感触としては、Cloudflare Argo Tunnel + Cloudflare Accessは通常よりも簡単にセキュリティを担保できるから良いぞ

# 本記事の背景と目的
GUIを触るために構築したUbuntu Desktopに対してトラブル対応時などに外部からVNC経由でアクセスしたいという要望がありました。
通常、社外から何かしら社内システムを触る場合には、不正アクセスなどが無いようにセキュリティが担保されているか、をきちんと検討しなければなりません。

特に、今回の環境はオンプレで稼働しているため、クラウドよりも考慮点や関係者が多いです。

そういった中で、以下4つの要件を満たす`Cloudflare Argo Tunnel` と `Cloudflare Access` を使うことで、VNC環境を外部からセキュアにアクセスできるようになったので備忘録として残しておきます。

```bash:要件
1. 利便性が高い
 * VPNなど特別な回線や設備が不要で、インターネット回線さえあれば良いこと
2. 導入が容易である
 * 外部からアクセスするにあたり、既存機器のACL変更などが発生しないこと
3. 認証機能が備わっていること
 * 出来れば、Google OAuthなど、複数の認証機能が利用できるとGood
4. (これは追加要望)出来ればVNCをブラウザから触りたい。
 * これは、後述するnoVNCで実現可能です。
```

## Cloudflare Argo Tunnelについて
### 概要
私が説明するよりも以下のリンクを見ていただいたほうが早いと思いますｗ
[Cloudflare Argo Tunnel](https://www.cloudflare.com/ja-jp/products/argo-tunnel/)

凄い雑に説明すると、公開したいサーバやアプリケーション側の設定を変更することなく、公開したいサーバ/アプリケーションがCloudflareと暗号化された通信を開始し、Cloudflare経由でセキュアなアクセスが可能になります。

利用例では、開発者の手元のMacで稼働しているWebサーバに外部からアクセスしたい、なんてときにも利用できますね。

### 費用
Cloudflare Argo Tunnel( 以下、Argo Tunnel )の利用自体は無料ですが、Argo Tunnelを利用するにはArgo Smart Routing( 以下、Argo ) が必要です。
Argoを利用するためには、5ドル/月と通信量に応じて 0.10ドル/1GBの費用がかかります。


### 実装
それでは、実装してみましょう。
以下を前提として構築されているものとします。

1. OSはUbuntu 16.04 Desktop
2. vnc4serverが導入済み かつ アクセス可能
3. [noVNC](https://github.com/novnc/noVNC) が導入済み
 * [quick-start](https://github.com/novnc/noVNC#quick-start)のとおりやれば動きます。

なお、公式ドキュメントは[こちら](https://developers.cloudflare.com/argo-tunnel/quickstart/)です。

#### 対象ドメインの追加
外部からアクセスする際のドメインを設定します。
どのプランにするか、はご自身の環境と相談なさってください。
私の方はテストということもあり、とりあえず無料プランで始めています。
すでに持っている方は飛ばしてください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56386/454c2f9a-eb70-0763-bbeb-11aaeea63950.png)


#### Argoの有効化
追加したドメインを選択し、画面上部の「Traffic」からArgo( Argo Smart Routing )を有効化する画面に飛びます。
以下の画像では、すでにEnabledになってますが、初めてEnableにする際は、お金かかるよ的な感じで聞いてくれます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56386/a0b10ef7-fffb-444a-49be-f5087f538b05.png)

ちなみに、Argoを有効化しない状態で、Argo Tunnelを使おうとしても以下のようなエラーを吐いて怒られます。

```bash: 
ERRO[0000] Register tunnel error from server side        connectionID=0 error="Server error: Argo Smart Routing is NOT enabled"
ERRO[0001] Quitting due to error                         error="Server error: Argo Smart Routing is NOT enabled"
```

#### Argo Tunnelのインストールから起動まで
続いて、`cloudflared` というパッケージのインストールを行います。
インストール先は、前提に記載したnoVNCを外部公開したいUbuntu Desktop(以下、VNCサーバ)が対象となります。
[ここ](https://developers.cloudflare.com/argo-tunnel/downloads/)から環境にあったパッケージをダウンロードしましょう。
今回は、 `.deb` パッケージをダウンロードし、インストールしました。

インストールできたら、次のコマンドを実行してログインしましょう。

```bash
$ cloudflared tunnel login
```

コマンド実行後、URLが表示されます。
自動的にブラウザで表示されない場合はコピペして開きましょう。

( 環境によってはroot権限が必要なことがあります。適宜読み替えてください )

ブラウザで開くと、どのドメインと紐付けるかを聞かれるので、希望するドメインを選択してください。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56386/8f78f405-aa9b-84ba-653c-296aec6277c9.png)

ドメイン選択後、証明書がダウンロードされます。
この証明書を、VNCサーバの `/etc/cloudflared/` 配下に配置してください。
すでに存在する `cert.pem` は破棄するかどこかに移動しておきましょう。(中身は空っぽです)

続いて、以下を参考にconfig.ymlを修正しましょう。
最低限、 `hostname`と`url`があれば良いとはドキュメントに書いてありますが、せっかくなので`logfile`も指定します。

```bash
$ cat /etc/cloudflared/config.yml
hostname: masked_domain.dev  # ご自身の環境に合わせてください
url: http://localhost:6080   # こちらもご自身の環境に合わせてください。noVNCデフォルトはこれで行けます。
logfile: /var/log/cloudflared.log
```

続いて、以下のコマンドでArgo Tunnelのdaemonを起動しましょう。

```bash
$ cloudflared tunnel --config /etc/cloudflared/config.yml --origincert /etc/cloudflared/cert.pem
```

以下のようにログが出力されたまま終われば起動成功です。

```bash
INFO[0007] Route propagating, it may take up to 1 minute for your new route to become functional  connectionID=2
INFO[0009] Connected to SIN                              connectionID=3
INFO[0009] Each HA connection's tunnel IDs: map[0:hoge 1:fuga 2:foo 3:bar]  connectionID=3
INFO[0009] Route propagating, it may take up to 1 minute for your new route to become functional  connectionID=3
```

この状態だと、ドメインさえ知っていれば誰でもアクセスできる状態です。
続いて、Cloudflare Accessを入れましょう。

## Cloudflare Accessについて
詳細な説明は[Cloud Access](https://www.cloudflare.com/ja-jp/products/cloudflare-access/)をご覧ください。
超絶雑にいうと、Cloudflareを通っているアプリケーションやWebサイトであれば、ボタンひとつで認証設定が行えます。
今回のように、Argo Tunnelを経由している場合はアプリケーション側の設定変更無しに認証機能を実装できるのは良いことですね :)

### 費用
5人までは無料ですが、6人目からは3ドル/人かかります。
今回はテスト用途なので、5人までの無料プランにしています。


### 実装
では、実装しましょう。

Cloudflareのダッシュボードから、今回設定対象のドメインを選択してください。
選択後、画面上部の「Access」をクリックすると、Cloudflare Accessが未設定であれば以下のような画面が出てきます。
Paymentの画面が出てきますが、5人に設定しておくと0ドルになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56386/4a3ce29e-12f5-8265-31f7-d998e67e9486.png)


次にアクセスポリシーの設定にしましょう。
( 初回設定時、自動的に遷移するかもしれません。 )
今回は、お試しでメール認証にしてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56386/bbccdabb-4e7b-bee2-4879-31e3618e3837.png)



### 実際にアクセスする
ここまでくれば、Argo Tunnel + Cloudflare Accessによってアクセスができる状態となっていると思います。
私の環境では以下の流れでアクセスできます。

https://自ドメイン/vnc.html にアクセスする
メール認証を求められるので自身のアドレスを入力する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56386/957c84fd-a674-1d85-da03-6155b00eaef6.png)

メールに送られたPINコードの入力を求められます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56386/63afd86d-fad5-6fb5-3d90-8be5182e3622.png)

noVNCの画面に遷移します。
VNC接続用のパスワードを求められる場合は入力しましょう。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56386/ba4e7671-a5be-4993-dfa3-8046273ff495.png)

noVNCへ接続できましたね。
手元のスマホなどからもアクセスできますよ。お試しあれ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56386/4c7bfdfd-4dcd-71d7-bdea-b03da29680e3.png)

もちろん、VNC経由の操作で[イチマン](https://ichiman.j-sen.jp)を見ることだって出来ます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/56386/6c5bae3b-bf4a-34be-b282-c9b0fd31629b.png)


今回はメールにしましたが、他にもGoogleやGitHubアカウントを利用した複数のOAuth認証が利用できるようですね。

# まとめ
今回は、あくまでテストということで、本当に必要最低限の設定しかしていません。
(英語をきちんと読まなかったせいで)ハマった箇所もそれなりにはありましたが、それでも社内にある機器のACLを変更する、などよりは非常に簡単に社外からアクセスできるようになりました。

今回は、題材としてVNC( noVNC )を選択しましたが、これ以外にもRedashやRundeck、phpMyAdminなどの管理ツールなど、セキュアにかつ社外からアクセスしたいんだけど正直手が回らない系の箇所にArgo TunnelやCloudflare Accessを利用はとても良いと思いました。