Cloudflare for Teamsを使ったNode-REDへのリモートアクセス

# Node-REDへのリモートアクセス手段について
PCやRaspberry PiでNode-REDサーバを構築し活用する場合、同一LAN内からのアクセスはできますが、インターネットからのリモートアクセスができないことがネックになることが多いと思います。従来、この用途に[ngrok](https://ngrok.com/)が使われることが多く、簡単な設定で[node-red-contrib-ngrok](https://flows.nodered.org/node/node-red-contrib-ngrok)を導入することでNode-REDからも活用できますが

- 無料プランだとセッション維持時間に制限があり、再接続時にはURLが変更になる。
- 有料サービスは結構高い (\$60/年～。\$5/月出すならVPS借りますよね)。
- 標準でアクセス制限機能がBASIC認証しかないので、柔軟な設定はNode-REDサーバ側で設定する必要があり、設定を間違えると危険。
- 独自ドメインの場合、httpsで使うには証明書を自前でセットアップする必要がある。

という問題があり、テスト的に短期間つかうのはともかく、ngrokで安定的に稼働するサービスを構築するのは難しいのではないかと思います。

本稿では、ngrokに代わり、Cloudflare社が提供する[Cloudflare for Teams](https://www.cloudflare.com/ja-jp/teams/)を活用することで、グローバルIPアドレスを持たないNode-REDサーバを**インターネットへ安定して公開**できるリモートアクセスを構築する手順を解説します。

## 本稿の対象読者

- できるだけ安く(月に100円程度～)インターネットから固定URLでアクセスできるNode-REDサーバを運用したい
- 自宅IoTダッシュボードにインターネットからだれでもアクセスできてほしいが、FlowEditorには自分だけがアクセスできるようにしたい
- パブリッククラウドサーバなんて信用できないので（そんなことはありません）Node-REDもオンプレミスサーバで運用したい



# Cloudflare for Teamsについて
[Cloudflare社](https://www.cloudflare.com/ja-jp/) は大手CDN事業者で、公開Webサイトへの外部からの様々な攻撃から防御しつつ、セキュアで効率的にコンテンツを配信するさまざまなサービスを提供しています。2018年7月より、セキュアなリモートアクセスVPNを提供する[「Cloudflare Access」を提供](https://blog.cloudflare.com/cloudflare-access-now-teams-of-any-size-can-turn-off-their-vpn/)していましたが、Access及び周辺のサービス(Cloudflare Gateway等)を合わせて2020年1月に「Cloudflare for Teams」として[新たに提供](https://www.cloudflare.com/ja-jp/press-releases/2020/cloudflare-enters-new-security-market-launches-cloudflare-for-teams-to-make/)されています。

Cloudflare for Teamsの特徴は以下の通りです。

- Webサーバや社内PCアプリなどのローカル向けサービスに、インターネットから安全にアクセスする「ゼロトラストアクセス」を提供
- Cloudflare Gateway機能で、クライアントからの柔軟なアクセス制御、アクセスログの提供
- Cloudflare Access機能で、安全なリモートトンネリング機能の提供

## Cloudflare AccessとCloudflare for Teamsとの関係（未確認）

本稿では、Cloudflare for Teamsのうち、Cloudflare Accessの機能を中心に説明します。単体のサービスとしてのCloudflare Accessは、\$3/月/ユーザ/ドメインのサブスクリプション課金体系になっていますが、Cloudflare for Teamsから使うと、50ユーザ/ドメインまで無料で使えるようです。Cloudflare for TeamsのダッシュボードでAccessの設定をすると、Cloudflare Accessのコンソール（日本語あり）にも情報が表示されますが、ここで設定した内容がサブスクリプション課金なしで使えるかどうか不明なので、本稿では、設定はすべてCloudflare for Teamsのダッシュボード（残念ながら日本語化されていません）を使う想定で記述しています。


▼Cloudflare Accessシステム図( https://developers.cloudflare.com/access/about )

![image.png](https://developers.cloudflare.com/access/static/35228a755cf2a5e5489c38e74c1e35a0/56dab/network-diagram.png)

## Node-REDサーバとCloudflare for Teamsでできること

Node-REDサーバと合わせて活用することで、以下の機能を実現することができます。

- 自宅LANやイントラネットで稼働しているNode-REDサーバに、インターネットから安全にアクセスすることができる。
- Node-RED側で高度な設定をしなくても、Cloudflare側の設定だけで柔軟なアクセス制御ができる。例えば、FlowEditorにはメールpinコード認証、WebAPIにはIPアドレス制限、Dashboard uiには制限なし、ということが可能。
- Node-RED側の設定なしにTLSサーバ証明書が設定され、httpsでセキュアなアクセスを提供。

また、適切に設定を行うことで、Node-REDサーバ以外にも

- SSH/RDP/VNCを用いたリモートアクセス
- SFTP/SMBを用いたネットワークストレージのリモートアクセス
- 自社で契約したSaaSへのセキュアなアクセス

等に活用することができます。（本稿では説明しません）

ちなみに、名前は似てますが、[Microsoft Teams](https://www.microsoft.com/ja-jp/microsoft-365/microsoft-teams/group-chat-software/)とは関係ないみたいです。


## Cloudflare for Teamsの料金プラン
Cloudflare for Teamsはフリーミアムで提供されており、

- 最大50アクセスユーザアカウント
- 最長1日のアクセスログ

は利用料無料で使うことができます。現在のところ、無料サービスでもアクセス数やトラフィックに制限はないようです。さすがCDN事業者、太っ腹。

なお、有料サービスについては
https://www.cloudflare.com/teams-pricing/
を参照してください。Node-REDを小規模にリモートアクセスするだけなら無料プランで十分です。

## Cloudflare for Teamsの利用に必要なもの
Cloudflare for Teamsの利用には以下のものが必要です

- 自分でDNS設定可能で、できれば他の用途に使っていないドメイン名（レジストラが無料で提供するTLDは不可）
- Cloudflareのアカウント、クレジットカード or 有効なPayPalアカウント （無料プランでも必要）
- インターネットに接続した、公開するサーバ（IPアドレス変動しても、グローバルIPを持ってなくてもOK）
 
Cloudflare for Teamsの設定を実施するために、まず自分のドメイン名を登録する必要があります。ドメイン名はこの用途のために新しく取得する場合は問題ありませんが、別の用途で使っている場合、ネームサーバの管理をCloudflareに移す必要があり、メールサーバの停止等の支障をきたすことがあります。（DNSの導入ウィザードがあり、間違いにくいようにはなっています）

ドメイン名は、レジストラから購入することができます。手軽に購入できる[google domains](https://domains.google.com)だと年1300円くらいからあります。もっと安いレジストラもあり、初年度の取得費用を割り引いているところを使うとコストを抑えることもできます。（初年度費用が安いレジストラは初年度中のドメイン移管ができないなど、制約も多いので注意が必要です）

なお、[一部のTLD](https://www.cloudflare.com/ja-jp/tld-policies/)では、[Cloudflare Registrar](https://www.cloudflare.com/ja-jp/products/registrar/)へドメインを移管することで、Cloudflare内で管理でき、コストを節約することができるとのことですが、2020年12月現在、Cloudflare Registrarで新規ドメインを登録することはできないようで、一旦別のレジストラでドメイン取得して移管するしかないようです。(.comドメインが\$8.03/年はかなりお安いので、初年度の費用が安いレジストラで契約し、Cloudflare Registrarへ移管してもいいかもしれません）

また、.cf/.ga/.gq/.ml/.tkのTLDの登録を無料で実施してくれるレジストラがありますが、これらのドメインはCloudflare for Teamsの無料プランでは利用できません。

Cloudflare for Teamsの無料プランの利用開始時に、クレジットカードかPayPalのアカウント登録が必要です。無料プランであれば課金されることはないはずですが、心配なら、PayPal側で支払い上限を設定するなど自衛しましょう。(Cloudflareの請求画面でBilling Usage Alartを設定することができるようですが、利用サービスが無料サービスだけならそもそも選択肢が表示されず、設定できません）

公開するサーバは、本稿ではNode-REDが稼働するサーバを想定しています。cloudflaredというプログラムをサービスとして起動することでCloudflare accessに常時接続する必要があり、公開したいNode-REDサーバが接続しているLANがインターネットに接続している必要があります。モバイルネットワークやケーブルテレビネットワーク、IPoE(v6プラス/transix)等のような、IPアドレスが固定されなかったり、そのLANがグローバルIPアドレスを持つネットワークに接続していない場合でも大丈夫です。

# Node-REDサーバ側設定
Node-REDの導入方法については本稿では説明しません。Raspberry Piへの導入については、拙記事 [Raspberry PiにおけるNode-REDの活用について](https://qiita.com/utaani/items/7155c62d6c5e96822afb)を参照ください。

Node-REDサーバにCloudFlare for Teamsを使ってリモートアクセスを実施するためには、Node-REDサーバ側にもいくつかの設定が必要になります。

## Node-REDのURL設定
標準インストールでは、```http://localhost:1880/``` にアクセスするとFlowEditorにアクセスできます。リモートからFlowEditorにアクセスするのが所有者のみで、1種類のアクセス制限だけなら標準設定でも問題ありませんが、FlowEditor/Dashboard UI/静的コンテンツなどそれぞれごとにアクセス制限を設ける場合は、FlowEditorのURLを分離する必要があります。セキュリティ的にも、FlowEditorのURLは変更しておくことをお勧めします。

settings.jsの87行目付近（Node-REDのバージョンによって変わります）にある

```
//httpAdminRoot: '/admin',
```

の先頭のコメントをはずす(//を消去)することで、FlowEditorのアクセスURLが```http://localhost:1880/admin```に変更されます。

[node-red-dashboard](https://flows.nodered.org/node/node-red-dashboard)を導入している場合、ダッシュボードのURLは ```http://localhost:1880/ui```になりますが、これはsettings.jsの110行目の

```
//ui: { path: "ui" },
```

で変更することができます。（有効にするには先頭のコメント//を外す）

また、Node-REDでは内蔵のexpressエンジンをつかって静的コンテンツの配信も可能ですが、settings.jsの102行目

```
//httpStatic: '/home/nol/node-red-static/',
```

で変更することができます。（有効にするには先頭のコメント//を外す）


さらに、HTTP-inノードなどURLを使う場合は、それぞれのノード内でURLを設定しますが、settings.jsの93行目の

```
//httpNodeRoot: '/red-nodes',
```
の設定でrootパスを指定することができます。（有効にするには先頭のコメント//を外す）

Node-REDのこれらのURLごとに、後述のアプリケーション設定を割り当てることで、それぞれ違った認証でNode-REDを使うことができるようになります。

なお、settings.jsを変更した場合は、有効にするためにNode-REDを再起動する必要があります。（```node-red-restart```コマンド、もしくは```sudo systemctl restart nodered```)

## FlowEditorのログイン画面設定（推奨）

Node-REDの標準インストールでは、前述のとおり ```http://localhost:1880/admin``` にアクセスすることでFlowEditorを開くことができますが、settings.jsに設定することで、FlowEditorへのアクセス時にNode-RED側でログイン画面を開いて認証させることができます。

▼ログイン画面の例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/0ff67ab0-f624-50ed-20a6-9727e24aeaa7.png)

Raspberry Piの場合、標準インストールではNode-REDはpiユーザで動作しますが、piユーザは管理者権限を持ちますのでFlowEditorからexecノードを使われてしまうと管理者権限でRaspberry Piの全操作が可能になってしまいます。

Cloudflare for Teamsで設定完了すると、アクセス時にCloudFlareの認証が設定されますので、ローカル側での認証設定は過剰かもしれませんが、設定ミスによって認証が外れた場合にNode-RED側の認証ダイアログが最後の砦になるかもしれませんので、設定しておくことをお勧めします。（すべてのアクセスをCloudflare経由でアクセスする場合は、Cloudflare側の設定完了を確認した後にNode-RED側の認証を外してもいいかもしれません）

[Flow Editorのログイン画面設定 (重要)](https://qiita.com/utaani/items/7155c62d6c5e96822afb#flow-editor%E3%81%AE%E3%83%AD%E3%82%B0%E3%82%A4%E3%83%B3%E7%94%BB%E9%9D%A2%E8%A8%AD%E5%AE%9A-%E9%87%8D%E8%A6%81) にて設定方法を記載していますので参考にしていただければ幸いです。


# Cloudflare for Teamsの設定
それではCloudflare for Teamsの設定を行っていきます。まず最初に、Cloudflare for TeamsのWebページ https://www.cloudflare.com/ja-jp/teams/ にアクセスします。

▼Cloudflare for Teams Webページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/53ca1adc-4432-3de8-a3de-711ed976e79a.png) 
（以降、画面スナップショットと手順は2020年12月現在のものです。将来変更されるかもしれません）

## アカウント取得
右上の「サインアップ」から、アカウント取得の手続きをします。

▼アカウント作成ページ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/9b552c48-d3bd-5af0-86b4-dd0ff6d091ca.png)

「アカウントを作成」をクリックすると、設定したメールアドレスにメールアドレス確認用のメールが届きますので、リンクをクリックして確認します。

▼Welcomeページ（メールのリンクをクリックすると表示される）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/2db4aac7-6354-9744-69be-248d3df33e8d.png)

Welcomeページが表示されます。が、この画面からはサイト登録（ドメイン設定）ができないので、右下の「Skip To Teams dash→」をクリックしてダッシュボードを表示し、

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/7a4ca936-d622-d986-64b3-a5d04ebb8073.png)

さらに画面左下の「cloudflare.com→」をクリックしてCloudflareのサイトトップに移動します。（アカウント作成手順によっては、最初からサイトトップで表示されることもあります）

▼Cloudflare サイトトップ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/d107db34-8b9a-8bb2-b987-b03b96700b5a.png)

## サイト（ドメイン）の追加
新しくアカウントを作成した場合には、Webサイト登録がありません。「+サイトを追加する」をクリックして、ドメインを登録します。

▼サイトを追加する
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/80edc303-4ed7-4837-9f4d-97afdc05ef0c.png)

サイト名のところに、所有するドメイン名を入力して「サイトを追加」をクリックします。

▼プラン選択
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/c9cf12fa-4b72-738b-da4a-0b4c21843d3c.png)

「プランを選択」画面では、下部のFreeをクリックすると、枠が青くなり（わかりにくい）、「続行」がクリックできるようになります。

▼現在のDNS登録状態
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/819ada4a-4e09-f5cc-8ac6-4e068fb1ee24.png)

確認して「続行」をクリックします。

▼ネームサーバ設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/2ac559ac-8434-f549-3f43-a17c5b49d613.png)

新しく取得導入したドメインでも、デフォルトでレジストラのNS（ネームサーバ設定）がすでに登録されていることが多いです。DNSのNSフィールドを、Cloudflareから指示されたものに置き換えます。書き換えたら画面下部の「完了しました、ネームサーバーをチェックしてください」をクリックします。


なお、お持ちのドメインが、Google Domainsで登録されている場合は、マイドメイン管理の「DNS」メニューで変更できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/b78d9f62-a8d7-82f8-9bcc-2141eb00dc69.png)

▼クックスタートガイド
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/9df92a0e-4419-ea37-7a2b-fc3e284a8a14.png)

