- 記事一覧/
ポート開放ができない環境でサーバを外部公開するための個人的ベストプラクティス
目次
はじめに #
この記事は DeNA 23 新卒 Advent Calendar 2022 の11日目の記事です。
こんにちは DeNA23 卒内定者の bigbell です。
自分は
大学の研究室でネットワークとサーバの運用・保守を担当しているのですが、ポート開放ができない環境でサーバを外部公開する必要があり、その中で得られた知見があるので、同じ悩みを抱えた人のためにも今回初めて記事を書いてみようと思います。
説明が間違っていることもあるかも知れませんがその点はご容赦ください
経緯とか #
私の研究室では後輩が 官公庁オークションで手に入れてきたラックマウントサーバ(ラックにマウントするとは言ってない)を使用して、入退室管理システムやファイルサーバ、研究で使用する自作ソフトウェアを動かしています。
最近ではAWSやGCPといったクラウドサービスがあるのに「なぜ今の時代にオンプレ環境?」と突っ込みたい人もいるかも知れませんがこれには理由があります。
実はこの環境に移る前はAWSのEC2上に無料枠でサーバを建てて、研究室内のシステムを動かしていました。
しかし、無料枠の範囲内ではサーバのスペックが足りず、自作のソフトウェアを実行するとまともにSSHすら繋がらなくなってしまう有様でした。
この問題を受けて、当初は幾らかお金が掛かるのには目をつぶって運用しようかという話にもなったのですが、「研究室内でそんなに使われていないシステムを動かすのに金銭的コストを掛けるのもどうなの?」という意見を受けて白紙になりました。
「う〜ん…運用どうしよう」と考えていた所、ちょうど後輩が官公庁オークションで上記のラックマウントサーバを手に入れてきたので、こちらを使用したオンプレ環境に移行したという形です。
直面した問題 #
サーバを手に入れて、よし!これで問題は解決!!と言いたい所でしたが、サーバを外部公開するに当たって別の問題に直面しました。
各研究室には大学側が設置している上流のルータを通してプライベートIPが振られており、基本的に自前で用意したサーバをポート開放して公開することはできないのです。
大学によっては情シスの人に頼めば良い感じにルータを設定してくれて、外部公開できる所もあるかと思いますが私の大学ではそれは厳しそうでした。
上述の問題の解決策として、よくQiitaでは ngrok (エングロック) のサービスをした方法が紹介されています。
このサービスは ngrok のサーバに対してトンネルを貼ることで、外部からの通信を中継してくれるというサービスです。
簡単に言えばリバースプロキシを楽に使えるようにしたようなもので、プライベートIPしか振られていないような環境でもインターネットにさえ繋がっていればサーバを外部に公開することができます。
ちなみに公式では以下のように説明されています
ngrokは、NATやファイアウォールに囲まれたローカルネットワークのサービスを安全なトンネルを介して公衆インターネットに公開します。ローカルウェブサイトの共有、Webhookコンシューマの構築/テストWebhook コンシューマーの構築/テスト、個人サービスのセルフホスティングなどが可能です。
このように非常に便利なサービスですが無料枠で使用する場合は以下の制限があります
- 独自のドメインを割り当てることができず毎回URLが変わってしまう
- 帯域幅と転送量にリミットがある
そこで、より低コストで利用できるサービスがないか探した所、
Cloudflare社が提供しているサービスを見つけました。
このサービスを利用すると ngrok の有料プランに該当する機能をコストを掛けずに利用できます!!
(※ただし、無料プランでは1回にアップロードできるファイルサイズは100MB以下という制限だけ存在します)
Cloudflare のサービスを使ったサーバの外部公開方法 #
アカウントの作成とCloudflareへのドメインの登録が済んでいることを前提として進めていきます。
1. cloudflared のダウンロード #
以下のURLを参照して各自の環境に合わせた最新のバイナリファイルを選択してください。
https://github.com/cloudflare/cloudflared/releases/latest/
$ wget https://github.com/cloudflare/cloudflared/releases/download/2022.10.3/cloudflared-linux-amd64
apt
や yum
等を利用してインストールすることもできますが、自動更新の機能を利用したいので、ここではバイナリファイルを直接ダウンロードしてインストールを行います。2. バイナリファイルの名前を変更して適切なパスに配置する #
$ mv cloudflared-linux-amd64 cloudflared
$ sudo cp ./cloudflared /usr/local/bin/
3. 実行権限を与える #
$ sudo chmod +x /usr/local/bin/cloudflared
4. Cloudflare にログインする #
以下のコマンドを実行して表示されたURLを任意のブラウザで開く
ページが開いたら紐付けたいドメイン名を選択して 承認ボタン
を押す
$ cloudflared tunnel login
5. トンネルを作成する (この時点では設定をするだけでまだコネクションは貼られない) #
~/ホームフォルダ/.cloudflared/
内にトンネルID等の認証ファイルが生成される
abcd1234-0000-0000-0000-000000000000.json
の形式の名前のjsonファイルです。$ cloudflared tunnel create <任意のTunnelの名前>
6. トンネルIDとドメイン名を紐づける #
一つ前の作業で作成されたJSONファイルを確認してトンネルのIDを把握しておく
トンネルIDが分かったら以下のコマンドで トンネルID
と 設定したいドメイン
を紐づける
$ cloudflared tunnel route dns <Tunnelのid> <(紐付けたいドメイン名)>
7. 公開するポートと紐づけるドメインの設定 #
cloudflared
という名前のディレクトリを作成し、その中に config.yml
という名前のファイルを作成する。
config.yml
の中身は各自の目的に合わせて下の例のように記述する。
$ sudo mkdir /etc/cloudflared
$ sudo nano /etc/cloudflared/config.yml
config.ymlの内容 #
ここでは SSH
と VNCサーバ
を外部に公開する設定にしています。
他のポートを公開したい場合は各自任意の情報に書き換えてください。
tunnel: トンネルのID
credentials-file: 絶対パス/.cloudflared/作成されたjsonファイルを指定
ingress:
- hostname: <紐付けたいドメイン名>
service: ssh://localhost:22
- hostname: <紐付けたいドメイン名>
service: tcp://localhost:5900
- service: http_status:404
8. cloudflaredをサービスとして設定する (自動で起動するようにする) #
$ sudo cloudflared --config /etc/cloudflared/config.yml service install
9. cloudflaredを起動する #
$ sudo systemctl start cloudflared
$ sudo systemctl enable cloudflared
10. 正常に起動しているか確認する #
Active
の欄が active (running)
になっていればOK
$ sudo systemctl status cloudflared
🟢 cloudflared.service - Cloudflare Tunnel
Loaded: loaded (/etc/systemd/system/cloudflared.service; enabled; vendor preset: disabled)
Active: active (running) since Thu 2022-10-27 12:29:48 JST; 3 weeks 0 days ago
Main PID: 2976033 (cloudflared)
Tasks: 30 (limit: 202791)
Memory: 64.3M
CGroup: /system.slice/cloudflared.service
└─2976033 /usr/local/bin/cloudflared --config /etc/cloudflared/config.yml tunnel run
自動アップデートの設定 #
下記のコマンドで cloudflared.service
を開き、ExecStartの行から --no-autoupdate
の記述を削除する
$ sudo nano /etc/systemd/system/cloudflared.service
$ sudo systemctl daemon-reload
$ sudo systemctl restart cloudflared
SSH接続できるようにするための設定 #
※クライアント側の設定です!
サーバ側のSSHポートを公開して外部からアクセスできるようにしたい場合は、以下の設定も必要になります。
ProxyCommand
の行が肝です
Host ssh.example.com
HostName ssh.example.com
User hoge
ProxyCommand /usr/local/bin/cloudflared access ssh --hostname %h
VNC接続するときのコマンド #
$ sudo cloudflared access tcp --hostname vnc.example.com --url localhost:1234
コマンドを実行した後にVNC Viewer等で localhost:1234
に接続すると繋がります
まとめ #
この記事ではポート開放ができない環境でも、Cloudflareのサービスの利用によってサーバを外部公開する方法を紹介しました。 近年ではAWSやGCPといったクラウドサービスが普及しているため、サーバの外部公開で困ることは少ないかも知れません。 しかし、研究活動の一環での利用となると、コストやその他諸々の事情でそれらの利用が難しい場合も あります。 この問題を解決するための方法として本記事ではCloudflareのサービスについて紹介しました。
なお、記事中ではあまり触れていませんが、Cloudflareのサービスを使い出す前は ngrok のサービスも実際に導入し利用を検討していました。 こちらのサービスはコマンドを1つ叩くだけで指定したポート番号を外部に公開できるため、短期間だけデバックやデモとして公開したい場合には非常に便利なサービスです。 URLが固定じゃなくても問題ない場合にはまずは ngrokを試してみても良いかもしれません。 同様の問題を抱えている人にこの記事が参考になれば幸いです。
明日は@a5chinさんによる「数独・ナンプレを画像から解く AI を作る」という記事が公開されます。 お楽しみに!!