Cloudflareで自宅のRaspberry Piを呼び出す


#目的
手元のRaspberry Pi zeroをLINEのMessaging APIから呼び出すため、ローカル環境をWebhook URLに登録する話題です。LINE Messaging APIの使い方はここでは触れません。
[スマホの誘惑を断ち切る箱](https://qiita.com/urakarin/items/12994521d7263d3013d6)作成の際に利用しました。

#前提
ローカル環境を固定URLとして呼び出せるようにします。自前でDNS設定可能なドメインを保持していることを前提とします。

当初、目的を達成するために彷徨っていたところ、"[Cloudflare の ngrok的なサービスがあるらしい](https://qiita.com/youtoy/items/3d312552f08a729bb5bb)"を見つけました。しかし、その通りやってみてもできません(2021/12現在)。Cloudflare側の挙動に変更があったのか、一時的なURLとして公開することができません（私の調査不足なだけかもしれませんけど）。

自前ドメインのサブドメインとして公開するのは可能でしたので、今回はその方法を紹介します。
ngrokは無償範囲では公開可能な持続時間に制限があるようなので却下です。

# 実現方法
[Cloudflare](https://dash.cloudflare.com/login)のArgo Tunnelというサービスを無償範囲で利用し、サブドメインをローカル環境に向けます。例えば、brabrabra.com を自分で所有しているとして rpi.brabrabra.com を指定すると、自宅ローカル環境のRaspberry Pi zeroが呼ばれるようになります。本来はWAF提供用のサービスですので、ある意味目的外利用ですが簡単にローカル環境を公開できます。

## Raspberry Pi zeroでは正しく動かない(解決済み)
本題とは少しずれますが、ARMv6アーキテクチャを採用しているデバイスを公開しようとする場合に課題があります。Cloudflareが提供するバイナリがARMv7アーキテクチャを期待しているためです。ARMv6ではSegFaultを起こし正しく動作しないようです。

解決策はいくつかあります。
  　1. Version 2018.7.2を使用する
  　2. ARMv6用に自分でソースからビルドし直す→[参考](https://ilayk.com/2021/05/23/Cloudflared-Argo-Tunnel-on-a-Raspberry-Pi-Zero)
  　3. ARMv6用にビルドしてくれている親切な方のサイトからDLする→[GitHub上での議論](https://github.com/cloudflare/cloudflared/issues/38)
なるべく手間をかけたくないので、3を採用します。
世の中には[親切な人](https://www.reddit.com/r/pihole/comments/9m6u12/cloudflared_for_raspberry_pi_a_zero_and_zero_w/)がいて、ARMv6用に都度ビルドして[公開](https://hobin.ca/cloudflared/)してくれています。
Thanks a lot.

## CloudflaredのInstall
最新のdebを[ダウンロード](https://hobin.ca/cloudflared/)してRaspberry Pi zeroへインストールします。(記録時点での最新は Version 2021.12.4)
参考：[Installing cloudflared](https://docs.pi-hole.net/guides/dns/cloudflared/)
![ARMv6_r2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82958/12b8688f-2240-3e6c-e161-9d9e1ff28e6c.png)


```code:bash
$ wget https://hobin.ca/cloudflared/releases/2021.12.4/cloudflared_2021.12.4_arm.deb
$ sudo apt-get install ./cloudflared_2021.12.4_arm.deb
$ cloudflared -v
```

どこにインストールされたかと思いきや dpkg -L cloudflared してみると、なんと/にいます。
んー。引数が足りてないかもしれません。
まぁいいや。
とは言え、一応パスが通っているところにもリンクを置いておきます。

```code:bash
$ sudo ln -s /cloudflared /usr/local/bin/
```


# Cloudflareにアカウント登録

[公式のtutorial](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/tunnel-guide)によれば、自分のもつDNSへぶら下げるのが仕様のようです。
![setup_1st_tunnel_r3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82958/e419cf9c-b291-dd09-a690-d4f294989836.png)

1. [ここ](https://support.cloudflare.com/hc/en-us/articles/201720164-Creating-a-Cloudflare-account-and-adding-a-website)に従いアカウント登録を行い自分が管理するドメインを登録します。途中、自分の[webサーバ登録を求められる](https://support.cloudflare.com/hc/en-us/articles/205195708)ので入力します。(例：brabrabra.com)![create_cloudflare_account_r2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82958/e10aa9da-ca87-def2-d3ad-cc9c50018c8f.png)



2. 自前ドメインを登録している管理ページからDNSサーバのアドレスを書き換える必要があるので、現在の値から指定されたcloudflareのDNSアドレスへ変更します。(なぜこの作業が必要かはここでは説明しません。気になる方はDNSの仕組みを調べてみましょう）
![login_mydns_r2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82958/b23b4c6e-90ef-5013-8433-9de13e8eb662.png)
登録しているサービスによってUIが異なりますが、例えばこんな感じです。
![change_mydns_r3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82958/8db19438-df8f-3ec4-7280-f485174c0b0e.png)

3. DNS (name server)の設定完了
![setup_dns_r3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82958/d366ad2a-ba4f-6999-932d-a05ac624d9b2.png)
次のようなメールが送信されてきます。
![change_dns_r2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82958/72a8f3a1-054e-aba7-cdda-808589e2020a.png)

4. DNSの設定が世の中に行き渡るためしばし待ちます。数時間から場合によっては1日程度かかるかもしれません。


# Cloudflaredの設定
ログインします。

```code:bash
  cloudflared tunnel login
```
DNSの反映が行き届いていないと下記のようにloginが成功しません。
![console_login_fail_r2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82958/f2e93ebf-392e-4ead-1e13-b900ec206cd8.png)
私の場合、3時間ほど待ったのちに成功しました。
![console_login_success_r2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82958/96b3952f-336a-90fa-2992-366077f32281.png)


loginが成功する場合、コンソールに表示されるURLにアクセスすると下のような画面が表示されます。これでArgo Tunnelが使えるようになったようになりました。
![argo_tunnel_r3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82958/f4d475fb-162f-9cb7-7179-5b28c905fcdf.png)


# 自宅のRaspberry Pi zero環境との紐付け
以下、Raspberry Pi zeroのコンソール上で実行する内容です。

## サブドメイン名の登録
紐付け先のサブドメイン名をsmartlockとしたい場合、次のコマンドを打ちます。

```code:base
 cloudflared tunnel create smartlock
```
下記のようにconfig用のjsonファイルとidが得られます。これらは後の設定で利用します。
![smartlock_r2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82958/ed00b24d-49da-0189-f0a0-3fb82ef6d5dd.png)

次のコマンドでサブドメインの登録状況を確認できます。

```code:bash
 cloudflared tunnel list
```
リスト表示されます。
![smartlock_list_r2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82958/acbb888a-cf8b-c1d7-6750-f8e6b7bbcb08.png)

## configuration fileの作成
config.ymlファイルを作成します。

```code:bash
 vi ~/.cloudflared/config.yml
```
内容は下記です。xxxの部分は先のidおよびjsonファイル名です。

```code:bash
 url: http://localhost:1880
 tunnel: xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
 credentials-file: /root/.cloudflared/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.json
```
ここではNode-REDの1880ポートを公開しています。世界中からアクセスできる状態になるので公開サービス（ここではNode-RED）の認証などセキュリティは別途設定する必要があります。

## トンネルの登録
ローカル環境を安全にサブドメインへ接続する経路をトンネルと呼びます。
トンネルを登録します。

```code:bash
 cloudflared tunnel route dns smartlock smartlock
```
これでトンネルの登録ができました。
![smartlock_subdomain_success_r2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82958/24bf9548-225b-42b7-a094-ad3bca2ee3d6.png)

## トンネルの稼働開始

```code:bash
 cloudflared tunnel run smartlock
```

トンネルの稼働状況は次のコマンドで確認できます。

```code:bash
 cloudflared tunnel info smartlock
```
うまく作られているようです。
![smartlock_check_r2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82958/23e87268-203e-6cd8-0adc-3490b5b15187.png)

これで完了です！
自前ドメインがbrabrabra.comだった場合、
https://smartlock.brabrabra.com 
へアクセスするとRaspbrerry Pi zeroの1880へフォワードされるようになります。
すばらしい。

# 永続化
[ここ](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/run-tunnel/run-as-service)を参考に、Raspberry Pi zeroの起動とともにサービスとして動作させます。
config.ymlをrootから見えるところに置きます。

```code:bash
 sudo ln -s ~/.cloudflared/config.yml /etc/cloudflared/
 sudo cloudflared service install
 sudo systemctl enable cloudflared
```

# Cloudflareのダッシュボード
Cloudflareにログインすると[ダッシュボード](https://dash.cloudflare.com/login)からアクセス状況を確認できます。
![status_r2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/82958/eeea76e0-60e9-4aee-4bb8-ea1379354837.png)


おわり。