クイックスタートガイドが表示されますが、「あとで完了する」をクリックしてサイトホーム画面にもどります。

▼サイトホーム画面（まだネームサーバチェック未完了）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/0e2d15e4-0119-ccd2-955a-91e8e9c52e7c.png)

レジストラのネームサーバ設定を変更しても、すぐ反映されません。右上のアイコンをクリックして、ホーム画面にもどります。

▼ホーム画面（まだネームサーバチェック未完了）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/1df59256-4033-7115-ca24-68aaf3a5b6ed.png)

レジストラの設定やその時点のDNS設定にもよりますが、15分～数時間で反映されますので待ちます。反映されるとメール通知されるとともに、サイトトップにサイト名が表示されます。

▼ホーム画面（ネームサーバチェック完了）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/4348e3e1-e760-4075-a339-e88d6658a210.png)

ドメイン名をクリックすると、サイト管理画面に遷移します。

▼サイト管理画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/2982a91b-39d2-18b7-7a48-01cd6e28db00.png)

設定したドメインは、今後はCloudflare内でDNSコンテンツの管理をする必要があります。静的にAレコードやAAAAレコードなど設定したい場合は、Cloudflareのサイトホームの「DNS」アイコン
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/9d573ce4-0477-26b0-90f5-adb429226202.png)
から設定を実施できます。

