From 2ffa06ac80077061e9132502ac3bd532d6cb665e Mon Sep 17 00:00:00 2001 From: Timmy Date: Fri, 10 Apr 2026 09:17:12 +0800 Subject: [PATCH] Initial commit: Tailscale Docker deployment with Headscale MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Docker Compose 部署 Tailscale 連線至自架 Headscale 控制伺服器, 包含子網路由、出口節點、iptables NAT 設定及完整中文文件。 Co-Authored-By: Claude Opus 4.6 (1M context) --- .gitignore | 2 + CLAUDE.md | 42 +++++++++++++++ OPERATIONS.md | 93 +++++++++++++++++++++++++++++++++ QUICKSTART.md | 44 ++++++++++++++++ README | 35 +++++++++++++ README.md | 67 ++++++++++++++++++++++++ SUMMARY.md | 25 +++++++++ docker-compose.yml | 23 ++++++++ docker_exec_tailscale_ip.sh | 4 ++ docker_exec_tailscale_status.sh | 2 + docker_exec_tailscale_up.sh | 9 ++++ iptables_reset_and_configure.sh | 44 ++++++++++++++++ run.sh | 2 + stop.sh | 4 ++ tailscale | 3 ++ 15 files changed, 399 insertions(+) create mode 100644 .gitignore create mode 100644 CLAUDE.md create mode 100644 OPERATIONS.md create mode 100644 QUICKSTART.md create mode 100644 README create mode 100644 README.md create mode 100644 SUMMARY.md create mode 100644 docker-compose.yml create mode 100755 docker_exec_tailscale_ip.sh create mode 100755 docker_exec_tailscale_status.sh create mode 100755 docker_exec_tailscale_up.sh create mode 100755 iptables_reset_and_configure.sh create mode 100755 run.sh create mode 100755 stop.sh create mode 100755 tailscale diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..93ad088 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +.env +.omc/ diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..fc16392 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,42 @@ +# CLAUDE.md + +This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository. + +## Overview + +Docker-based Tailscale deployment using a self-hosted Headscale control server (`https://headscale.lotimmy.com`). Runs a `tailscale/tailscale:latest` container in host network mode with subnet routing (192.168.88.0/24) and exit node capability. + +## Commands + +```bash +# Start the Tailscale container +./run.sh # docker-compose up -d + +# Stop the container +./stop.sh # docker-compose down + +# Connect to Headscale (advertise subnet routes + exit node) +./docker_exec_tailscale_up.sh + +# Check status / get IP +./docker_exec_tailscale_status.sh +./docker_exec_tailscale_ip.sh + +# Run arbitrary tailscale commands inside the container +./tailscale # wrapper for: docker exec -i tailscale tailscale "$@" + +# Reset iptables and configure NAT/forwarding for Tailscale routing (run on host) +./iptables_reset_and_configure.sh +``` + +## Architecture + +- **docker-compose.yml** - Single service (`tailscale`) running `tailscale/tailscale:latest` with `NET_ADMIN`/`SYS_MODULE` caps, host networking, TUN device mount, and persistent state at `/opt/tailscale`. +- **`.env`** - Contains `TS_AUTHKEY` for pre-authenticated registration with Headscale. +- **iptables_reset_and_configure.sh** - Configures host firewall: allows SSH/HTTP/HTTPS/ICMP, sets up MASQUERADE NAT for Tailscale CGNAT range (100.64.0.0/10) via eth0, and enables forwarding between `tailscale0` and `eth0`. +- Watchtower auto-update is enabled via container label. + +## Notes + +- Documentation (`README`) is in Traditional Chinese. +- Hostname convention: `ip-192-168-88-XX` matching the host's LAN IP. diff --git a/OPERATIONS.md b/OPERATIONS.md new file mode 100644 index 0000000..e567ae0 --- /dev/null +++ b/OPERATIONS.md @@ -0,0 +1,93 @@ +# Operations Guide + +## 日常操作 + +### 啟動服務 + +```bash +./run.sh +``` + +啟動 Tailscale Docker 容器(背景執行)。 + +### 停止服務 + +```bash +./stop.sh +``` + +停止並移除容器。 + +### 連線至 Headscale + +```bash +./docker_exec_tailscale_up.sh +``` + +使用預設的 Auth Key 連線至 `https://headscale.lotimmy.com`,並: +- 廣播子網路 `192.168.88.0/24` +- 啟用出口節點(Exit Node) +- 接受其他節點的路由 + +### 檢查狀態 + +```bash +./docker_exec_tailscale_status.sh # 查看連線狀態 +./docker_exec_tailscale_ip.sh # 查詢 Tailscale IP +``` + +### 執行任意 Tailscale 指令 + +```bash +./tailscale status +./tailscale ping +./tailscale netcheck +``` + +`./tailscale` 是 `docker exec -i tailscale tailscale` 的包裝腳本。 + +## 防火牆與路由設定 + +在主機上執行: + +```bash +sudo ./iptables_reset_and_configure.sh +``` + +此腳本會: +1. 清除所有現有 iptables 規則 +2. 允許 SSH (22)、HTTP (80)、HTTPS (443)、ICMP +3. 設定 Tailscale CGNAT 範圍 (100.64.0.0/10) 的 NAT MASQUERADE +4. 啟用 `tailscale0` ↔ `eth0` 之間的封包轉送 +5. 將規則儲存至 `/etc/iptables/rules.v4` + +## 環境變數 + +| 變數 | 說明 | 位置 | +|------|------|------| +| `TS_AUTHKEY` | Headscale 預認證金鑰 | `.env` | + +## 持久化資料 + +- Tailscale 狀態檔案:主機的 `/opt/tailscale` 掛載至容器的 `/var/lib/tailscale` +- iptables 規則:`/etc/iptables/rules.v4` + +## 故障排除 + +```bash +# 確認容器正在執行 +docker ps | grep tailscale + +# 查看容器日誌 +docker logs tailscale + +# 確認 TUN 裝置存在 +ls -la /dev/net/tun + +# 確認 IP 轉送已啟用 +cat /proc/sys/net/ipv4/ip_forward + +# 登出並重新連線 +./tailscale logout +./docker_exec_tailscale_up.sh +``` diff --git a/QUICKSTART.md b/QUICKSTART.md new file mode 100644 index 0000000..62e302f --- /dev/null +++ b/QUICKSTART.md @@ -0,0 +1,44 @@ +# Quick Start + +## 前置需求 + +- Docker 與 Docker Compose +- `/dev/net/tun` 裝置(主機需支援 TUN/TAP) +- 具備 `NET_ADMIN` 權限的環境 + +## 步驟 + +### 1. 設定 Auth Key + +在 `.env` 檔案中填入 Headscale 預認證金鑰: + +``` +TS_AUTHKEY=your-preauth-key-here +``` + +### 2. 啟動容器 + +```bash +./run.sh +``` + +### 3. 連線至 Headscale + +```bash +./docker_exec_tailscale_up.sh +``` + +### 4. 設定防火牆(如需子網路由/出口節點) + +```bash +sudo ./iptables_reset_and_configure.sh +``` + +### 5. 驗證 + +```bash +./docker_exec_tailscale_status.sh +./docker_exec_tailscale_ip.sh +``` + +看到 Tailscale IP 和節點列表即代表連線成功。 diff --git a/README b/README new file mode 100644 index 0000000..6aba218 --- /dev/null +++ b/README @@ -0,0 +1,35 @@ +Tailscale 操作筆記(使用 Headscale) + +登出目前 Tailscale 使用者 +tailscale logout + +登入 Headscale 自架登入伺服器 +tailscale up --login-server=https://headscale.lotimmy.com + +使用預先產生的 Auth Key 進行登入 +tailscale up --login-server=https://headscale.lotimmy.com --authkey <你的-preauth-key> + +範例:使用實際的 Auth Key +tailscale up --login-server=https://headscale.lotimmy.com --authkey tskey-xxxxxxx + +正式使用 Auth Key 登入(可取代上方範例) +tailscale up --login-server=https://headscale.lotimmy.com --authkey d07067c4bcc950e7f1b02d4b492859b84ca464350d86273e + +登入並接受子網路路由(子網路代理模式) +tailscale up --login-server=https://headscale.lotimmy.com --authkey d07067c4bcc950e7f1b02d4b492859b84ca464350d86273e --accept-routes + +完整範例:廣播子網段、設為出口節點、指定主機名稱 +tailscale up \ + --accept-routes \ + --advertise-routes=192.168.88.0/24 \ + --advertise-exit-node \ + --login-server=https://headscale.lotimmy.com \ + --authkey=d07067c4bcc950e7f1b02d4b492859b84ca464350d86273e \ + --hostname=ip-192-168-88-81 + +檢查目前連線狀態 +tailscale status + +查詢本機 Tailscale IP +tailscale ip + diff --git a/README.md b/README.md new file mode 100644 index 0000000..3591ad4 --- /dev/null +++ b/README.md @@ -0,0 +1,67 @@ +# Tailscale Docker 部署(Headscale) + +使用 Docker Compose 部署 Tailscale,連線至自架的 Headscale 控制伺服器。 + +## 功能 + +- 透過 Docker 容器執行 Tailscale,使用 host 網路模式 +- 連線至 `https://headscale.lotimmy.com` +- 子網路由廣播(192.168.88.0/24) +- 出口節點(Exit Node)支援 +- iptables NAT/轉送自動設定 +- 透過 Watchtower 自動更新容器映像 + +## 檔案結構 + +| 檔案 | 說明 | +|------|------| +| `docker-compose.yml` | Docker 服務定義 | +| `.env` | 環境變數(TS_AUTHKEY) | +| `run.sh` | 啟動容器 | +| `stop.sh` | 停止容器 | +| `docker_exec_tailscale_up.sh` | 連線至 Headscale(含路由與出口節點設定) | +| `docker_exec_tailscale_status.sh` | 查看連線狀態 | +| `docker_exec_tailscale_ip.sh` | 查詢 Tailscale IP | +| `tailscale` | Tailscale CLI 包裝腳本 | +| `iptables_reset_and_configure.sh` | 防火牆與 NAT 設定 | + +## 快速開始 + +```bash +# 1. 設定 .env 中的 TS_AUTHKEY +# 2. 啟動 +./run.sh + +# 3. 連線至 Headscale +./docker_exec_tailscale_up.sh + +# 4. 設定防火牆(如需路由功能) +sudo ./iptables_reset_and_configure.sh + +# 5. 驗證 +./docker_exec_tailscale_status.sh +``` + +## 網路架構 + +``` +Tailscale 節點 ──► Headscale (headscale.lotimmy.com) + │ + ▼ + tailscale0 介面 (100.64.0.0/10) + │ + NAT MASQUERADE + │ + ▼ + eth0 ──► LAN (192.168.88.0/24) +``` + +## 主機名稱慣例 + +使用 `ip-192-168-88-XX` 格式,對應主機的區域網路 IP。 + +## 相關文件 + +- [QUICKSTART.md](QUICKSTART.md) — 快速開始指南 +- [OPERATIONS.md](OPERATIONS.md) — 維運操作手冊 +- [SUMMARY.md](SUMMARY.md) — 專案摘要 diff --git a/SUMMARY.md b/SUMMARY.md new file mode 100644 index 0000000..47cb2fb --- /dev/null +++ b/SUMMARY.md @@ -0,0 +1,25 @@ +# Summary + +## 專案摘要 + +此專案是一個 Docker 化的 Tailscale 部署方案,用於將主機連線至自架的 Headscale 控制伺服器(`https://headscale.lotimmy.com`)。 + +## 核心元件 + +- **Docker Compose 服務**:以 `tailscale/tailscale:latest` 映像執行,採用 host 網路模式,具備 `NET_ADMIN` 和 `SYS_MODULE` 權限。 +- **Headscale 整合**:透過預認證金鑰(Pre-auth Key)自動註冊節點。 +- **子網路由**:廣播 `192.168.88.0/24` 網段,讓遠端 Tailscale 節點可存取區域網路。 +- **出口節點**:允許其他節點透過此主機路由所有流量。 +- **iptables 設定**:NAT MASQUERADE 處理 Tailscale CGNAT 流量,並啟用 `tailscale0` ↔ `eth0` 轉送。 + +## 技術規格 + +| 項目 | 值 | +|------|---| +| 容器映像 | `tailscale/tailscale:latest` | +| 網路模式 | host | +| 控制伺服器 | `https://headscale.lotimmy.com` | +| 廣播子網 | `192.168.88.0/24` | +| Tailscale CGNAT | `100.64.0.0/10` | +| 狀態持久化 | `/opt/tailscale` → `/var/lib/tailscale` | +| 自動更新 | Watchtower(透過 container label) | diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..2536a4e --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,23 @@ +services: + tailscale: + image: tailscale/tailscale:latest + container_name: tailscale + hostname: virmach-ubuntu + restart: unless-stopped + cap_add: + - NET_ADMIN + - SYS_MODULE + network_mode: host + # privileged: true + environment: + - TS_AUTHKEY=${TS_AUTHKEY} + volumes: + - /dev/net/tun:/dev/net/tun + - /opt/tailscale:/var/lib/tailscale + labels: + - "com.centurylinklabs.watchtower.enable=true" + # command: > + # tailscaled + command: > + sh -c "env && tailscaled" + diff --git a/docker_exec_tailscale_ip.sh b/docker_exec_tailscale_ip.sh new file mode 100755 index 0000000..e45aec1 --- /dev/null +++ b/docker_exec_tailscale_ip.sh @@ -0,0 +1,4 @@ +#!/bin/bash +# docker exec -it tailscale tailscale ip +tailscale ip + diff --git a/docker_exec_tailscale_status.sh b/docker_exec_tailscale_status.sh new file mode 100755 index 0000000..c4051e2 --- /dev/null +++ b/docker_exec_tailscale_status.sh @@ -0,0 +1,2 @@ +docker exec -it tailscale tailscale status + diff --git a/docker_exec_tailscale_up.sh b/docker_exec_tailscale_up.sh new file mode 100755 index 0000000..c4c73b9 --- /dev/null +++ b/docker_exec_tailscale_up.sh @@ -0,0 +1,9 @@ +#!/bin/bash +tailscale up \ + --authkey d07067c4bcc950e7f1b02d4b492859b84ca464350d86273e \ + --advertise-routes=192.168.88.0/24 \ + --accept-routes \ + --advertise-exit-node \ + --login-server=https://headscale.lotimmy.com \ + --hostname=ip-192-168-88-82 + diff --git a/iptables_reset_and_configure.sh b/iptables_reset_and_configure.sh new file mode 100755 index 0000000..b64e282 --- /dev/null +++ b/iptables_reset_and_configure.sh @@ -0,0 +1,44 @@ +#!/bin/bash + +echo "🧹 清除所有規則並重設策略..." +iptables -F +iptables -t nat -F +iptables -X + +# 設定預設策略 +# iptables -P INPUT DROP +iptables -P INPUT ACCEPT +iptables -P FORWARD ACCEPT +# iptables -P FORWARD DROP +iptables -P OUTPUT ACCEPT + +echo "✅ 設定 INPUT 安全規則..." + +# 允許已建立與相關的連線(像是回應封包) +iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT -m comment --comment "Allow established/related" + +# 允許 loopback +iptables -A INPUT -i lo -j ACCEPT -m comment --comment "Allow loopback" + +# 允許 ICMP (ping) +iptables -A INPUT -p icmp --icmp-type echo-request -j ACCEPT -m comment --comment "Allow ping" + +# 允許 SSH +iptables -A INPUT -p tcp --dport 22 -j ACCEPT -m comment --comment "Allow SSH" + +# 可選:允許 HTTP/HTTPS(如果有 Web 應用) +iptables -A INPUT -p tcp --dport 80 -j ACCEPT -m comment --comment "Allow HTTP" +iptables -A INPUT -p tcp --dport 443 -j ACCEPT -m comment --comment "Allow HTTPS" + +echo "🔧 設定 Tailscale 出口 NAT(MASQUERADE)" +iptables -t nat -A POSTROUTING -s 100.64.0.0/10 -o eth0 -j MASQUERADE -m comment --comment "Tailscale NAT" + +echo "🔧 允許 Tailscale → LAN 轉送" +iptables -A FORWARD -i tailscale0 -o eth0 -j ACCEPT -m comment --comment "Tailscale → LAN" +iptables -A FORWARD -i eth0 -o tailscale0 -m state --state RELATED,ESTABLISHED -j ACCEPT -m comment --comment "LAN → Tailscale return" + +echo "📦 儲存規則(iptables-persistent)" +iptables-save > /etc/iptables/rules.v4 + +echo "✅ 防火牆與 NAT 重設完成!" + diff --git a/run.sh b/run.sh new file mode 100755 index 0000000..2a67cfd --- /dev/null +++ b/run.sh @@ -0,0 +1,2 @@ +#!/bin/bash +docker-compose up -d diff --git a/stop.sh b/stop.sh new file mode 100755 index 0000000..e4fab3e --- /dev/null +++ b/stop.sh @@ -0,0 +1,4 @@ +#!/bin/bash +# docker stop caddy +# docker system prune -f +docker-compose down diff --git a/tailscale b/tailscale new file mode 100755 index 0000000..0549696 --- /dev/null +++ b/tailscale @@ -0,0 +1,3 @@ +#!/bin/bash +docker exec -i tailscale tailscale "$@" +