Site icon ZingServer

Hướng dẫn xây dựng Mesh Network trên VPS bằng Headscale: Kết nối dev team và Database an toàn (2026)

Hướng dẫn xây dựng Mesh Network trên VPS bảo mật Database bằng Headscale

Giải pháp mạng nội bộ Headscale trên VPS cho đội ngũ lập trình

Mở thẳng cổng 5432 của PostgreSQL hoặc 3306 của MySQL ra Internet là một hành động tiềm ẩn nhiều rủi ro, tạo điều kiện cho các hệ thống rà soát tự động dò tìm lỗ hổng. Trong khi đó, việc quản lý danh sách whitelist IP tĩnh lại trở thành gánh nặng vận hành khi developer làm việc remote, di chuyển liên tục giữa quán cafe và mạng gia đình khiến IP thay đổi không ngừng. Nhiều kỹ sư hệ thống tìm đến giải pháp VPN truyền thống như WireGuard thuần, nhưng việc cấp phát key thủ công, sửa file config liên tục mỗi khi có nhân sự mới lại tiêu tốn rất nhiều thời gian.

Để giải quyết bài toán này, việc xây dựng Mesh Network trên VPS bằng Headscale đang được ứng dụng rộng rãi trong các dự án công nghệ.

Nỗi đau kinh điển khi mở cổng Database cho team remote

Khi vận hành hạ tầng cho một đội ngũ phát triển phân tán, các Sysadmin và DevOps thường xuyên phải đối mặt với những vấn đề nhức nhối về hiệu năng và bảo mật mạng:

Mô hình Mesh Network cho phép dữ liệu truyền tải ngang hàng (Peer-to-Peer), khắc phục điểm nghẽn băng thông của hệ thống VPN tập trung.

Sự dịch chuyển kiến trúc: Từ WireGuard thuần sang Headscale

Để khắc phục các điểm yếu của VPN truyền thống, kiến trúc mạng hiện đại phân tách rõ ràng hệ thống thành hai phần: Control Plane (Mặt phẳng điều khiển) và Data Plane (Mặt phẳng dữ liệu).

Việc tự host Headscale mang lại lợi thế về quyền kiểm soát dữ liệu (Data Sovereignty). Tổ chức không phải gửi siêu dữ liệu (metadata), thông tin thiết bị hay file log lên hạ tầng đám mây của các nhà cung cấp bên thứ ba. Hơn nữa, việc tự vận hành hệ thống này giúp tối ưu chi phí cho các dự án có tốc độ scale nhân sự nhanh, vì bạn không bị tính phí theo số lượng người dùng hay thiết bị.

Chuẩn bị hạ tầng & sơ đồ kiến trúc để xây dựng Mesh Network trên VPS

Việc xây dựng Mesh Network trên VPS không tiêu tốn nhiều tài nguyên tính toán, bởi máy chủ chỉ làm nhiệm vụ điều hướng thông tin cấu hình. Lưu lượng truy vấn Database nặng nề sẽ đi trực tiếp (Peer-to-Peer) giữa máy Dev và DB Server.

Yêu cầu hạ tầng cơ bản:

Các port cần mở trên Firewall của VPS (Security Group/UFW):

Headscale VPS chỉ làm nhiệm vụ điều phối (Control Plane), trong khi lưu lượng truy vấn Database đi trực tiếp qua đường hầm WireGuard (Data Plane).

Thực chiến 5 bước cấu hình Headscale, Headplane và Caddy

Để hệ thống hoạt động ổn định và có tính trực quan cao, hạ tầng sẽ được đóng gói qua Docker Compose, kết hợp Caddy (tự động HTTPS) và Headplane (Giao diện Web UI quản trị hiện đại).

Bước 1: Khai báo Docker Compose và sinh API Key an toàn

Nhiều hệ thống gặp lỗi khi khởi chạy toàn bộ container cùng lúc vì Headplane cần một API Key từ Headscale để giao tiếp, nhưng API Key lại chưa được tạo. Để xử lý bài toán này gọn gàng mà không sinh ra container dư thừa, chúng ta sẽ khai báo tệp docker-compose.yml trước, sau đó mượn volume để sinh key.

Tạo cấu trúc thư mục trên VPS:

mkdir -p /opt/headscale/{config,data}

Di chuyển vào thư mục vừa tạo:

cd /opt/headscale

Tải tệp cấu hình mẫu từ repository chính thức:

wget -O ./config/config.yaml https://raw.githubusercontent.com/juanfont/headscale/main/config-example.yaml

Chỉnh sửa tệp config.yaml. Với các phiên bản Headscale v0.29 trở lên, cú pháp IP đã thay đổi. Bạn cần sử dụng block prefixes thay cho định dạng cũ để tránh lỗi bỏ qua cấu hình:

server_url: https://vpn.congtycua.com
listen_addr: 0.0.0.0:8080

# Cấu hình IP chuẩn cho dải mạng ảo
prefixes:
  v4: 100.64.0.0/10
  allocation: sequential

database:
  type: sqlite
  sqlite:
    path: /var/lib/headscale/db.sqlite

# Bật MagicDNS để phân giải tên miền nội bộ
dns_config:
  magic_dns: true
  base_domain: tailnet.local
  nameservers:
    - 1.1.1.1
    - 8.8.8.8

# Khai báo file Policy (Sẽ tạo ở phần Zero Trust sau)
policy:
  mode: file
  path: /etc/headscale/policy.hujson

Tạo tệp docker-compose.yml. Việc ghim cứng phiên bản v0.29.3 cho Headscale và 0.7.0 cho Headplane được khuyên dùng để bảo vệ hệ thống khỏi các lỗi đứt gãy (breaking changes):

version: '3.8'

services:
  headscale:
    image: headscale/headscale:0.29.3
    container_name: headscale
    restart: unless-stopped
    volumes:
      - ./config:/etc/headscale
      - ./data:/var/lib/headscale
    command: serve
    networks:
      - mesh-net

  headplane:
    image: ghcr.io/tale/headplane:0.7.0
    container_name: headplane
    restart: unless-stopped
    environment:
      - HEADSCALE_URL=http://headscale:8080
      # Sẽ điền mã API Key vào đây sau khi sinh
      - HEADSCALE_API_KEY=your_api_key_here
      # Tạo một chuỗi ngẫu nhiên làm secret cookie
      - COOKIE_SECRET=random_string_xyz_123
    networks:
      - mesh-net

  caddy:
    image: caddy:latest
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config
    networks:
      - mesh-net

networks:
  mesh-net:

volumes:
  caddy_data:
  caddy_config:

Mượn cấu hình volume từ tệp Compose vừa tạo để sinh API Key (lệnh --rm giúp container tự động xóa sau khi chạy xong nhiệm vụ, giữ hệ thống sạch sẽ):

docker-compose run --rm headscale headscale apikeys create --expiration 9999h

Sao chép chuỗi mã API Key vừa sinh ra, mở lại file docker-compose.yml và dán vào biến HEADSCALE_API_KEY.

Bước 2: Tích hợp định tuyến Caddy và khởi chạy hệ thống

Tạo tệp Caddyfile để xử lý routing nội bộ và cấp SSL. Ở đây, ta áp dụng chiến lược định tuyến ngược: ưu tiên phân luồng đường dẫn quản trị cho Headplane và đẩy toàn bộ traffic còn lại về Headscale để không đánh rơi các endpoint ngầm của Tailscale client (như /machine, /derp):

vpn.congtycua.com {
    # Truy cập Web UI Headplane qua thư mục /admin
    reverse_proxy /admin* headplane:3000

    # Đẩy toàn bộ API và traffic lưới mạng còn lại về Headscale
    reverse_proxy * headscale:8080
}

Khởi chạy hệ thống hoàn chỉnh:

docker-compose up -d

Lúc này, bạn có thể truy cập https://vpn.congtycua.com/admin trên trình duyệt để sử dụng giao diện Headplane, giúp quản lý user, node và policy trực quan.

Bước 3: Khởi tạo User và cấp Auth Key chuyên biệt

Từ phiên bản v0.29, Headscale phân định rất rõ giữa thiết bị của người dùng cá nhân (User-owned) và thiết bị máy chủ hạ tầng (Tagged devices). Mọi thao tác qua CLI cũng yêu cầu ID số học thay vì tên chuỗi.

Khởi tạo không gian làm việc cho team:

docker exec -it headscale headscale users create dev-team

Tra cứu ID của user vừa tạo:

docker exec -it headscale headscale users list

(Giả sử kết quả trả về ID của dev-team là 1).

Tạo Key cho Developer (User-owned):

Tạo một Pre-auth key có khả năng dùng nhiều lần (reusable) với thời hạn 30 ngày bằng tham số -u kết hợp ID:

docker exec -it headscale headscale preauthkeys create -u 1 --reusable --expiration 720h

Hệ thống cung cấp chuỗi hskey-auth-xxxx.... Dùng mã này để dev kết nối máy tính cá nhân.

Tạo Key cho Máy chủ (Infrastructure/Tagged devices):

Đối với Database Server, bạn không nên dùng key của user thông thường. Hãy tạo một Pre-auth Key được nhúng sẵn nhãn mạng. Thao tác này sẽ tự động gán thiết bị vào nhóm hệ thống tagged-devices và cấp thẻ tag:database mà không cần cấu hình rườm rà:

docker exec -it headscale headscale preauthkeys create --tags tag:database --reusable --expiration 720h

Lưu lại mã hskey-auth-yyyy... này dành riêng cho hạ tầng server.

Bước 4: Cài đặt Tailscale Client và kích hoạt Tailscale SSH trên Database

Trên Database Server (chạy Ubuntu/Debian), tải và thực thi script cài đặt Tailscale:

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

Kích hoạt dịch vụ khởi chạy cùng hệ thống:

sudo systemctl enable --now tailscaled

Thay vì quản lý SSH Key (authorized_keys) hoặc mở port 22 đối mặt với nguy cơ bị brute-force, bạn có thể áp dụng công nghệ Tailscale SSH. Tính năng này cho phép Sysadmin kết nối vào server dựa trên danh tính mạng Mesh được cấp quyền trong ACL.

Kết nối server vào mạng lưới bằng Key có sẵn Tag và kích hoạt cờ SSH:

sudo tailscale up --login-server https://vpn.congtycua.com --authkey hskey-auth-yyyy-MA-CUA-DB --ssh

Nhờ key đã nhúng sẵn tag từ Bước 3, máy chủ sẽ tự động nhận diện danh tính tag:database.

Bước 5: Join máy Dev vào mạng lưới & ứng dụng MagicDNS

Trên các thiết bị cá nhân (Windows, macOS, Linux), developer cài đặt ứng dụng Tailscale chính thức và kết nối bằng lệnh:

tailscale up --login-server https://vpn.congtycua.com --authkey hskey-auth-xxxx-MA-CUA-DEV --accept-dns=true

Tham số --accept-dns=true cho phép thiết bị nhận cấu hình MagicDNS. Thay vì nhớ địa chỉ IP nội bộ 100.64.0.10, developer có thể ping hoặc truy vấn database thông qua tên định danh thân thiện:

ping db-prod.tailnet.local

Thiết lập Zero Trust ACL và Defense-in-Depth

Triết lý bảo mật Zero Trust (Không tin tưởng mặc định) yêu cầu mọi kết nối phải được xác thực và chỉ mở đúng port dịch vụ được cấu hình. Nếu bỏ qua bước thiết lập Policy, mạng Mesh sẽ hoạt động ở chế độ Allow-all, cho phép các node truy cập chéo tự do, gây rủi ro lớn.

Khai báo Policy, Grants và tích hợp Automate Tests

Trong hệ thống Headscale/Tailscale, mạng lưới chỉ tự động chuyển sang trạng thái chặn mặc định (Deny-by-default) khi hệ thống đọc thấy sự tồn tại của mảng acls. Ngay cả khi bạn sử dụng khối grants (cú pháp phân quyền hiện đại), việc khai báo mảng acls: [] rỗng là thao tác bắt buộc để khóa các luồng traffic tự do.

Đặc biệt, ở phiên bản Headscale v0.29+, bạn có thể sử dụng khối tests để tự động xác thực tính đúng đắn của các luật ACLs/Grants, đảm bảo hệ thống không bị cấu hình sai lệch.

Tạo tệp policy.hujson tại thư mục /opt/headscale/config/:

{
  // Bắt buộc phải có mảng này để kích hoạt chặn mọi luồng traffic mặc định
  "acls": [],

  "groups": {
    "group:devs": ["dev-team"]
  },
  "tagOwners": {
    "tag:database": ["group:devs"] 
  },
  "grants": [
    // Cấp quyền cho nhóm Dev truy cập node tag:database chỉ qua cổng TCP 5432
    {
      "src": ["group:devs"],
      "dst": ["tag:database"],
      "ip": ["tcp:5432"]
    }
  ],
  "ssh": [
    // Cho phép nhóm Dev sử dụng tính năng Tailscale SSH vào DB Server.
    // Đặt action là "accept" để luồng SSH hoạt động tự động dựa trên ACL, tránh bị treo phiên xác thực.
    {
      "action": "accept",
      "src": ["group:devs"],
      "dst": ["tag:database"],
      "users": ["ubuntu", "root"]
    }
  ],
  "tests": [
    // Tự động kiểm thử xem Dev có được vào cổng 5432 và bị chặn ở cổng 80 hay không
    {
      "src": "user1@group:devs",
      "accept": ["tag:database:5432"],
      "deny": ["tag:database:80"]
    }
  ]
}

Kiểm tra cú pháp và áp dụng thay đổi vào hệ thống (hoặc bạn có thể dán cấu hình này trực tiếp trên giao diện Headplane):

docker exec -it headscale kill -HUP 1