▼DNS画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/d5f0e2a0-198f-d2aa-622a-21dc8969be9e.png)

## Cloudflare for Teamsのダッシュボードでの設定
[cloudflare-accessとcloudflare-for-teamsとの関係(未確認)](#cloudflare-accessとcloudflare-for-teamsとの関係未確認)に記述の理由により、以降の操作は、Cloudflare for Teamsのダッシュボードで実施します。サイト管理画面からは、上部のAccessでCloudflare Accessの設定画面を表示し、最上部の「Teamsを起動」で遷移できます。

▼Cloudflare Accessの設定画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/5acec852-1ad4-4415-5878-555c19efa70a.png)

なお、
https://dash.teams.cloudflare.com/
から直接、Cloudflare for Teamsのダッシュボードにアクセスできます。
（ログインしていない場合は認証画面になります）

## プランの設定、課金の追加
まず、Cloudflare for Teamsを無料で使うために、サイトのプランの設定を行います。

▼ダッシュボード画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/76c64640-3ff7-4cca-9369-b9efe76ff531.png)

Accout→Billingを選択します。

▼Billing画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/cb35a7c0-ad93-b5da-c516-773e0cc54667.png)

Choose Planをクリックし、プラン選択画面を表示します。

▼プラン選択画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/b53e81e5-4b2b-bd7a-4d49-4eb739c9df8c.png)

