Cloudflare Zero TrustとRaspberry Piを使って自宅のPCをクラウド化する

2022/12/04に公開

この記事はEEIC Advent Calendar 2022 4 日目の記事として作成しました

はじめに

こんにちは。EEIC2022 の hososuke です。最近自作 PC をしたんですが、せっかく組んだ性能のいい PC を大学にいるときや、実家に帰省したときでも使えるようにしたいと思い、色々と試行錯誤したことをこの記事に書きたいと思います。
記事のタイトルを「自宅の PC をクラウド化する」なんて大げさに書いてしまいましたが具体的に行ったことは次の 3 つになります。

  • 外出先からも自宅の PC に SSH 接続できるようにする
  • 自宅の PC を遠隔で起動できるようにする
  • 自宅の PC の状態(起動しているかどうか)を監視する

若干タイトル詐欺気味になってしまうのですが、もし興味があれば最後までお付き合いいただければと思います笑

概説

以下に、ネットワークの概略図を載せます。

zerotrust_architecture

まず、外出先から自宅ネットワークの接続に関してですが、cloudflare zero trustというサービスを利用します。このサービスはcloudflare tunnelcloudflare accessという2つのサービスから構成されていて、詳しくは後ほど説明したいと思います。

また、Raspberry Piの役割と常時起動している理由についてですが、Wake On Lanという機能を用いてデスクトップPCを起動するための足がかりとしたいのと、デスクトップの起動状態を常に監視するためです。

これから各部分について詳しく説明したいと思います。

なぜ外出先から自宅のネットワークにアクセスするのが難しいのか

SSHだろうがhttpsだろうがなんだろうが、まずは自宅のネットワークにアクセスしないと何もできないのですが、外出先から自宅のネットワークにアクセスするには少し工夫が必要となります。
主な問題点としては次のようなものがあります。

  • 自宅のネットワークに固定ipが割り振られていない
  • NATの問題
  • セキュリティの問題

固定ip・NATに関する問題

皆さんご存知の方も多いと思いますが、TCP/IPで通信をするときにはipアドレスとポート番号を指定して通信すると思います。ブラウザでgoogle.comのドメイン名を用いて通信を行うときでもDNSによってドメイン名がipアドレスとして解決され、通信を行うことができるようになっています。
2022年現在最も広く普及しているのはIPv4というプロトコルであり、8.8.8.8のような形式で8bitの数字4つを用いてアドレスを指定しています。

しかしながら、このIPv4には問題があり、それは最大でも2^{32}個(約40億)のアドレスしか利用できないということです。そういう問題があるためIPv4ではサーバー以外の端末(パソコンやスマホ等)には固定のipアドレスを割り当てず、また、ルータを介するときにNAT, NAPT(Network Address (Port) Translation)によりグローバルipとローカルipを変換することにより、どうにか限られたアドレス空間でやりくりしています。

PCをクライアントとして使う分にはこれでもほとんど困ることはないのですが、外出先からSSHをするなど、サーバー的な使い方をしようとすると色々と問題が生じてきます。

セキュリティの問題

仮に、固定ipの取得やDynamic DNSなどを利用することで上記の問題を解決できたとしても、今度は様々なセキュリティの問題が生じます。自宅のipを公開するというのは攻撃のリスクが上がるということでもあるので、セキュリティの観点からはあまり望ましくありません。

どのようにしてネットワークを公開するか

外部から自宅ネットワークにアクセスする方法として次の3つを検討しました。

ngrokとcloudflare tunnelはどちらもPCのポートを公開するwebサービスです。両者の違いとしてはngrokのほうが比較的手軽に設定できる一方、cloudflare tunnelは一緒にcloudflareから提供されているcloudflare accessを用いることで認証の設定がかんたんにできるといった違いがあります。

今回はSSH以外でも利用できるようにしたかったのと、認証もつけたかったのでcloudflare tunnelを利用する方法を選択しました。

Wake On Lanについて

遠隔でPCを起動する方法に関してですが、Wake On Lanというものを利用します。これは起動したいPCのMACアドレスなどを含むMagick Packetをネットワーク内にブロードキャストすることで、対応するPCを起動することができるというものです。
注意点としては、どのPC(マザーボード)でも対応しているわけではないので気をつけてください。

また、ラズパイからPCが起動しているか確認もできるようにしたいので、それについては単純にpingでPCとの疎通を見ることで確認しています。

