VPN truyền thống bắt đầu vỡ trận khi hạ tầng lớn dần
Quản lý vài chục server trải dài trên nhiều cloud provider — AWS ở Virginia, Hetzner ở Nuremberg, thêm mấy VPS ở Singapore — và bạn sẽ sớm nhận ra OpenVPN hay WireGuard theo mô hình hub-and-spoke không còn phù hợp nữa. Tất cả traffic phải đi qua server trung tâm. Latency tăng. Server đó mà chết là cả mạng tắt.
Slack đối mặt đúng vấn đề này ở quy mô hàng nghìn node. Họ tự xây và open-source Nebula — một mesh VPN overlay, trong đó mỗi node kết nối trực tiếp peer-to-peer với nhau sau khi xác thực qua một lighthouse (node chỉ đường, không relay traffic). Không còn điểm chết đơn lẻ. Không còn bottleneck.
Mình đã dùng Nebula để kết nối 3 VPS ở 3 datacenter khác nhau và một laptop dev. Mọi thứ chạy sau 30 phút setup. Latency giữa hai node cùng region thấp hơn ~15ms so với WireGuard qua relay.
Cơ chế hoạt động của Nebula
Mỗi node nhận một IP ảo trong dải bạn tự chọn (thường là 192.168.100.0/24). Traffic giữa các node mã hóa bằng Noise Protocol Framework — cùng nền tảng với WireGuard, nhưng kiến trúc khác hoàn toàn. Bốn điểm tạo nên sự khác biệt:
- Lighthouse: Node có IP public, giúp các node khác tìm thấy nhau (hoạt động như STUN server). Không relay traffic, chỉ làm discovery.
- Peer-to-peer thực sự: Sau discovery, hai node kết nối thẳng qua UDP hole punching — kể cả khi cả hai đều sau NAT.
- Certificate-based auth: Mỗi node có certificate ký bởi CA của bạn. Không có cert hợp lệ thì không vào được mạng, đơn giản vậy thôi.
- Firewall nhúng trong config: Kiểm soát traffic ở tầng overlay, không cần iptables riêng.
Cài đặt Nebula
Yêu cầu
- Ít nhất 1 server có IP public (làm lighthouse)
- Linux/macOS/Windows đều hỗ trợ
- UDP port 4242 mở trên firewall của lighthouse
Tải binary
Trên mỗi node (kể cả lighthouse), tải binary từ GitHub releases:
# Trên Linux x86_64
wget https://github.com/slackhq/nebula/releases/latest/download/nebula-linux-amd64.tar.gz
tar -xzf nebula-linux-amd64.tar.gz
sudo mv nebula nebula-cert /usr/local/bin/
Tạo CA và certificate cho từng node
Bước này chạy một lần duy nhất trên máy admin, sau đó phân phối cert đến từng node qua scp. Quan trọng: ca.key không bao giờ rời khỏi máy này.
# Tạo CA
nebula-cert ca -name "MyInfra CA"
# Sinh ra: ca.crt và ca.key — giữ ca.key CỰC KỲ bí mật
# Tạo cert cho lighthouse (IP ảo: 192.168.100.1)
nebula-cert sign -name "lighthouse" \
-ip "192.168.100.1/24" \
-ca-crt ca.crt -ca-key ca.key
# Sinh ra: lighthouse.crt, lighthouse.key
# Tạo cert cho server app (IP ảo: 192.168.100.10)
nebula-cert sign -name "app-server" \
-ip "192.168.100.10/24" \
-groups "servers" \
-ca-crt ca.crt -ca-key ca.key
# Tạo cert cho laptop dev (IP ảo: 192.168.100.50)
nebula-cert sign -name "dev-laptop" \
-ip "192.168.100.50/24" \
-groups "developers" \
-ca-crt ca.crt -ca-key ca.key
Khi cần tính subnet cho dải IP overlay, mình hay dùng toolcraft.app/vi/tools/developer/ip-subnet-calculator — nhập CIDR là ra ngay network range, broadcast, số host tối đa. Tiện hơn nhiều so với tính tay.
Cấu hình chi tiết
Config cho Lighthouse
Tạo file /etc/nebula/config.yaml trên lighthouse server:
pki:
ca: /etc/nebula/ca.crt
cert: /etc/nebula/lighthouse.crt
key: /etc/nebula/lighthouse.key
lighthouse:
am_lighthouse: true
listen:
host: 0.0.0.0
port: 4242
punchy:
punch: true
logging:
level: info
firewall:
outbound:
- port: any
proto: any
host: any
inbound:
- port: any
proto: icmp
host: any
Config cho node thông thường (app-server, dev-laptop)
pki:
ca: /etc/nebula/ca.crt
cert: /etc/nebula/app-server.crt
key: /etc/nebula/app-server.key
lighthouse:
am_lighthouse: false
interval: 60
hosts:
- "192.168.100.1" # IP ảo của lighthouse
static_host_map:
"192.168.100.1": ["203.0.113.10:4242"] # IP public thật của lighthouse
listen:
host: 0.0.0.0
port: 4242
punchy:
punch: true
respond: true
logging:
level: info
firewall:
outbound:
- port: any
proto: any
host: any
inbound:
- port: any
proto: icmp
host: any
# Cho phép SSH từ group developers
- port: 22
proto: tcp
groups:
- developers
# Cho phép app traffic giữa các server
- port: 8080
proto: tcp
groups:
- servers
Deploy cert và chạy thử
Copy cert lên từng node rồi test trước khi đưa vào systemd:
# Copy lên lighthouse
scp ca.crt lighthouse.crt lighthouse.key root@<lighthouse-ip>:/etc/nebula/
# Copy lên app-server
scp ca.crt app-server.crt app-server.key root@<app-server-ip>:/etc/nebula/
# Chạy foreground để xem log trực tiếp
sudo nebula -config /etc/nebula/config.yaml
Khi log xuất hiện dòng Handshake message sent và Handshake message received, nghĩa là hai node đã bắt tay thành công. Lúc đó mới chuyển sang systemd:
cat > /etc/systemd/system/nebula.service << 'EOF'
[Unit]
Description=Nebula VPN
After=network.target
[Service]
ExecStart=/usr/local/bin/nebula -config /etc/nebula/config.yaml
Restart=always
RestartSec=5
[Install]
WantedBy=multi-user.target
EOF
systemctl daemon-reload
systemctl enable --now nebula
Kiểm tra kết nối và Monitoring
Ping qua overlay network
Khi Nebula chạy trên tất cả node, kiểm tra bằng IP ảo:
# Từ app-server, ping dev-laptop qua Nebula overlay
ping 192.168.100.50
# Xem thông tin cert của node hiện tại
nebula-cert print -path /etc/nebula/app-server.crt
Xem trạng thái peer qua Prometheus metrics
Nebula hỗ trợ expose metrics theo định dạng Prometheus. Thêm vào config:
stats:
type: prometheus
listen: 127.0.0.1:8080
path: /metrics
namespace: nebula
subsystem: stats
interval: 10s
# Xem số tunnel đang active, handshake thành công/thất bại
curl -s http://127.0.0.1:8080/metrics | grep -E "(tunnel|handshake)"
Debug firewall rules
# Bật log level debug để xem packet bị allow hay deny
# Sửa config: logging.level: debug
# Restart rồi theo dõi
journalctl -u nebula -f | grep -E "(ALLOW|DENY|firewall)"
Test throughput thực tế
Đo băng thông giữa hai node sau khi mạng ổn định:
# Trên node receiver (192.168.100.10)
iperf3 -s -B 192.168.100.10
# Trên node sender — 4 luồng song song, test 30 giây
iperf3 -c 192.168.100.10 -t 30 -P 4
Những điều cần nhớ khi vận hành thực tế
Vài tuần đầu chạy production mình đã vấp phải đủ thứ. Ghi lại đây để bạn khỏi mất công debug:
- Lighthouse redundancy: Tối thiểu 2 lighthouse ở 2 datacenter khác nhau. Thêm IP lighthouse thứ hai vào
lighthouse.hostsvàstatic_host_maptrong config của mỗi node là xong. - Certificate expiry: Cert mặc định không có thời hạn — nghe có vẻ tiện nhưng thực ra rất nguy hiểm nếu cert bị lộ. Luôn đặt
-duration 8760h(1 năm) khi ký cert và có lịch rotate định kỳ. - MTU overhead: Nebula thêm khoảng 60 bytes header. App bị timeout hoặc packet loss không rõ lý do? Thử thêm
tun: mtu: 1300vào config. - Revoke node: Cần kick một node ra khỏi mạng ngay lập tức? Thêm cert của nó vào
pki.blocklisttrong config của tất cả node, reload — Nebula từ chối kết nối từ cert đó ngay.
So với WireGuard, Nebula phức tạp hơn ở bước setup ban đầu. Nhưng firewall rules nhúng thẳng vào node config tiết kiệm rất nhiều công quản lý access control khi số node vượt qua 10. Không cần iptables riêng, không cần đồng bộ rules thủ công giữa các server. Với hạ tầng đang lớn dần, đây là lựa chọn đáng thay thế OpenVPN hub-and-spoke cổ điển.