Freeプランの下部にある「Select Plan→」をクリックします。

▼プラン確認画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/aa8ce512-0760-980d-9684-54b0c1bd84cb.png)

Proceed to paymentをクリックします。

▼Payment Method画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/54b91f5a-66cd-5688-3657-5fa51b0c4725.png)

payment methodを追加しないと、Nextがクリックできないので、Add payment methodをクリックします。

▼Payment Method追加画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/cc17042d-af81-8e54-52d1-f54bd698cf60.png)

クレジットカードを登録する場合はカード情報を入力します。PayPalを使う場合は右上のPayPalボタンから手続きします。


▼Payment Method確認画面（Billing addressは消しています）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/d4eee013-4a38-b024-fff5-3e857e27af8c.png)

手続きできたら、PayPalのボタンが変わりますので、Billing addressを入力して「Next」をクリックします。

▼Purchase確認画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/8e812a45-02cf-1308-768e-8f8723e701c3.png)

確認画面が表示されますので、内容確認して「Purchase」をクリックします。

▼無料プランで登録されした
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/94c4f193-2931-f727-5be4-4caba4dd711c.png)


## 認証メソッドの追加（基本：メールでpinを送信する）

次に、サイトアクセスする際の認証メソッドを追加します。まず、一番簡単なOne-time PINを試してみます。One-Time PINは、認証がない状態でアクセスしたら、認証画面が表示され、同時に登録したメールアドレスにPIN番号がメールされるので、その番号を入力することでアクセスを認証する方式です。

Cloudflare for Teamsのダッシュボードから、
Access →　AuthenticationでAuthentication画面を表示します。

▼Authentication画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/07aedb3d-ffe2-e7d2-b65e-e8a8bd9bc327.png)

Login method の右側の +Addをクリックます。

▼Add an identity provider画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/fd94799b-a57b-acdc-df18-f09a90ca9ad1.png)

One-Time PINをクリックすると、設定なしで「ADDED」と表示されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/4fe3134a-62bc-9463-69a6-f20dfad6ba42.png)

