🍆

Synology NAS用のトンネルを AWS Lightsail で格安構築

に公開

概要

自宅ネットワーク内の Synology NAS に外部からアクセスするため、AWS Lightsail でトンネルサーバを構築する方法を解説します
記事自体は Synology NAS についての解説ですが、自宅ネットワーク内の任意のサーバを外部公開したい場合にも応用できます。

では早速解説と行きたいところですが、しかしその前に数ある選択肢から Lightsail へ至った経緯から始めます

QuickConnect は重い

簡単に設定できて無料の QuickConnect は魅力的ですが、全ての通信が Synology社のサーバを経由する仕組みであり、通信速度が遅いため利用を断念しました。

DDNS は専有グローバルIPが必要、セキュリティ面でもデメリットあり

自宅ネットワークに割り当てられてたグローバルIP を DDNS で任意のドメインに紐付けることで、そのドメインで自宅IPに直接接続する方式です。Synology社が提供している DDNS サービスを無料で利用できます
この方法は直接自宅に接続するため通信速度は速いですが以下のデメリットがあります

  • 原則として専有グローバルIPが必要なので、接続回線の選択肢が限定される ※プライベートIPしか割り振られない環境では利用できない
  • MAP-E 方式など IPv4 アドレスを共有する場合は疎通可能ポートに制限があってやっかい
  • 自宅のIPに外部から直接疎通可能なのはセキュリティ的なリスクがある

私の自宅環境は MAP-E 方式のため、IPv4 アドレスに対して利用可能なポート範囲が限られます。
さらに割り当てポート範囲は固定とも言えないため、不意に再割り当てが発生して、利用可能なポートが変わり、各PC/スマホに設定していた接続先ポート番号をすべて変更して回るという問題が過去に1度発生しました
IPアドレスの変化は DDNS で追随できますが、利用可能ポートの変化には DDNS では対応できないというのが盲点でした

MAP-E 方式の利用可能ポート範囲は IPv6 アドレスから計算で求められるので、私のケースでは IPv6 アドレスの再割り当てが発生したようです

Cloudflare Zero Trust は仕様上の制限がある

Cloudflare Zero Trust は HTTPS 通信を中継するプロキシとして動作する仕様で、自宅の Synology NAS へ外部からアクセスするくらいの用途では無料で利用できます
さすが Cloudflare というべきか、通信速度は DDNS で直接接続するのと比べても遜色ないほどです

しかし残念ながら以下の理由でベストな選択肢にはなりませんでした

  1. Synology Photos のスマホアプリで容量の大きい動画をアップロードすると 524 A timeout occurred が発生して失敗する
    • Cloudflare のプロキシタイムアウトが 100秒のためそれ以上かかるアップロードの通信は切断される
  2. 任意の TCP 通信を中継できないため、Synology Drive を利用できない(※厳密には可能だがクライアント側でも cloudflared の実行が必要で不便)
  3. E2E Encryption を実現できない、Cloudflare のエッジサーバーで復号化してから再度 cloudflared のトンネル経由で暗号化通信される

スマホで10~20分程度の動画を撮っただけでアップロードエラーが発生するのは率直に不便でした
また、非HTTP(S)プロトコルを利用する Synology Drive を利用できない点でも候補にはできませんでした

ngrok はデータ通信に制限あり

無料サービスは諦めて有料のマネージドのトンネリングサービスを模索しました
有名どころの ngrok は次のような特徴を持ちます

  • 複数人で 1つの IPv4 アドレスを共有する
  • HTTPS の 443 ポートも共有だが、SNI(Server Name Indication)で振り分けるため実用上は問題なし
  • 任意の TCP 通信のトンネリングは可能だが、パブリック側のポートはランダム割り当て

限られた IPv4アドレスを有効活用するという意味で考えられたサービスだなという感想で、要件的にはやりたいことができそうでした。
しかし $8/month の PERSONAL プランでは Data Transfer Out が 5GB しかなく、想定するデータ通信量を考慮すると高いプランを利用することとなり予算オーバーで断念しました

最終的にたどり着いた AWS Lightsail

マネージドサービスにはサービスの設計上で何らかの制限があるので、インターネット上に固定の IPv4 アドレスを持つサーバーを用意する方向にしました
AWS EC2 でもなんでも良かったのですが、設定の簡単さを重視して AWS Lightsail を選択しました

構成

自宅ネットワーク内の Synology NAS から AWS Lightsail に SSH 接続することで、Lightsail → Synology NAS の方向に 80, 443, 6690 を転送するトンネルを作り、グローバルIPを持たない Synology NAS へインターネットから接続可能とします。

各ポートの用途

  • 80 -> 80: Let's Encrypt 証明書発行用
  • 443 -> 5001: Synology NAS の管理画面(Synology DiskStation Manager / DSM)や Synology Photos など複数アプリで利用
  • 6690 -> 6690: Synology Drive で利用

設定方法

AWS Lightsail インスタンス作成

AWS Lightsail にアクセスして以下の設定でインスタンスを作成します

  • Select a platform -> Linux/Unix
  • Select a blueprint -> Operating System (OS) Only, Ubuntu 24.04 LTS
  • SSH key -> Create custom key で鍵を作成してダウンロード ※後のフェーズで使います
  • Select a network type -> Dual-stack
  • Select a size -> $5 USD per month
  • Instance name -> 任意の名前

