kotoyuuko

CORE

昨日より、明日より、笑える今が一番大好き。
github
telegram
email

自建 Headscale + DERP サーバー

以前はポートマッピングを通じて自宅の NAS にアクセスしていましたが、いくつかの問題がありました:

  • DDNS の設定が必要で、IP が切り替わると遅延が発生する
  • Web サービスにアクセスするにはポートを追加する必要がある
  • 一部のサービスしか公開できず、比較的コアなサービス(例えばルーターの設定)はパブリックアクセスを許可できない

最近の間に、さまざまなネットワーク構成のソリューション(ZeroTier/WireGuard/Tailscale)を調査し、試した結果、最終的に自前の Headscale フルスタックソリューションを選択しました。

準備#

  • VPS を 1 台、Docker および Docker Compose をインストールし、以下のポートを開放する必要があります
    • 8080 Headscale HTTP
    • 9090 Headscale Metrics
    • 8443 DERP サーバー HTTPS
    • 3478/udp DERP サーバー STUN
    • 8008 Headscale-Admin
  • クライアント(Linux/macOS/Windows/iOS/Android)

DERP サーバーのデプロイ#

DERP サーバーの設定ファイルを保存するディレクトリを作成します

mkdir -p /app/derper/certs
cd /app/derper

自己署名証明書を作成します

openssl req -x509 -newkey rsa:4096 -sha256 -days 3650 -nodes -keyout /app/derper/certs/<hostname>.key -out /app/derper/certs/<hostname>.crt -subj "/CN=<hostname>" -addext "subjectAltName=DNS:<hostname>"

hostname は任意で、統一すれば良いです

docker-compose.yamlファイルを作成し、内容は以下の通りです:

services:
  derper:
    image: ghcr.nju.edu.cn/yangchuansheng/derper:latest
    container_name: derper
    restart: always
    volumes:
      - /app/derper/certs:/app/certs
    environment:
      - DERP_CERT_MODE=manual
      - DERP_ADDR=:443
      - DERP_DOMAIN=<hostname>
    ports:
      - 8443:443
      - 3478:3478/udp

ここでは南京大学が提供する GHCR イメージを使用しています。必要ない場合はghcr.nju.edu.cnghcr.ioに置き換えてください。

最後に DERP サーバーを起動します

docker compose pull
docker compose up -d

derp.json設定ファイルを作成し、直接アクセスできる場所に保存します:

{
  "Regions": {
    "901": {
      "RegionID": 901,
      "RegionCode": "cn-hangzhou",
      "RegionName": "Hangzhou",
      "Nodes": [
        {
          "Name": "901h",
          "RegionID": 901,
          "DERPPort": 8443,
          "HostName": "<hostname>",
          "IPv4": "<IP>",
          "InsecureForTests": true
        }
      ]
    }
  }
}

ここでは、すでにhttps://example.com/derp.jsonにアップロードされていると仮定します。

Headscale のデプロイ#

Headscale の設定ファイルディレクトリを作成します

mkdir -p /app/headscale
cd /app/headscale
mkdir config
touch config/db.sqlite
wget -O config/config.yaml https://raw.githubusercontent.com/juanfont/headscale/main/config-example.yaml

config/config.yamlファイルの設定を変更します:

  • server_urlhttp://<IP>:8080に変更
  • listen_addr0.0.0.0:8080に変更
  • metrics_listen_addr0.0.0.0:9090に変更(オプション)
  • grpc_listen_addr0.0.0.0:50443に変更
  • noise.private_key_path/etc/headscale/noise_private.keyに変更
  • prefixes.v4prefixes.v6は必要に応じて変更
  • derp.urls[0]を先ほどアップロードしたderp.jsonファイルの URL に変更、ここではhttps://example.com/derp.json
  • database.sqlite.path/etc/headscale/db.sqliteに変更
  • dns_config.nameservers223.5.5.5223.6.6.6に変更(必要に応じて変更可能)
  • dns_config.base_domainを自分のドメインに変更、クライアントに表示されます

docker-compose.yamlファイルを作成します:

services:
  headscale:
    image: headscale/headscale:0.23.0-alpha8
    container_name: headscale
    restart: always
    command: serve
    volumes:
      - ./config:/etc/headscale
    ports:
      - 8080:8080
      - 9090:9090

最後に Headscale を起動します

docker compose pull
docker compose up -d

Headscale-Admin のデプロイ#

Headscale-Admin の設定ファイルディレクトリを作成します

mkdir -p /app/headscale-admin
cd /app/headscale-admin

ブラウザの HTTP セキュリティ制限により、直接ドメインにアクセスするとクロスオリジンになります。ここでは Caddy を使用してリバースプロキシを回避します。

nano Caddyfile

内容は以下の通りです:

:{$PORT:80} {
  reverse_proxy /api/* <IP>:8080
  root * /app
  encode gzip zstd
  try_files {path}.html {path}
  file_server
}

docker-compose.yamlファイルを作成します:

services:
  headscale-admin:
    image: goodieshq/headscale-admin:latest
    container_name: headscale-admin
    restart: unless-stopped
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
    environment:
      - PORT=80
      - ENDPOINT=/headscale
    ports:
      - 8008:80

最後に起動します

docker compose pull
docker compose up -d

Headscale の API キーは以下のコマンドで作成できます:

docker exec -it headscale headscale apikey create

Web UI にはhttp://<IP>:8008/headscaleでアクセスでき、設定ではLegacy APIのチェックを外す必要があります。

ユーザーの作成#

サーバーで以下のコマンドを実行するだけです

docker exec -it headscale headscale users create <あなたのユーザー>

クライアント設定#

Linux#

まず Tailscale クライアントをインストールします

curl -fsSL https://tailscale.com/install.sh | sh

次に Headscale ネットワークに参加を申請します

tailscale up --login-server=http://<IP>:8080 --accept-routes

このノードを通じて他のネットワークセグメントにアクセスする必要がある場合は、--advertise-routesオプションを追加します:

tailscale up --login-server=http://<IP>:8080 --advertise-routes=192.168.1.0/24 --accept-routes

戻ってきた結果のリンクを開くと、認証コマンドが含まれています。それをサーバーで実行します。

docker exec headscale headscale nodes register --user <あなたのユーザー> --key nodekey:******

Apple デバイス#

直接http://<IP>:8080/appleにアクセスし、手順に従って操作します。

Android#

F-Droid のこのページを開いて APK インストーラーをダウンロードします:

f-droid.org/en/packages/com.tailscale.ipn

インストール後、アプリを開き、右上の 3 つの点を数回タップするとChange Serverが表示されます。そこにhttp://<IP>:8080を入力し、指示に従って認証を完了します。

Windows#

自宅に Windows デバイスがないため、実際のテストはできません。皆さんは参考資料のチュートリアルを参照してください。

参考資料#

読み込み中...
文章は、創作者によって署名され、ブロックチェーンに安全に保存されています。