## アプリケーションの設定
次に、アプリケーションの設定を行います。アプリケーションとは、Cloudflare Accessを介して公開したいWebサービスのことです。本稿ではまずNode-REDのFlowEditorを公開するところから始めます。（残りは後で設定します）

Cloudflare for Teamsのダッシュボードから、
Access →　ApplicationsでApplications画面を表示します。

▼Applications画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/452f36cf-5c38-7e87-2bbf-01c079ec44b7.png)

「Begin setup」をクリックします。

▼authentication domain設定ウィザード
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/fe11a2a6-2f8b-5c70-e2f2-e2ca7ae46954.png)

Authentication domain欄に、そのサイトで利用する認証ページのドメインを指定します。.cloudflareaccess.comは固定で決まっていますので、その前の部分にサイトを表すユニークな名前を入力し、「Next」をクリックします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/ce46e0bb-f2da-ebee-0a1b-b89e5ba065ec.png)

▼Add an application画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/450ed19c-1fb1-af57-819b-8ed51376e7ed.png)

アプリケーションの名前と、公開したいアプリケーションのURLを指定します。まず、Node-RED全体を公開する設定として、以下のように入力します。ドメイン部分は登録したドメインから選択します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/29930a75-e80b-e0eb-5638-2b3c0f521289.png)


この設定で、```https://editor.nrcf.xyz/```でNode-REDサーバが公開されることになります。FlowEditorは```https://editor.nrcf.xyz/admin```でアクセスします。

「Next」をクリックします。

▼Policy画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/f5019c64-32c2-e62f-ba07-51f4aae33388.png)

ここで認証ポリシーを設定します。すでに認証メソッドとしてOne-Time PINを設定していますので、メールの認証が2種類選択できるようになっています。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/91632021-fc8d-fc70-3441-39fdfdcfb486.png)

Emailsはユーザ決め打ちで認証する場合、Emails ending inは特定ドメインのメールアドレスはすべて許可する設定です。今回はまず自分宛のメールで認証することにしますので、以下のように入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/cd2eb5a5-292c-484c-658a-115c1d7a63f2.png)
なお、email欄は複数メールアドレスの入力が可能です。

▼設定完了画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/c14a8d0f-3fe7-acca-6ae9-532b3fb1ff07.png)

View your applicationをクリックするとダッシュボードに戻ります。

▼アプリケーション一覧画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/bc590fc9-7929-59f8-e313-1b0f022e8af5.png)

アプリケーション一覧画面で設定されていることが確認できます。


# cloudflared の導入
cloudflaredは、Cloudflare Argo TunnelというVPN構築用のクライアントプログラムです。今回の用途では、Node-REDサーバに導入することで、Cloudflare GatewayからのアクセスをNode-REDに到達させるために導入します。

なお、以下の手順では、最終的にサービス化するためにsudoで実行しています。cloudflared自体はユーザ権限での実行も可能ですが、サービス化して自動起動するには、管理者権限になれるアカウントが必要です。

導入に当たっては、 https://developers.cloudflare.com/argo-tunnel/getting-started も参照してください。

## クライアントプログラムの導入
クライアントプログラム「cloudflared」をNode-REDサーバに導入します。「cloudflared」は、Cloudflare Argo Tunnelのクライアントプログラムです。「cloudflared」はgo言語で記述されており、
https://github.com/cloudflare/cloudflared
で[独自ライセンスのOSS](https://github.com/cloudflare/cloudflared/blob/master/LICENSE)としてソース公開されています。

導入方法は以下のドキュメントサイトで公開されています。
https://developers.cloudflare.com/argo-tunnel/getting-started


まず、クライアント配布サイト
https://developers.cloudflare.com/argo-tunnel/getting-started/installation
より、ご自分の環境にあったクライアントプログラムをダウンロードします。

Linuxの場合はお使いの環境に合わせて.deb/.rpmパッケージを使うことで、パッケージマネージャによりプログラムの自動更新がされるので便利です。Node-REDサーバのブラウザでダウンロードしてそのままブラウザから実行することで導入できます。

Raspberry Piでは、ARMv6の.debパッケージが使えますが、Raspberry Pi OS 64bit版をお使いの場合はARM64版のパッケージは2020/12現在公開されていませんので、ARM64版のバイナリーファイルをダウンロードして使います。配布サイトのリンク先はGitHubリポジトリーのリリースサイトで、2020年12月現在は2020.11.11版が最新です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/c9656b17-2b15-49f9-64f1-520dc1ce678a.png)


バイナリファイルで導入する場合は、ダウンロードしたファイルを、```/usr/local/bin/cloudflared```などに配置します。Raspberry Pi OS 64bit版の場合はこんな感じです。（CLI作業）

```
sudo cp Downloads/cloudflared-linux-arm64 /usr/local/bin/cloudflared
sudo chmod +x /usr/local/bin/cloudflared
```

macOSの場合は、Homebrewを用いて導入します。Windowsの場合はZIPファイルでダウンロードし、適当なフォルダに展開した上でpathを通す必要があります。

