Cloudflare Tunnelを使ってAndroidに立てたWebサイトを外部公開できるか検証してみた

## はじめに

[Cloudflare Tunnel](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/)はローカルに立てたサーバーを外部からアクセスできるようにするトンネリングサービスです。同じようなサービスに[ngrok](https://ngrok.com/)などがあります。今回はAndroidのTermuxに立てた.NETサーバーをCloudflare Tunnelを使って外部に公開できるか検証してみます。

## Cloudflare Tunnelがどのように動作するか

Cloudflare Tunnelは、[cloudflared](https://github.com/cloudflare/cloudflared)をインストールすることで動作します。cloudflaredは、近くのCloudflareデータセンターに対して長期間の接続を作ります。Cloudflareがドメインへのリクエストを受信すると、接続しているデータセンターにリクエストを中継します。中継されたリクエストは、cloudflaredとデータセンターの接続を逆方向に辿って、cloudflaredの背後にあるローカルサービスにプロキシされます。

![handshake.jpeg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263052/84eccbf9-4e03-6d8e-616e-ef63e665184e.jpeg)
出典：[Cloudflare Tunnel · Cloudflare Zero Trust docs](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/)

cloudfalredからCloudflareデータセンターに対する接続は、アウトバウンド専用接続です。これは、接続の起点がcloudflaredからということです。オリジンサーバーは着信トラフィックを許可する必要がありませんし、パブリックに到達可能なIPアドレスも必要ありません。


今回のケースでは、Androidにcloudflaredをインストールします。ドメインへのリクエストをCloudflareがcloudflaredまで中継してくれるので、パブリックに到達可能なIPアドレスを持たないAndroid端末のローカルサービスを外部公開できるようになります。

**参考**
[Cloudflare Tunnel · Cloudflare Zero Trust docs](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/)
[Highly available and highly scalable Cloudflare tunnels](https://blog.cloudflare.com/highly-available-and-highly-scalable-cloudflare-tunnels/)
[Tunnel availability and failover · Cloudflare Zero Trust docs](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/deploy-cloudflared-replicas/)
[Introducing post-quantum Cloudflare Tunnel](https://blog.cloudflare.com/post-quantum-tunnel/)
[Getting Cloudflare Tunnels to connect to the Cloudflare Network with QUIC](https://blog.cloudflare.com/getting-cloudflare-tunnels-to-connect-to-the-cloudflare-network-with-quic/)

## 事前準備

事前に以下の手順を進めてください。
次のセクションからは事前準備が完了している前提で話を進めます。

- [AndroidでASP.NET Coreを動かす](https://qiita.com/karuakun/items/c8439d0aadb2e798cf08)を参考にローカルで.NETサーバーを立てられる状態にします。
- [Quick Tunnels](https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/do-more-with-tunnels/trycloudflare/)という開発用トンネルを使って公開するのでさらっと目を通しておいてください。

## cloudflaredをインストールする

TermuxでUbuntuにログインします。

```
$ proot-distro login ubuntu
```

cloudflaredをインストールします。

```
$ wget -q https://github.com/cloudflare/cloudflared/releases/latest/download/cloudflared-linux-arm64.deb
$ dpkg -i cloudflared-linux-arm64.deb
```

cloudflaredがインストールされていることを確認します。

```
$ cloudflared version
cloudflared version 2022.11.0 (built 2022-11-21-1100 UTC)
```

インストールが確認できたら不要なパッケージは削除しておきます。

```
$ rm cloudflared-linux-arm64.deb
```

## .NETサーバーを立てる

トンネルを開ける前に、先に外部公開するサーバーを立てておきます。
適当なプロジェクトを作成します。

```
$ dotnet new mvc -o SampleApp
```

.NETサーバーを起動します。
.NET側がhttpsだとうまくいかないため、urlsオプションでhttpを指定しています。

```
$ dotnet run --urls http://*:5000
Building...
info: Microsoft.Hosting.Lifetime[14]
      Now listening on: http://[::]:5000
info: Microsoft.Hosting.Lifetime[0]
      Application started. Press Ctrl+C to shut down.
info: Microsoft.Hosting.Lifetime[0]
      Hosting environment: Development
info: Microsoft.Hosting.Lifetime[0]
      Content root path: /root/apps/SampleApp/
```

Webブラウザで確認します。

<img style="text-align: center"width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263052/06362c58-da31-0a70-b16e-b310aa1083e2.png">

## トンネルを開ける

ローカルサーバーが立ち上がったので、いよいよトンネルを開けます。
.NETサーバーとは別のセッションを立ち上げます。

<img style="text-align: center"width="300" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263052/7b3dac66-26dd-3adf-d679-c77ada3d0636.png">

忘れずにubuntuにログインします。

```
$ proot-distro login ubuntu
```

ローカルで立ち上がっている.NETサーバーのurlを指定してトンネルを開けます。
エラーが出ることがありますが、接続のリトライを待てば問題ありません。

```
$ cloudflared tunnel --url http://localhost:5000
2022-12-22T22:45:40Z INF Thank you for trying Cloudflare Tunnel. Doing so, without a Cloudflare account, is a quick way to experiment and try it out. However, be aware that these account-less Tunnels have no uptime guarantee. If you intend to use Tunnels in production you should use a pre-created named tunnel by following: https://developers.cloudflare.com/cloudflare-one/connections/connect-apps
2022-12-22T22:45:40Z INF Requesting new quick Tunnel on trycloudflare.com...
2022-12-22T22:45:43Z INF +--------------------------------------------------------------------------------------------+
2022-12-22T22:45:43Z INF |  Your quick Tunnel has been created! Visit it at (it may take some time to be reachable):  |
2022-12-22T22:45:43Z INF |  https://castle-fabric-binding-achieving.trycloudflare.com                                 |
2022-12-22T22:45:43Z INF +--------------------------------------------------------------------------------------------+
2022-12-22T22:45:43Z INF Cannot determine default configuration path. No file [config.yml config.yaml] in [~/.cloudflared ~/.cloudflare-warp ~/cloudflare-warp /etc/cloudflared /usr/local/etc/cloudflared]
2022-12-22T22:45:43Z INF Version 2022.11.0
2022-12-22T22:45:43Z INF GOOS: linux, GOVersion: go1.19.3, GoArch: arm64
2022-12-22T22:45:43Z INF Settings: map[protocol:quic url:http://localhost:5000]
2022-12-22T22:45:43Z INF cloudflared will not automatically update if installed by a package manager.
2022-12-22T22:45:43Z INF Generated Connector ID: 031733ef-3baa-4e20-a2d7-b5f897edff07
2022-12-22T22:45:43Z INF Initial protocol quic
2022-12-22T22:45:43Z INF ICMP proxy will use 100.69.103.63 as source for IPv4
2022-12-22T22:45:43Z INF ICMP proxy will use 2001:268:9817:6236:748d:6633:977d:27a9 in zone rmnet_data1 as source for IPv6
2022-12-22T22:45:43Z WRN The user running cloudflared process has a GID (group ID) that is not within ping_group_range. You might need to add that user to a group within that range, or instead update the range to encompass a group the user is already in by modifying /proc/sys/net/ipv4/ping_group_range. Otherwise cloudflared will not be able to ping this network error="open /proc/sys/net/ipv4/ping_group_range: permission denied"
2022-12-22T22:45:43Z INF Starting metrics server on 127.0.0.1:39681/metrics
2022-12-22T22:45:43Z WRN Your version 2022.11.0 is outdated. We recommend upgrading it to 2022.12.1
2022-12-22T22:45:43Z ERR Failed to serve quic connection error="Unauthorized: Failed to get tunnel" connIndex=0 ip=198.41.200.53
2022-12-22T22:45:43Z ERR Register tunnel error from server side error="Unauthorized: Failed to get tunnel" connIndex=0 ip=198.41.200.53
2022-12-22T22:45:44Z INF Retrying connection in up to 2s connIndex=0 ip=198.41.200.53
2022-12-22T22:45:45Z ERR Failed to serve quic connection error="Unauthorized: Failed to get tunnel" connIndex=0 ip=198.41.200.53
2022-12-22T22:45:45Z ERR Register tunnel error from server side error="Unauthorized: Failed to get tunnel" connIndex=0 ip=198.41.200.53
2022-12-22T22:45:45Z INF Retrying connection in up to 4s connIndex=0 ip=198.41.200.53
2022-12-22T22:45:47Z ERR Failed to serve quic connection error="Unauthorized: Failed to get tunnel" connIndex=0 ip=198.41.200.53
2022-12-22T22:45:47Z ERR Register tunnel error from server side error="Unauthorized: Failed to get tunnel" connIndex=0 ip=198.41.200.53
2022-12-22T22:45:47Z INF Retrying connection in up to 8s connIndex=0 ip=198.41.200.53
2022-12-22T22:45:54Z ERR Failed to serve quic connection error="Unauthorized: Failed to get tunnel" connIndex=0 ip=198.41.200.53
2022-12-22T22:45:54Z ERR Register tunnel error from server side error="Unauthorized: Failed to get tunnel" connIndex=0 ip=198.41.200.53
2022-12-22T22:45:54Z INF Retrying connection in up to 16s connIndex=0 ip=198.41.200.53
2022-12-22T22:45:57Z ERR Failed to serve quic connection error="Unauthorized: Failed to get tunnel" connIndex=0 ip=198.41.200.53
2022-12-22T22:45:57Z ERR Register tunnel error from server side error="Unauthorized: Failed to get tunnel" connIndex=0 ip=198.41.200.53
2022-12-22T22:45:57Z INF Retrying connection in up to 32s connIndex=0 ip=198.41.200.53
2022-12-22T22:46:16Z INF Connection 20325584-9cc5-4ad1-b838-91547858f63f registered with protocol: quic connIndex=0 ip=198.41.200.53 location=KIX
2022-12-22T22:46:17Z INF Connection 325242b4-aa1b-473d-b3ae-9a53ca49c3dd registered with protocol: quic connIndex=1 ip=198.41.192.27 location=NRT
2022-12-22T22:46:18Z INF Connection 16d223e2-36b2-4c2e-a2ef-4a899a1ede7f registered with protocol: quic connIndex=2 ip=198.41.200.193 location=KIX
2022-12-22T22:46:19Z INF Connection 27b58ddd-c9c0-48a0-be8e-eb68e3ddcfcc registered with protocol: quic connIndex=3 ip=198.41.192.47 location=NRT
```

払い出されたURLに別端末からアクセスしてみます。

![](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/263052/f4771f15-5277-37c0-e52c-45ae24d8968a.png)

表示されました！成功です！やったー🚀

## おわりに

今回はCloudflare TunnelのQuick Tunnelsという開発用トンネルで、Androidに立てたWebサイトを外部公開してみました。Cloudflareにドメインを登録して運用すれば、アクセス権限を設定したり、Cloudflareの保護を受けられます。通信量を気にしなければ、自宅サーバーならぬポケットサーバー(?)としてちょっとしたサイトを公開するのに良いのではないでしょうか。