Tailscale serve.json 設定項目一覧 （Funnel）

> [Tailscaleのソースコード(2024/07/27)](https://github.com/tailscale/tailscale/blob/1d6ab9f9dbba01988ef8798f76a21d3c88e5a0f9/ipn/serve.go) に準拠しております
---
### plantuml図

```plantuml
@startuml
!theme mars
skinparam monochrome false
skinparam shadowing false
skinparam defaultFontName "Helvetica"
skinparam defaultFontSize 14

cloud "                インターネット                " as internet

frame "Tailscaleネットワーク（Tailnet）" as network{
  frame "tailnetメンバー" {
    actor ローカルユーザー as localuser
  }
  frame "Tailscaleノード" as node {
    card "tailscaled" as tailscaled {
      rectangle "Funnel" as funnel
      rectangle "Serve" as serve
    }
    card "ハンドラー" as handler {
      rectangle "TCPハンドラー" as tcp
      rectangle "Webハンドラー" as web
    }
  }
}
  database "ローカルサービス（127.0.0.1）" as local {
    [HTTPサーバー :8000]
    [HTTPサーバー :3000]
    [HTTPサーバー :8080]
    [静的ファイル\n/var/www/html]
  }

internet -[thickness=4,#blue]-> funnel : "    Funnel でサービスを\nインターネットに公開\n:443 :8443\n:10000 のみ"

funnel <-left-> serve

serve --> handler
localuser -[thickness=4,#green]> serve : "ローカル接続"

tcp --> [HTTPサーバー :8000] : ":443 TLS終端"
tcp --> [HTTPサーバー :3000] : ":10000"
web --> [HTTPサーバー :8080] : "  /api"
web --> [静的ファイル\n/var/www/html] : "  /"
@enduml
```

---

### ⇩ クリックして展開！

<details><summary>serve.json(c)</summary>

## serve.json

```jsonc
{
  // TCP: map[uint16]*TCPPortHandler
  "TCP": {
    "80": {
      // ポート80で HTTP を提供
      // HTTPSのみを使用する構成でも80番ポートを開けてhttpsにリダイレクトさせるようにしましょう
      "HTTP": true
    },
    "443": {
        // TLS接続をtailscaled（Tailscaleのデーモン）で終端し、平文のTCPトラフィックとして転送先に渡すか制御できます
        // 特定のSNI名のみを許可することで、不正なTLS接続を防ぐことができます
        // ポート443でTLS終端を行い、localhost:8000に転送
        // 例としてexample.qilin-qilin.ts.netを使用します
        "TCPForward": "localhost:8000",
        "TerminateTLS": "example.qilin-qilin.ts.net"
    },
    "10000": {
      // ポート10000への接続をlocalhost:3000にすべて転送
      "TCPForward": "localhost:3000"
    }
  },
  // Web: map[HostPort]*WebServerConfig
  "Web": {
    // HostPortは、コロンで結合されたSNI名とポート番号です
    // 暗黙の443ポートはありません。必ずコロンを含む必要があります
    // HostPortに ${TS_CERT_DOMAIN} を使用することで、example.qilin-qilin.ts.net などに置き換わります
    "${TS_CERT_DOMAIN}:80": {
      "Handlers": {
        "/": {
          "Proxy": "https://example.com"
        }
      }
    },
    "${TS_CERT_DOMAIN}:443": {
      // Handlers: map[string]*HTTPHandler
      "Handlers": {
        "/": {
          // 任意のパスを静的ファイルを提供できます
          "Path": "/var/www/html"
        },
        "/api": {
          // /apiパスをlocalhost:8080にプロキシします
          "Proxy": "http://localhost:8080"
        },
        "/test": {
          // /testパスで単純なテキストを返します
          "Text": "これはテストページです"
        }
      }
    }
  },
  // AllowFunnel: map[HostPort]bool
  "AllowFunnel": {
    // Funnelはtailnet外部へウェブサイトを公開することができる機能です
    // あらかじめ Admin-Consoleで設定しておく必要があります
    // 現在Funnelは 10000、443、80番のみ 許可されています
    "example.qilin-qilin.ts.net:443": true,
    "example.qilin-qilin.ts.net:8443": true,
    "${TS_CERT_DOMAIN}:10000": true
  },

  // 自動化のための項目です。一般の人は使わないであろう設定です
  // Foreground は、Tailscaleの一時的な設定を管理するために使用されます
  // これらの設定は永続的ではなく、一時的に適用されます
  // Foreground: map[string]*ServeConfig
  "Foreground": {
    "test-session-789": {
      "TCP": {
        "9000": {
          "HTTP": true
        }
      },
      "Web": {
        "example.qilin-qilin.ts.net:9000": {
          "Handlers": {
            "/test": {
              "Text": "こんにちは！外部プログラムによって設定されました！"
            }
          }
        }
      }
    }
  }
}
```

</details>

---

- `${TS_CERT_DOMAIN}` を使用することで、tailscaled が管轄する [**Tailnet-name**](https://tailscale.com/kb/1217/tailnet-name) に動的に置き換えられます
- `TCP`、`Web`、`AllowFunnel`、`Foreground`、`ETag`が設定できますが、`UDP` は不可です


## プロキシ対象のURL展開

以下のフォーマットが許可されています：

- `3000`
- `localhost:3000`
- `tcp://localhost:3000`
- `http://localhost:3000`
- `https://localhost:3000`
- `https-insecure://localhost:3000`
- `https-insecure://localhost:3000/foo`

:::note warn
**注意**: 
`https-insecure` スキームを使用すると、自己署名証明書 や 無効な証明書 を持つ HTTPSサーバー への接続が可能になります。
TLS接続は確立されますが、証明書の検証は行われません
:::
:::note alert
**プロキシ先の注意** （2024/10/04 現在）
現在、プロキシでは http://127.0.0.1 のみがサポートされています
Docker Compose などのネットワークにて接続し、コンテナのホストを指定しても（http://nginx/ など）繋がりませんので注意してください。

Tailscaleをサイドカーとしてコンテナを公開したい場合、Compose.yml内に
`network_mode: service:tailscale`
を設定して コンテナのすべてのトラフィックを **Tailscaleコンテナ経由で ルーティング**してください。tailscaled の 127.0.0.1 の仲間入りになります。
くわしくは **[docker-tailscale-guide](https://tailscale.com/blog/docker-tailscale-guide)** をご参照ください
:::

## Funnel機能の使用条件

Funnelを使用することでHTTPSを通じてWebサービスを**外部に**公開させることができます
以下のような Tailnet-nameを使用し公開されます
例: https://example.qilin-qilin.ts.net/
**[アドミンコンソール](https://login.tailscale.com/admin/dns)** にてtailnameが変更可能です


:::note 
**Funnelが使えない場合、以下をチェックしてください**: 
- Funnelを使用する場合、[初期設定が必要です](https://tailscale.com/kb/1223/funnel)
- FunnelはTLS接続が前提となっております。[HTTPSを有効にする](https://tailscale.com/kb/1153/enabling-https)
- ACLにnodeAttrsを付与する必要があります。[ACLに追加する](https://tailscale.com/kb/1337/acl-syntax#node-attributes)
:::
:::note warn
**制限事項**
1. **使用可能なDNS名**: tailnetのドメイン（tailnet-name.ts.net）内のみ
1. **リッスン可能なポート**: 443、8443、10000 のみ
1. **接続タイプ**: TLS暗号化接続のみ
1. **帯域幅**: 設定不可能な制限あり
1. **対応プラットフォーム**: Tailscale CLIが実行可能なプラットフォームのみ
1. **macOSでの使用**: オープンソースバージョンのTailscaleアプリケーションが必要
:::

## Foreground設定について

Foregroundは、IPN Bus（Inter-Process Notification Bus）セッションIDに紐づきます。主にCLIツールやその他の短期的な操作で使用され、永続的な設定変更を行わずに一時的なサービス提供を可能にします。セッションが終了すると、これらの設定は自動的に無効になります。

CLIによる自動化を行う際に、CLIツールやその他のプログラムが簡単に設定の読み書きを行うためにこの処理が用意されています。

> **注**: 一般のユーザーはおそらく使用しません