バイナリーファイルを用いて導入した場合(windows含む)は、自動で更新されませんので、定期的に ```cloudflared update```コマンドで手動更新する必要があります。



## アクセス証明書の取得
クライアントの導入後、まず、cloudflaredを使ってTunnelを構築するために必要なアクセス証明書を取得します。

```
sudo cloudflared tunnel login
```
を実行することで、証明書を取得するための一時URLが表示されます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/84f962e4-3759-1125-3279-a69e1de9653b.png)


そのURLをコピーし、ブラウザでアクセスします。そのブラウザでCloudflare にログインしていない場合はログインします。

▼認証ドメインの確認画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/4bbff933-b155-8e9b-c8ce-a17499081170.png)
ドメインをクリックして選択します。（一つしかないはず）

▼確認ダイアログ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/663cf23b-89ac-598f-5d10-dc821904cf2e.png)
「認証」をクリックします。

▼認証完了ダイアログ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/5d2fef9a-312f-832c-fa31-3674d245611f.png)

ログインが成功すると、必要な証明書が ```/root/.cloudflared/cert.pem``` に保存されます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/154ea638-ece2-2dca-7e33-716a77f9966d.png)



## 設定ファイル(config.yaml)

```/root/.cloudflared/config.yaml``` にYAML形式で設定ファイルを記述します。最低限の記述は以下の項目になります。

```
hostname: 「Add an applications」画面で設定したApplication URLのホスト部分
url: 公開するNode-REDのローカルURL 
logfile: 動作ログを保存するファイルパス
```

従前の設定では、例えばこんな感じです。

```
hostname: editor.nrcf.xyz
url: http://localhost:1880
logfile: /var/log/cloudflared.log
```

## トンネル接続テスト

```
sudo cloudflared tunnel 
```



```https://app名.ドメイン/admin``` にアクセスすることでFlowEditorのログイン認証画面が表示されます。（設定した認証ドメインxxxxx.cloudflare.comに転送されます）

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/de105652-b336-393c-1e15-995357575324.png)

Email欄に、Policy画面で設定したメールアドレスを入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/5cb07cf7-0ad9-924e-388e-f23a1eefe850.png)

「Send me a code」をクリックすると、6桁のPINが含まれたメールが送信されますので、遷移先に入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/7daaa915-40f5-31c2-9609-46e6872e80f0.png)

「Sign in」をクリックすると、Node-REDのログイン画面が表示されれば設定は完了です。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/ab381e07-770d-e306-7372-2dac8f7d59bb.png)

[FlowEditorのログイン画面設定（推奨）](#floweditorのログイン画面設定推奨)で設定したユーザ名、パスワードでNode-REDにログインし、Node-REDの一通りの動作を確認します。

確認が終わったら、Ctrl + c でcloudflaredを終了します。


## cloudflaredのサービス化
このままではcloudflaredを終了させてたら接続が切れてしまいますので、Node-REDサーバ起動時に自動でcloudflaredが起動するようにサービス化する必要があります。

### Linux（Raspberry Pi含む）の場合

```
sudo cloudflared service install
```

で、```/root/.cloudflared```に記載したcert.pem/config.yamlを ```/etc/cloudflared```に複製して、OS固有のサービス定義(systemdなど)を設定してくれます。

サービス設定後、cloudflaredを手動起動する場合は

```
sudo systemctl start cloudflared.service
```
となります。

システム起動時に、systemdで起動時に自動起動するには

```
sudo systemctl enable cloudflared.service
```

でサービスの自動起動を有効にできます。

### macOSの場合
Linuxと同様に

```
sudo cloudflared service install
```

で設定されるそうです（が持ってないのでわかりません）

詳しくは、[公式ドキュメント](https://developers.cloudflare.com/argo-tunnel/run-tunnel/run-as-service#macos)を参照してください

### Windowsの場合
https://developers.cloudflare.com/argo-tunnel/run-tunnel/run-as-service#windows
に記載されていますので参照してください。


## cloudflaredのログローテート設定
前述の設定で、ログは```/var/log/cloudflared.log```に出力されます。長期間の稼働でログがあふれてdisk fullになるのを防ぐために、ログローテーションの設定を実施します。たとえばlinuxであれば以下の手順です。

- ```/etc/logrotate.d/cloudflare``` を以下のように記述 （毎日ログをローテートして、10世代前まで圧縮して保持する設定）

```
/var/log/cloudflared.log
{
        rotate 10
        daily
        missingok
        notifempty
        compress
        delaycompress
}
```



ここまでの設定で、Node-RED全体をメール認証にてインターネットへ公開できました。


# 応用

## 認証について

### 他のユーザのメールアドレスでもログインできるようにしたい
ダッシュボードのApplicationsで対象のアプリを選んで、Rulesタブ内のConfigure a ruleでルールにメールを追加することで、他のユーザのメールアドレスを追加できます。

▼ACCESS→Applicatios→アプリ内のRulesタブ画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/4951d69b-867d-79c6-735f-661c82b47ea8.png)

また、「Emails ending in」を指定することで、特定のドメインのメールアドレスで認証することもできます。
▼メールドメイン認証
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/0ee057fb-993d-038d-fac1-96a746c15288.png)

