diff --git a/docs/CUSTOM_CLIENT.md b/docs/CUSTOM_CLIENT.md new file mode 100644 index 000000000..1467c238c --- /dev/null +++ b/docs/CUSTOM_CLIENT.md @@ -0,0 +1,384 @@ +# Hướng dẫn Custom Tailscale Client + +## Mục lục +1. [Tổng quan](#tổng-quan) +2. [Danh sách files đã thay đổi](#danh-sách-files-đã-thay-đổi) +3. [Chi tiết từng thay đổi](#chi-tiết-từng-thay-đổi) +4. [Build Windows Client](#build-windows-client) +5. [Build Linux Client](#build-linux-client) +6. [Tạo MSI Installer (Windows)](#tạo-msi-installer-windows) +7. [Tray App (Windows)](#tray-app-windows) +8. [Cách deploy lên máy mới](#cách-deploy-lên-máy-mới) + +--- + +## Tổng quan + +Custom Tailscale Client là bản fork từ Tailscale v1.97.0, được tuỳ chỉnh để: +- **Chạy song song** với Tailscale chính thức trên cùng 1 máy +- **Kết nối Headscale** tại `https://vpn.softs.business` (default) +- **Không xung đột** service name, named pipe, registry, TUN adapter, thư mục dữ liệu + +### Namespace isolation (tránh xung đột) + +| Thành phần | Tailscale gốc | Tailscale-Custom | +|------------|---------------|------------------| +| Service name | `Tailscale` | `Tailscale-Custom` | +| Named pipe | `Tailscale\tailscaled` | `Tailscale-Custom\tailscaled` | +| Registry | `SOFTWARE\Tailscale IPN` | `SOFTWARE\Tailscale-Custom IPN` | +| Policy registry | `Policies\Tailscale` | `Policies\Tailscale-Custom` | +| ProgramData | `C:\ProgramData\Tailscale` | `C:\ProgramData\Tailscale-Custom` | +| LocalAppData | `...\Tailscale` | `...\Tailscale-Custom` | +| TUN adapter | `Tailscale` | `Tailscale-Custom` | +| TUN GUID | `{37217669-...}` | `{47317669-...}` | +| Control URL | `https://controlplane.tailscale.com` | `https://vpn.softs.business` | + +--- + +## Danh sách files đã thay đổi + +### Nhóm 1: Đổi tên service / đường dẫn (Coexistence) + +| File | Thay đổi | +|------|----------| +| `cmd/tailscaled/tailscaled_windows.go` | `serviceName = "Tailscale-Custom"` | +| `cmd/tailscaled/tailscaled.go` | `defaultTunName() = "Tailscale-Custom"` | +| `paths/paths.go` | Named pipe path, state file path | +| `paths/paths_windows.go` | ACL directory check | +| `util/winutil/winutil_windows.go` | Registry keys | +| `util/syspolicy/source/policy_store_windows.go` | Policy registry paths | +| `net/tstun/tun_windows.go` | WintunTunnelType + GUID | +| `logpolicy/logpolicy.go` | Log directories | +| `log/filelogger/log.go` | Log file path | +| `clientupdate/clientupdate_windows.go` | Update cache path | +| `envknob/envknob.go` | Env file path | +| `ipn/auditlog/store.go` | Audit log path | + +### Nhóm 2: Đổi Control URL + +| File | Thay đổi | +|------|----------| +| `ipn/prefs.go` | `DefaultControlURL = "https://vpn.softs.business"` | +| `ipn/conf.go` | Default URL trong comment | +| `control/controlclient/direct.go` | Server URL references | +| `cmd/tailscale/cli/debug.go` | Debug command default | +| `cmd/tailscaled/debug.go` | Debug URL | +| `net/netmon/state.go` | Login endpoint | +| `net/captivedetection/endpoints.go` | Captive portal check | +| `util/winutil/policy/policy_windows.go` | Policy default URL | +| `util/syspolicy/syspolicy.go` | System policy default | + +### Nhóm 3: Thêm mới + +| File | Mô tả | +|------|-------| +| `cmd/tailscale-tray/main.go` | Windows system tray app | +| `cmd/tailscale-tray/icon.go` | Icon generation | +| `installer/TailscaleCustom.wxs` | WiX v5 MSI installer | + +--- + +## Chi tiết từng thay đổi + +### 1. `ipn/prefs.go` - Control URL mặc định +```go +// TRƯỚC: +const DefaultControlURL = "https://controlplane.tailscale.com" + +// SAU: +const DefaultControlURL = "https://vpn.softs.business" +``` + +Thêm `vpn.softs.business` vào `IsLoginServerSynonym()` để Tailscale nhận diện đây là server hợp lệ. + +### 2. `cmd/tailscaled/tailscaled_windows.go` - Service name +```go +// TRƯỚC: +const serviceName = "Tailscale" + +// SAU: +const serviceName = "Tailscale-Custom" +``` + +### 3. `cmd/tailscaled/tailscaled.go` - TUN device name +```go +// TRƯỚC (trong defaultTunName()): +case "windows": return "Tailscale" + +// SAU: +case "windows": return "Tailscale-Custom" +``` + +### 4. `paths/paths.go` - Named pipe & state paths +```go +// TRƯỚC: +DefaultTailscaledSocket = `\\.\pipe\ProtectedPrefix\Administrators\Tailscale\tailscaled` +stateFileInProgramData = `Tailscale\server-state.conf` + +// SAU: +DefaultTailscaledSocket = `\\.\pipe\ProtectedPrefix\Administrators\Tailscale-Custom\tailscaled` +stateFileInProgramData = `Tailscale-Custom\server-state.conf` +``` + +### 5. `net/tstun/tun_windows.go` - TUN adapter +```go +// TRƯỚC: +tun.WintunTunnelType = "Tailscale" +guid, _ := windows.GUIDFromString("{37217669-42da-4657-a55b-0d995d328250}") + +// SAU: +tun.WintunTunnelType = "Tailscale-Custom" +guid, _ := windows.GUIDFromString("{47317669-42da-4657-a55b-0d995d328250}") +``` + +> **Quan trọng**: GUID phải khác để 2 TUN adapter cùng tồn tại. + +### 6. `util/winutil/winutil_windows.go` - Registry +```go +// TRƯỚC: +regBase = `SOFTWARE\Tailscale IPN` +regPolicyBase = `SOFTWARE\Policies\Tailscale` + +// SAU: +regBase = `SOFTWARE\Tailscale-Custom IPN` +regPolicyBase = `SOFTWARE\Policies\Tailscale-Custom` +``` + +### 7. `control/controlclient/direct.go` - Server validation +Cập nhật các URL reference từ `controlplane.tailscale.com` sang `vpn.softs.business`. + +### 8. `logpolicy/logpolicy.go` - Log paths +```go +// TRƯỚC: +dir = filepath.Join(os.Getenv("ProgramData"), "Tailscale", "Logs") + +// SAU: +dir = filepath.Join(os.Getenv("ProgramData"), "Tailscale-Custom", "Logs") +``` + +--- + +## Build Windows Client + +### Yêu cầu +- Go 1.26+ (hoặc dùng `.\tool\go.exe` trong repo) +- GCC/MinGW (cho CGO, cần cho tray app) + +### Build CLI + Daemon +```powershell +cd + +# Build tailscale.exe (CLI) +.\tool\go.exe build -o .\dist\tailscale.exe ` + -ldflags "-X tailscale.com/version.longStamp=1.97.176-custom -X tailscale.com/version.shortStamp=1.97.176-custom" ` + tailscale.com/cmd/tailscale + +# Build tailscaled.exe (daemon/service) +.\tool\go.exe build -o .\dist\tailscaled.exe ` + -ldflags "-X tailscale.com/version.longStamp=1.97.176-custom -X tailscale.com/version.shortStamp=1.97.176-custom" ` + tailscale.com/cmd/tailscaled +``` + +### Build Tray App +```powershell +# Cần CGO_ENABLED=1 (cho systray) và -H=windowsgui (ẩn console) +$env:CGO_ENABLED="1" +.\tool\go.exe build -o .\dist\tailscale-tray.exe ` + -ldflags "-H=windowsgui" ` + tailscale.com/cmd/tailscale-tray +``` + +### Cần thêm `wintun.dll` +Copy `wintun.dll` từ: +- https://www.wintun.net/ (tải chính thức) +- Hoặc từ `C:\Program Files\Tailscale\wintun.dll` nếu đã cài Tailscale gốc + +```powershell +Copy-Item "C:\Program Files\Tailscale\wintun.dll" .\dist\ +``` + +--- + +## Build Linux Client + +### Build CLI + Daemon +```bash +cd + +# Lấy Go toolchain +./tool/go build -o ./dist/tailscale \ + -ldflags "-X tailscale.com/version.longStamp=1.97.176-custom -X tailscale.com/version.shortStamp=1.97.176-custom" \ + tailscale.com/cmd/tailscale + +./tool/go build -o ./dist/tailscaled \ + -ldflags "-X tailscale.com/version.longStamp=1.97.176-custom -X tailscale.com/version.shortStamp=1.97.176-custom" \ + tailscale.com/cmd/tailscaled +``` + +### Cài đặt trên Linux +```bash +# Copy binaries +sudo cp dist/tailscale /usr/local/bin/ +sudo cp dist/tailscaled /usr/local/bin/ + +# Tạo systemd service +sudo cat > /etc/systemd/system/tailscale-custom.service << 'EOF' +[Unit] +Description=Tailscale-Custom VPN daemon +After=network-online.target +Wants=network-online.target + +[Service] +ExecStart=/usr/local/bin/tailscaled --state=/var/lib/tailscale-custom/tailscaled.state --socket=/var/run/tailscale-custom/tailscaled.sock +Restart=on-failure +RuntimeDirectory=tailscale-custom +StateDirectory=tailscale-custom + +[Install] +WantedBy=multi-user.target +EOF + +sudo systemctl daemon-reload +sudo systemctl enable --now tailscale-custom +``` + +### Kết nối +```bash +sudo tailscale up --login-server https://vpn.softs.business --accept-dns=false \ + --socket /var/run/tailscale-custom/tailscaled.sock +``` + +> **Lưu ý Linux**: Trên Linux, custom Tailscale dùng `--socket` và `--state` khác path để tránh xung đột với Tailscale gốc. Không cần đổi tên service vì Linux dùng socket file thay vì named pipe. + +--- + +## Tạo MSI Installer (Windows) + +### Yêu cầu +- .NET SDK +- WiX Toolset v5: `dotnet tool install --global wix` +- WiX Util extension: `wix extension add WixToolset.Util.wixext` + +### Cấu trúc thư mục installer +``` +dist/ +├── tailscale.exe # CLI +├── tailscaled.exe # Daemon/service +├── tailscale-tray.exe # System tray app +└── wintun.dll # TUN driver + +installer/ +└── TailscaleCustom.wxs # WiX definition +``` + +### Build MSI +```powershell +wix build -o .\dist\TailscaleCustom.msi ` + -ext WixToolset.Util.wixext ` + .\installer\TailscaleCustom.wxs +``` + +### MSI bao gồm: +- Cài `tailscaled.exe` làm Windows Service (auto-start) +- Cài `tailscale.exe` (CLI) và thêm vào PATH +- Cài `tailscale-tray.exe` với auto-start qua Registry +- Cài `wintun.dll` (TUN driver) +- Shortcuts trên Desktop và Start Menu +- UpgradeCode riêng: `E1F2A3B4-C5D6-4E7F-8A9B-0C1D2E3F4A5B` + +--- + +## Tray App (Windows) + +### Tính năng +- **System tray icon**: Xanh = kết nối, xám = ngắt kết nối +- **Status**: Hiển thị trạng thái, IP, hostname +- **Connect / Disconnect**: Bật/tắt VPN +- **Account**: Submenu hiển thị tất cả profiles, chuyển đổi giữa các server +- **Add Server**: Dialog nhập URL server mới → tạo profile mới → mở trình duyệt login +- **Single instance**: Chỉ cho chạy 1 instance qua Windows Mutex + +### Kiến trúc code +``` +cmd/tailscale-tray/ +├── main.go # App logic, systray menu, Win32 dialogs +└── icon.go # ICO generation (16x16, green/gray) +``` + +**Pattern**: Dùng per-item `onClick` goroutine (giống official Tailscale systray): +```go +func onClick(ctx context.Context, item *systray.MenuItem, fn func()) { + go func() { + for { + select { + case <-ctx.Done(): return + case <-item.ClickedCh: fn() + } + } + }() +} +``` + +### Dependency +- `fyne.io/systray` - Cross-platform system tray +- `golang.org/x/sys/windows` - Win32 API +- `tailscale.com/client/local` - IPC client đến tailscaled + +--- + +## Cách deploy lên máy mới + +### Windows - MSI Installer +```powershell +# Cài đặt (silent) +msiexec /i TailscaleCustom.msi /qn + +# Kết nối (mở cmd/powershell) +tailscale up --login-server https://vpn.softs.business --accept-dns=false + +# Hoặc dùng pre-auth key (tự động, không cần approve trên server) +tailscale up --login-server https://vpn.softs.business --accept-dns=false --authkey +``` + +### Linux - Manual install +```bash +# Copy binaries +sudo cp tailscale tailscaled /usr/local/bin/ + +# Tạo service (xem phần Build Linux ở trên) +sudo systemctl enable --now tailscale-custom + +# Kết nối +sudo tailscale up --login-server https://vpn.softs.business --accept-dns=false \ + --socket /var/run/tailscale-custom/tailscaled.sock + +# Hoặc dùng pre-auth key +sudo tailscale up --login-server https://vpn.softs.business --accept-dns=false \ + --authkey --socket /var/run/tailscale-custom/tailscaled.sock +``` + +### Quan trọng: `--accept-dns=false` +Luôn dùng flag này để tránh Tailscale ghi đè DNS config của máy, gây mất mạng internet. + +--- + +## TODO cho phiên bản tiếp theo + +### Web Admin App (Docker) +- [ ] Dashboard: tổng nodes, online/offline +- [ ] Nodes list: approve/reject/delete +- [ ] Users management: CRUD +- [ ] Pre-auth keys: tạo/quản lý +- [ ] Dùng Headscale REST API (xem `HEADSCALE_SETUP.md`) + +### Hoàn thiện Linux Client +- [ ] Build script cho Linux (amd64, arm64) +- [ ] Tạo `.deb` / `.rpm` package +- [ ] Systemd service file đóng gói sẵn +- [ ] Test coexistence với Tailscale gốc trên Linux + +### Hoàn thiện Windows Client +- [ ] Code signing cho exe/msi +- [ ] Auto-update mechanism +- [ ] Tray app: hiển thị danh sách peers +- [ ] Tray app: copy IP khi click diff --git a/docs/HEADSCALE_SETUP.md b/docs/HEADSCALE_SETUP.md new file mode 100644 index 000000000..a9063d757 --- /dev/null +++ b/docs/HEADSCALE_SETUP.md @@ -0,0 +1,278 @@ +# Hướng dẫn cài đặt Headscale Server + +## Mục lục +1. [Tổng quan](#tổng-quan) +2. [Yêu cầu hệ thống](#yêu-cầu-hệ-thống) +3. [Cài đặt Headscale bằng Docker](#cài-đặt-headscale-bằng-docker) +4. [Cấu hình domain & reverse proxy](#cấu-hình-domain--reverse-proxy) +5. [Quản lý users & nodes](#quản-lý-users--nodes) +6. [API Reference cho Web Admin](#api-reference-cho-web-admin) + +--- + +## Tổng quan + +Headscale là bản self-hosted của control server Tailscale. Nó cho phép: +- Tạo mạng riêng ảo (VPN mesh) giữa các máy +- Không phụ thuộc vào server của Tailscale +- Toàn quyền quản lý users, nodes, ACL + +**Kiến trúc:** +``` +┌─────────────────┐ ┌──────────────────┐ ┌─────────────────┐ +│ Client Windows │────▶│ Headscale │◀────│ Client Linux │ +│ (Tailscale- │ │ (vpn.softs. │ │ (Tailscale- │ +│ Custom) │ │ business) │ │ Custom) │ +└─────────────────┘ │ Port: 443 │ └─────────────────┘ + │ gRPC + HTTPS │ + └──────────────────┘ + ▲ + │ + ┌──────────────────┐ + │ Web Admin App │ + │ (quản lý nodes) │ + └──────────────────┘ +``` + +--- + +## Yêu cầu hệ thống + +- VPS Linux (Ubuntu 22.04+ hoặc Debian 12+) +- Docker + Docker Compose +- Domain trỏ về VPS (ví dụ: `vpn.softs.business`) +- Port 443 (HTTPS) mở + +--- + +## Cài đặt Headscale bằng Docker + +### 1. Tạo thư mục cấu hình + +```bash +mkdir -p /opt/headscale/config /opt/headscale/data +``` + +### 2. Tạo file cấu hình `/opt/headscale/config/config.yaml` + +```yaml +server_url: https://vpn.softs.business +listen_addr: 0.0.0.0:8080 +metrics_listen_addr: 0.0.0.0:9090 + +# gRPC cho Tailscale client +grpc_listen_addr: 0.0.0.0:50443 +grpc_allow_insecure: false + +# Database +database: + type: sqlite + sqlite: + path: /var/lib/headscale/db.sqlite + +# Khoảng IP cấp cho các node +prefixes: + v4: 100.64.0.0/10 + v6: fd7a:115c:a1e0::/48 + +# DERP (relay khi P2P không được) +derp: + server: + enabled: true + region_id: 999 + region_code: custom + region_name: "Custom DERP" + stun_listen_addr: 0.0.0.0:3478 + + urls: [] + paths: [] + auto_update_enabled: true + update_frequency: 24h + +# DNS - KHÔNG bật MagicDNS để tránh xung đột +dns: + magic_dns: false + base_domain: vpn.local + nameservers: + global: [] + +# Thời gian hiệu lực node key +node_key_expiry: 0 # không hết hạn + +# Bật API (quan trọng cho Web Admin) +# API key tạo bằng: headscale apikeys create +``` + +### 3. Tạo `docker-compose.yml` + +```yaml +version: "3.9" +services: + headscale: + image: headscale/headscale:latest + container_name: headscale + restart: always + volumes: + - /opt/headscale/config:/etc/headscale + - /opt/headscale/data:/var/lib/headscale + ports: + - "8080:8080" # HTTP API + - "9090:9090" # Metrics + - "3478:3478/udp" # STUN + command: serve + environment: + - TZ=Asia/Ho_Chi_Minh +``` + +### 4. Reverse proxy (Nginx) + +```nginx +server { + listen 443 ssl http2; + server_name vpn.softs.business; + + ssl_certificate /etc/ssl/certs/vpn.softs.business.crt; + ssl_certificate_key /etc/ssl/private/vpn.softs.business.key; + + location / { + proxy_pass http://127.0.0.1:8080; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_buffering off; + proxy_read_timeout 86400s; + proxy_send_timeout 86400s; + } +} +``` + +### 5. Khởi động + +```bash +cd /opt/headscale +docker compose up -d + +# Tạo user đầu tiên +docker exec headscale headscale users create default + +# Tạo API key (dùng cho Web Admin) +docker exec headscale headscale apikeys create --expiration 365d +# Lưu lại key này! +``` + +--- + +## Quản lý users & nodes + +### Tạo user +```bash +docker exec headscale headscale users create +``` + +### Đăng ký node (sau khi client login) +```bash +docker exec headscale headscale nodes register --key --user +``` + +### Liệt kê nodes +```bash +docker exec headscale headscale nodes list +``` + +### Xóa node +```bash +docker exec headscale headscale nodes delete --identifier +``` + +### Tạo pre-auth key (để client tự đăng ký, không cần approve thủ công) +```bash +docker exec headscale headscale preauthkeys create --user --reusable --expiration 24h +``` + +Client dùng pre-auth key: +```bash +tailscale up --login-server https://vpn.softs.business --authkey +``` + +--- + +## API Reference cho Web Admin + +Headscale có REST API đầy đủ. Web Admin app sẽ dùng các endpoint này: + +### Authentication +Mọi request cần header: +``` +Authorization: Bearer +``` + +### Endpoints chính + +| Method | Endpoint | Mô tả | +|--------|----------|-------| +| `GET` | `/api/v1/user` | Danh sách users | +| `POST` | `/api/v1/user` | Tạo user mới | +| `DELETE` | `/api/v1/user/{name}` | Xóa user | +| `GET` | `/api/v1/node` | Danh sách tất cả nodes | +| `GET` | `/api/v1/node/{nodeId}` | Chi tiết 1 node | +| `DELETE` | `/api/v1/node/{nodeId}` | Xóa node | +| `POST` | `/api/v1/node/{nodeId}/expire` | Expire node | +| `POST` | `/api/v1/node/register` | Đăng ký node mới | +| `GET` | `/api/v1/node/{nodeId}/routes` | Routes của node | +| `POST` | `/api/v1/routes/{routeId}/enable` | Bật route | +| `POST` | `/api/v1/routes/{routeId}/disable` | Tắt route | +| `GET` | `/api/v1/preauthkey` | Danh sách pre-auth keys | +| `POST` | `/api/v1/preauthkey` | Tạo pre-auth key | +| `POST` | `/api/v1/preauthkey/expire` | Expire key | +| `GET` | `/api/v1/apikey` | Danh sách API keys | +| `POST` | `/api/v1/apikey` | Tạo API key | + +### Ví dụ: Lấy danh sách nodes +```bash +curl -s -H "Authorization: Bearer " \ + https://vpn.softs.business/api/v1/node | jq +``` + +Response: +```json +{ + "nodes": [ + { + "id": "1", + "machineKey": "mkey:...", + "nodeKey": "nodekey:...", + "name": "thinkpad", + "user": { "id": "1", "name": "huanld" }, + "ipAddresses": ["100.64.0.1", "fd7a:115c:a1e0::1"], + "online": true, + "lastSeen": "2026-04-10T16:52:30Z", + "createdAt": "2026-04-10T16:55:04Z", + "registerMethod": "REGISTER_METHOD_CLI" + } + ] +} +``` + +### Ví dụ: Approve node mới (thay vì chạy lệnh thủ công) +```bash +# Lấy danh sách nodes chờ approve +curl -s -H "Authorization: Bearer " \ + https://vpn.softs.business/api/v1/node + +# Register node bằng key +curl -X POST -H "Authorization: Bearer " \ + -H "Content-Type: application/json" \ + -d '{"key": "", "user": "huanld"}' \ + https://vpn.softs.business/api/v1/node/register +``` + +### Web Admin cần hiển thị: +1. **Dashboard**: Tổng nodes, online/offline, users +2. **Nodes list**: Tên, IP, user, trạng thái online, last seen +3. **Approve**: Nút approve cho nodes mới (gọi register API) +4. **Users**: CRUD users +5. **Pre-auth Keys**: Tạo/quản lý keys để client tự đăng ký