インスタンスを作成したら Networking メニューにアクセスして static IP を作成し、先ほど作成したインスタンスにアタッチします

sshd の設定変更

AWS Lightsail インスタンスで 0.0.0.0 にバインドする許可と、 1-1023番の範囲のポートで Listen をするために root での接続を許可する設定を行います。
セキュリティ的な懸念があるので鍵の管理にはご注意ください。

Lightsail 管理画面の左メニューの Instances から作成したインスタンスを選択して、 Connect using SSH ボタンを押してブラウザウインドウで ssh ターミナルを開きます

sudo vim /etc/ssh/sshd_config

以下の設定を追加します

PermitRootLogin yes
GatewayPorts yes

ファイルを保存したら sshd を再起動します

sudo systemctl restart ssh

次に root の authorized_key を編集して転送に関する制限を削除します

sudo vim /root/.ssh/authorized_keys

no-port-forwarding,no-agent-forwar... の部分を削除して以下の部分だけ残して保存します

ssh-rsa AAAAB3NzaC...cJf aws

Synology NAS からトンネル作成

本記事では SSH Tunnel を作成する方法として Container Manager を利用する方法を紹介しますが、Container Manager を利用できない機種の場合は「端末とSNMP」から SSH サービスを有効にした上で、タスクスケジューラを利用して SSH 接続を行ってください。

Container Manager を利用すると、不意に落ちても再起動してくれるメリットがあります。

Container Manager のインストール

Container Manager がインストールされていない場合はパッケージセンターからインストールします。

鍵ファイルを NAS にコピー

Create custom key で作成した鍵ファイルを File Station の /docker 直下(/docker/aws_synology_tunnel.pem)に保存します。

コンテナの設定

SSH Tunnel を作成するコンテナは Docker Hub の以下のコンテナイメージを利用します
https://hub.docker.com/r/jnovack/autossh

このコンテナイメージで利用されている autossh は ssh のラッパーで接続が切れても再接続してくれます。

今回は Synology NAS の管理画面や Synology Photos 及び Synology Drive を利用できるように 80, 443, 6690 ポートを Synology NAS に転送します。詳しくは構成項を参照ください。

  1. Container Manager を起動する
  2. 左メニューから「イメージ」 -> 「操作」 -> 「インポート」 -> 「URL から追加」と順に選択する
  3. 開いたダイアログで「ハブページまたはリポジトリURL」に jnovack/autossh と入力してインポートを押す
  4. 左メニューから「コンテナ」 -> 「作成」を選択する
  5. 「イメージ」のプルダウンで先ほどインポートした jnovack/autossh を選択して「次へ」を押す ※表示されない場合はダウンロードをしばらく待ってください
  6. 「ボリューム設定」 -> 「+ファイルの追加」を押して /docker/aws_synology_tunnel.pem を選択
    • テキストボックスには /id_rsa と入力し、ドロップダウンは「読み取り専用」を選択
  7. 「環境」 -> 「+追加」を押して以下を追加 ※他にも転送したい場合は SSH_OPTIONS に追加する
    • SSH_MODE -> -R
    • SSH_BIND_IP -> 0.0.0.0
    • SSH_TUNNEL_PORT -> 80
    • SSH_TARGET_HOST -> localhost
    • SSH_TARGET_PORT -> 80
    • SSH_REMOTE_USER -> root
    • SSH_REMOTE_HOST -> ※Lightsail の static IP または後フェーズで付けたドメイン名
    • SSH_OPTIONS -> -R 0.0.0.0:443:localhost:5001 -R 0.0.0.0:6690:localhost:6690
      • 1つめのポート転送設定には専用の環境変数を利用しますが、2つめ以降は SSH_OPTIONS にまとめて設定します
    • SSH_KEY_FILE -> /id_rsa
  8. 「ネットワーク」のプルダウンから「host」を選択
  9. 「次へ」を押す
  10. 「ウィザード終了後、このコンテナを実行」にチェックが付いていることを確認して「完了」

設定が終わったら https://{Lightsail の static IP}/ にアクセスします。IPアドレスでのアクセスなので証明書のエラーが発生しますが、無視すればアクセス可能なはずです。
ちなみに 80番ポートも転送していますが、これは Synology NAS の管理画面(Synology DiskStation Manager / DSM)にアクセスするためのポートではなく、Let's Encrypt の証明書発行のためのポートなので、通常時はアクセスしても開けません。

【任意で実行】ドメインに紐付け

何らかドメインを持っている場合は Lightsail の static IP に紐付けるとさらに便利です。必要に応じて DNS に設定を追加してください。

DNS の設定ができたら Synology NAS の管理画面(Synology DiskStation Manager / DSM)から Let's Encrypt の証明書を発行します。
ここまでの設定で 80, 443 が疎通可能なので DSM が自動的に証明書の発行と更新を行ってくれます。

Let's Encrypt の証明書の発行方法はこちらの記事を参照してください

簡単に解説するとドメイン名と連絡先の電子メールアドレスを入力すれば OK です。設定に問題が無ければ数十秒ほどで証明書が発行されます。

証明書を発行したら各アプリがその証明書を使うように設定が必要です。
DSM のコントロールパネルの「セキュリティ」 -> 「証明書」 -> 「設定」とたどり、そのドメインでアクセスするサービスの証明書を変更します。

まとめ

任意の TCP アクセスを転送できるので、Synology NAS 以外の用途にもぜひ活用してください!

Discussion