### 認証中ユーザの一覧と無効化

現在認証中のユーザは、ダッシュボードのLOGS→User画面に表示され、「Revoke session」で現在のセッションの認証を無効化することができます。（再度メールによるPIN認証が必要となる）

▼LOGS-User画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/e437a9cd-e860-f4c8-20e5-a1229efc2ee4.png)

一度認証したら、セッション維持期間は再認証不要になります。認証時間は、Application画面のOverview画面で変更できます。デフォルトは24時間です。No duration, expires immediatelyを選択すると、アクセス毎に認証が必要になります。

▼セッション認証期間の設定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/7e976433-65c5-8b25-20b1-8ca304faac64.png)


## Node-REDのダッシュボードは認証なしでアクセスしたい
[node-red-dashboard](https://flows.nodered.org/node/node-red-dashboard)で作成したダッシュボードは```https://localhost:1880/ui``` でアクセスできます。ここまでの設定により ```https://アプリホスト名/ui```でアクセスできますが、FlowEditor同様、メールのOne-Time PINの認証が必要になります。

ダッシュボードは認証なしでアクセスさせたい場合は、ダッシュボードを別のアプリケーションとして追加し、そちらは認証なしにすることにより、ダッシュボードだけインターネットに公開することができます。

ACCESS→Applicationsのアプリケーション一覧画面からアプリケーションを追加できます。

▼アプリケーション一覧画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/f5fe7861-ab5f-5d25-d704-b0a11298e324.png)

右上の「Add an application」をクリックします。

▼タイプ選択画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/d8b8b106-1988-b03c-ce49-9bf90b7f382f.png)
「Self-hosted」の「Select」をクリックします。

▼アプリ設定画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/2b2a8257-6eaf-ba8e-5e70-ac2e9ff2bd6e.png)

Application nameは分かりやすい名前を付けます。
Session Durationは認証なしなので「No duration,expires immediately」を選択します。Applicaion domainは、ホスト名の後に「ui」を入力します。（node-red-dashboardの場合、アプリの内部URIはすべて```ホスト名/ui```のあとのパラメータなので「ui/」でなくてもいいようです）
Identity providersは、認証なしですがそのままにしておきます。

▼アプリ設定画面-設定例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/087de78a-c05c-6037-993b-d172b4cabbf8.png)

「Next」をクリックします。

▼Add rules画面（初期設定時は「Set up a Policy」となっていた画面）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/88f394d4-8359-bd3e-fdb7-745e061f841d.png)

Rule nameは認証なしなので「no auth」とでも書きます。Rule actionは認証なしなので「Bypass」を選択します。Configure a rule欄のIncludeに「Everyone」とすることで、アクセスしてきた全員に認証なしの設定になります。

▼Add rules画面-認証なし設定例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/1dd0cc06-1b75-0cb9-d570-8715bc634ea8.png)

「Next」をクリックします。

▼Applicaiton setup画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/24d8e3ac-6dc9-c974-655a-e2030222986e.png)

アプリケーションへのアクセスに細かい設定ができます。（HTTPリクエストヘッダによる認証、Cookie設定など）
今回は設定せず、「Add applicaiton」をクリックします。

▼アプリケーション一覧画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/87018ee9-1aa5-e5de-9301-eb2f1b485367.png)

一旦、LOGS→Userで認証中のセッションをRevokeして、認証なしの状態にしてから、
```https://app名.ドメイン/ui``` にアクセスすることで、ダッシュボードに認証なしでアクセスできることが確認できます。

## http-inノードのAPIも認証なしにする
Node-REDのhttp-inノードを使って、APIを作成することがありますが、前項同様にApplication設定で「Bypass」を指定することで認証なしでアクセスを許可することができます。個別のhttp-inのURLごとにApplicationを指定することもできますが、Application Configuration指定の時にパスの最後に「/」をつけることで、そのパスを含むAPIをまとめて指定することができます。

▼Application設定例-「api/」と指定することで、/api/を含むhttp-inをすべて認証なしにする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/f3a3a3b4-b2f4-d972-3cad-acba3e103bde.png)

なお、ルールを変更する場合は、変更後、設定を反映するために、必ず右上の「Save application」をクリックする必要があります。

▼/api/をパスに含むhttp-inノードの利用例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/cbdea675-2c2f-efc9-2b05-cdda0d2211fe.png)

## 認証ルールを追加する
アプリケーション設定画面のRules設定で、これまではEmails/Emails ending in/Everyoneを使いましたが、ここにはほかのルールを設定することもできます。

- **Country**: アクセス元ソースIPから国を識別して認証
- **Emails**: メールアドレス（既出）
- **Emails ending in**: メールのドメイン（既出）
- **Access groups**: Cloudflare for Teamsに設定したユーザのグループによる認証
- **IP ranges**: ソースIPアドレスレンジで設定
- **Everyone**: 認証なし（既出）
- **Valid Certificate**: クライアント証明書による認証（無料プランだと使えない）
- **Common name**: クライアント証明書及びTLSのコモンネーム(FQDN)による認証（無料プランだと使えない）
- **Service Token**: JSON Web Token (JWT) による認証（無料プランだと使えない）
- **Any Access Service Token**: JSON Web Token (JWT) による認証（無料プランだと使えない）