Đóng băng Firewall vật lý và liên kết IP nội bộ

Mạng Mesh giải quyết việc phân quyền ở lớp mạng ảo (L3/L4 ảo). Để đạt phương án bảo mật nhiều lớp (Defense-in-Depth), hạ tầng vật lý của Database Server cần được bảo vệ nghiêm ngặt bằng tường lửa UFW cục bộ.

Sử dụng UFW để chặn mọi traffic từ Internet, chỉ cho phép dữ liệu lưu thông qua card mạng ảo tailscale0:

sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow in on tailscale0

Port 22 vật lý có thể chặn vì đã dùng Tailscale SSH:

sudo ufw delete allow 22/tcp

Kích hoạt tường lửa UFW:

sudo ufw enable

Tiếp đó, điều chỉnh cấu hình hệ quản trị cơ sở dữ liệu. Mở file postgresql.conf và giới hạn IP lắng nghe (listen) để dịch vụ không nhận diện IP Public:

listen_addresses = 'localhost, 100.64.0.10'

Xác thực Database ở lớp ứng dụng

Headscale ACL chỉ kiểm soát luồng gói tin mạng. Nó quyết định thiết bị nào được phép tạo kết nối TCP tới cổng 5432, nhưng không can thiệp vào quyền hạn đọc/ghi cấu trúc bảng dữ liệu bên trong.

Do đó, chốt chặn bảo mật ở lớp ứng dụng vẫn là yếu tố không thể bỏ qua để tối ưu database VPS Linux một cách an toàn. Quản trị viên cần tinh chỉnh tệp pg_hba.conf để yêu cầu xác thực bằng mật khẩu mạnh (sử dụng thuật toán scram-sha-256), đồng thời thiết lập Role phù hợp cho từng developer. Việc kết hợp chặt chẽ giữa bảo mật lớp mạng (Mesh VPN kiểm soát truy cập network) và lớp ứng dụng (Database Auth kiểm soát truy cập data) sẽ thiết lập một kiến trúc hạ tầng kiên cố.

Kết hợp Headscale ACLs và tường lửa cục bộ tạo ra hệ thống phòng thủ nhiều lớp (Defense-in-Depth) vững chắc cho cơ sở dữ liệu.

Câu hỏi thường gặp (FAQ)

1. Headscale có tính phí không?

Không. Headscale là mã nguồn mở hoàn toàn, không giới hạn số lượng user hay thiết bị. Bạn chỉ phải chi trả tiền thuê VPS hạ tầng.

2. Cần VPS cấu hình mạnh để chạy Headscale không?

Không. Headscale chỉ xử lý thông tin điều phối (Control Plane), không gánh traffic dữ liệu thực tế. Một VPS 1 vCPU, 1-2GB RAM đủ sức phục vụ hàng trăm node.

3. Nếu VPS Headscale ngừng hoạt động, mạng Mesh có bị ngắt kết nối?

Không ngay lập tức. Các thiết bị đã kết nối vẫn duy trì liên lạc trực tiếp (P2P) bình thường. Tuy nhiên, bạn sẽ không thể thêm node mới hoặc cập nhật Policy cho đến khi máy chủ Headscale online trở lại.

4. Dữ liệu truyền qua Headscale có bị lộ không?

Không. Dữ liệu thực tế được mã hóa đầu cuối (End-to-End Encryption) bằng WireGuard và truyền trực tiếp giữa các thiết bị. VPS Headscale hoàn toàn không nhìn thấy hay can thiệp vào gói tin dữ liệu này.

5. Tailscale SSH có an toàn hơn dùng cổng 22 vật lý?

Có. Việc dùng Tailscale SSH giúp bạn đóng hoàn toàn port 22 ra Internet, tránh bị brute-force. Việc xác thực được xử lý qua danh tính mạng Mesh thay vì quản lý file authorized_keys thủ công.

6. Có bắt buộc phải dùng Headplane không?

Không bắt buộc nhưng được khuyên dùng. Bạn hoàn toàn có thể quản lý Headscale qua giao diện dòng lệnh (CLI). Headplane chỉ đóng vai trò giao diện Web UI giúp thao tác trực quan và tiết kiệm thời gian hơn.

Kết luận

Quá trình tích hợp Headscale và Headplane cung cấp cho đội ngũ vận hành một bộ công cụ điều phối mạng trực quan. Việc xây dựng Mesh Network trên VPS mang lại một môi trường làm việc thông suốt cho dev team, đảm bảo dữ liệu truyền tải được mã hóa an toàn, đồng thời giúp tổ chức kiểm soát hạ tầng bảo mật theo cách chủ động.

Tài liệu tham khảo

Exit mobile version