実際に構築してみる

次に、実際に環境を構築していこうと思います。
かんたんに説明をしていこうと思いますが、公式のドキュメントだったり、Zennとかの他の記事が詳しかったりするのでそちらも参考にするといいです。

https://developers.cloudflare.com/cloudflare-one/

用意するもの

デスクトップPC以外には次のものを用意する必要があります。

  • Cloudflareアカウント
    • 今回使うサービスの範囲内では料金はかかりません
  • Raspberry Pi
    • 今回は3Bを利用しましたが、あまり性能は必要ないのでもっと古いのでも大丈夫かもしれないです
    • 自分は今までラズパイを持っていなかったのでメルカリで中古で購入しました(型落ちなのに8000円もした)
  • ドメイン
    • google domainsとかお名前.comとかで取ったやつで大丈夫です
    • あとでcloudflareのdnsに登録する必要があるのでcloudflare registerとかで取っちゃうと楽かも
    • .comとか.netなら$10/yearくらいで取れます

0. dns登録

まず、cloudflareに手持ちのdnsを登録しますダッシュボードにWebサイトって書かれたタブがあると思うので、そこから自分が持っているドメインを登録します。

dash-home

ここから登録すると利用できるdnsサーバ一覧みたいなのが出てくると思うので、これらのサーバーをドメインを購入したサイトで利用するdnsサーバとして登録します。

1. デスクトップの設定

1.1 tunnelの設定

まず、デスクトップPCの方のtunnelを設定していきます。

他の記事を見るとCLIで設定をしている記事が多いのですが、ウェブ上のダッシュボードで設定を行ったほうが簡単だったのでそちらがおすすめです。

https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/install-and-setup/tunnel-guide/remote/

https://developers.cloudflare.com/cloudflare-one/connections/connect-apps/use_cases/ssh/

今回はssh接続なので公式ドキュメントの該当箇所は上の2つです。

日本語記事だと次の記事がわかりやすかったので参考にしてください。

https://zenn.dev/inkohx/articles/cloudflare-tunnel-ssh

自分がハマったポイントとしては、利用するサブドメインとしてxxx.yyy.example.comのように2つ以上のサブドメインが連結する形だとsshではうまく行かないっぽかったです。(xxx.example.comのような形である必要がある)

https://community.cloudflare.com/t/tls-error-while-using-tunnel-for-ssh-and-other-services/350509/10

1.2 ネットワークに関する設定

デスクトップPCの電源の投入にはWake On Lanを利用しますが、この機能はデフォルトではオンになっていないことがあるのでUEFIの画面を開いて設定から有効化しておきます。

また、起動後にはラズパイからpingで疎通確認をしたいので、DHCPを無効果してローカルIPを固定しておくといいです。

2. Raspberry Piの設定

2.1 Wake On Lanを行うためのスクリプトの実装

Wake On Lanのmagic packetを送信するコマンドなどがあるので、それをラズパイにインストールするなどしてラズパイからPCの電源を起動できるようにします。

また、外部のネットワークから電源を入れることができるようにするには、そのコマンドを遠隔で呼び出せるようにしなければ行けないので、何らかの方法で簡単に呼び出せるようにするといいです。

自分はREST APIでwakeonlanコマンドを呼び出せるようにし、ついでにSaaSのダッシュボード風の画面をReactで作ってみました。

https://github.com/so298/home-cloud-backend

https://github.com/so298/home-cloud-dashboard

mydash

2.2 tunnelの設定

実装したREST APIを外部ネットワークから叩けるようにするため、ラズパイの方もcloudflare tunnelでポートを公開します。

ここはデスクトップの方のtunnelの作成とほぼ同じなので割愛します。

2.3 accessの設定

公開したAPIですが、そのままだと誰でもアクセスすることができ、自分のPCの電源を入れ放題ということになってしまっているので、それを防ぐためにcloudflare accessで認証を導入します。

https://developers.cloudflare.com/cloudflare-one/applications/configure-apps/self-hosted-apps/

このあたりのドキュメントが参考になります。

完成

これで、外部からの電源投入、SSH接続の両方が利用できるようになりました。

最後に

今回紹介したcloudflare zero trustですが、高いセキュリティを維持しながら簡単にネットワークを公開できることからIoTとかとかなり相性がいいのではないかと思います。 公式のドキュメントには他の様々なユースケースも載っているのでそちらも参考にしてみると良さそうです。

Discussion