無料プランでtokenによる認証が使えないのが残念です。例えばソースIPアドレス範囲からのアクセスを許可する場合は、以下の設定になります。

▼Application→Rules設定画面
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/027f5557-250b-fbbb-f2fb-10a50782046c.png)

Rule actionを「Service Auth」にする必要があります。401 Responseにチェックを入れることで認証失敗時に401ステータスを返すことができます。

また、対象IPアドレス(IPv4/IPv6)は複数記述できますが、CIDR形式（IPv4の場合は、xxx.xxx.xxx.xxx/xx）形式で指定することでIPレンジで指定することができます。




## 認証IDプロバイダを追加する

Cloudflare for Teamsでは、すでに設定したOne-time PIN以外に、以下の認証IDプロバイダに対応しています。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/c49d4407-695e-bb8a-f87d-83172bdf8fa4.png)

IDプロバイダと別途契約が必要だったり、サービスが無料で使えなかったり、連携アプリの構築が必要だったりと、簡単に試すのは難しいので、ここでは紹介しません。

https://developers.cloudflare.com/access/authentication/configuring-identity-providers
に設定方法が公開されているので、対応する認証IDプロバイダにアカウントがあり認証用のアプリをお持ちの方は参考にしてください。

# その他

## Cloudflare経由で使えないノード
[設定ファイル(config.yaml)](#設定ファイルconfigyaml)で設定したconfig.yamlでは、リモートアクセスで透過するプロトコルはHTTP/HTTPSのみです。Node-REDに標準で導入されるノードのうち、TCP-inノード、UDP-inノードは、このままの設定では使うことはできません。また、https://flows.nodered.org/ から導入できるカスタムノードでも、Node-REDサーバがhttp以外のサーバになるものは同様に使えません。

TCPノードについては、
https://developers.cloudflare.com/access/protocols-and-connections/arbitrary-tcp
にてTCPポートの転送方法が公開されているので、別途config.yamlの記述を追加することで使えるようになるかもしれません。UDPの透過はサポートされていないようです。

## Websocketノードの利用

Websocketノードについては、通信をhttpsで実施するので、対象Node-REDサーバが「待ち受け」の場合はパスを認証なしの設定にすることで使うことができます。例えば、URLが ```wss://アプリドメイン/ws/``` となる場合、```/ws/``` を認証なしの設定にすると外部からWebsocket接続することができます。

▼Node-REDのWebsocket待ち受けFlowの例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/3ef5f2d2-e3d1-c335-89c1-5f212999818e.png)

▼上記FlowのWebsocketを透過される設定例
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/25932/9e0659f5-c9c6-aaf0-da3b-8a3428182b12.png)

ただし、認証なしで外部からのWebsocket通信は、セキュリティに注意が必要です。

また、IPアドレスが常時変化する環境のNode-REDサーバでWebsocket待ち受けする場合、サーバからの接続経路変化時にWebsocket接続が切断され、自動再接続されるものの、Websocket inノードのステータスの「接続数」がどんどん増えていってしまいます...

### ファイルディスプリタ上限にひっかかる問題(12/14追記）
Websocketが正常に切断されない場合、OSのsocketをcloseしないまま新しいsocketを使ってしまうため、Cloudflaredのプロセスのファイルディスクリプタ上限を使い切ってしまい、```/var/log/cloudflared.log```に

```
 HTTP request error: dial tcp 127.0.0.1:1880: socket: too many open files
```
を大量に出力して、cloudflaredの接続が切れてしまいます。（だいたい3時間でデフォルトのファイルディスプリタ接続数 1024を使い果たしてしまうようです）

IPアドレスが常時変化する環境でどうしてもNode-REDサーバへWebsocketの接続をしたい場合は、cloudflaredが利用できるファイルディスプリタ上限を増やすため、以下の設定が可能です。

- ```sudo mkdir /etc/systemd/system/cloudflared.service.d``` 
- ```/etc/systemd/system/cloudflared.service.d/over.conf``` に以下の内容を記載

```
[Service]
LimitNOFILE=65536
```

- ```sudo systemctl daemon-reload```を実行して上記設定を有効に
- cloudflaredを再起動 （```sudo systemctl restart cloudflared```) 

それでも定期的な再起動が必要（3時間が数日になるだけ）になりますので、外部からWebsocketの常時接続を安定的に実施するのは難しいかもしれません...



# まとめ
Cloudflare for Teamsを使うことで、グローバルIPアドレスを持たないNode-REDサーバをインターネットに安全に公開することができるようになります。無料サービスだとクライアント証明書による認証ができないとか制約はあるにはありますが、無料サービスでも接続しっぱなしでも安定して固定URLでNode-REDサーバを公開することができますので、ぜひ活用いただければと思います。