SSD Nodes Learn Hosting plans →
Hướng dẫn Matt ConnorBởi Matt Connor

Tailscale có hoạt động ở Việt Nam không? CGNAT và DERP

Tailscale là mạng WireGuard giữa các máy bạn sở hữu. Bài viết giải thích vì sao CGNAT ở Việt Nam đẩy kết nối sang relay DERP, và cách tự đo bằng tailscale netcheck.

Tailscale có hoạt động ở Việt Nam không?

Có. Trên một đường Viettel, VNPT hay FPT, Tailscale kết nối được, và phần lớn trường hợp bạn không phải chỉnh gì thêm. Khác biệt nằm ở đường đi của gói tin. Cáp quang nhà ở Việt Nam rất hay nằm sau CGNAT (carrier-grade NAT, tức NAT cấp nhà mạng), nên hai thiết bị của bạn có thể không mở được đường trực tiếp với nhau. Khi đó Tailscale tự lùi về relay DERP, và relay gần bạn nhất thường đặt ở nước ngoài. Tailnet vẫn chạy. Nó chỉ chậm hơn, và nó phụ thuộc vào chất lượng đường truyền quốc tế.

Bài này giải thích cơ chế đó và các lựa chọn cấu hình. Mọi con số về độ trễ, mọi tên vùng DERP và mọi kết luận kiểu "máy tôi đang đi relay" đều phải do chính bạn đo trên máy của mình, vì kết quả đổi theo nhà mạng, theo khu vực và theo từng thời điểm. Bài viết chỉ nói về kỹ thuật, không bàn tới quy định hay chính sách của bất kỳ bên nào.

Tailscale là gì, và khác kiểu "VPN" bạn đang nghĩ ở chỗ nào

Ở Việt Nam, chữ VPN (virtual private network, mạng riêng ảo) thường được hiểu là một dịch vụ thương mại: bạn trả tiền, cài app, chọn một quốc gia, rồi toàn bộ lưu lượng duyệt web của bạn đi qua máy chủ của công ty đó. Tailscale không phải thứ này.

Tailscale là một mạng lưới WireGuard giữa những thiết bị mà bạn sở hữu. Mỗi máy tự sinh một cặp khóa, và khóa riêng không bao giờ rời khỏi máy. Máy chủ điều phối (control plane) của Tailscale chỉ phân phát khóa công khai, danh sách thiết bị và địa chỉ endpoint, để các máy tự bắt tay với nhau. Tập hợp các máy đó là tailnet của bạn. Nếu bạn muốn hiểu phần bên dưới, cách WireGuard gắn mỗi khóa với dải địa chỉ được phép chính là nền của mô hình này, còn bài giới thiệu Tailscale mô tả kỹ phần control plane.

Điểm quan trọng nhất: mặc định, không có lưu lượng duyệt web nào của bạn rời khỏi tailnet. Laptop vẫn ra Internet bằng đường của nhà mạng như cũ. Chỉ khi bạn chủ động bật exit node thì lưu lượng ra Internet mới đi qua một máy trong tailnet, và máy đó do bạn chọn. Đây là một lựa chọn cấu hình, không phải mặc định, nên câu hỏi Tailscale có phải là VPN hay không phụ thuộc vào việc bạn bật hay không bật đúng cái công tắc đó.

Vì sao cáp quang nhà ở Việt Nam thường nằm sau CGNAT

NAT (network address translation, chuyển đổi địa chỉ mạng) là việc modem thay địa chỉ riêng trong nhà bằng một địa chỉ công cộng khi gói tin đi ra. CGNAT là thêm một lớp nữa ở phía nhà mạng: rất nhiều thuê bao dùng chung một địa chỉ IPv4 công cộng. Nhà mạng làm vậy vì IPv4 đã cạn từ lâu, và gói cáp quang dân dụng thì không kèm IP tĩnh.

Bạn kiểm tra trong hai phút. Mở trang quản trị modem, xem địa chỉ WAN, rồi so với địa chỉ mà Internet nhìn thấy:

curl -4 https://ifconfig.me

Nếu hai địa chỉ khác nhau, hoặc nếu địa chỉ WAN của modem nằm trong dải 100.64.0.0/10 hay 10.0.0.0/8, đường của bạn đang ở sau CGNAT. Hệ quả rất cụ thể: không có cổng nào từ Internet trỏ thẳng về nhà bạn được, nên mở port trên modem cũng không có tác dụng.

Tailscale xử lý chuyện này bằng kỹ thuật đục lỗ NAT (hole punching). Hai máy cùng gửi gói UDP ra ngoài, học địa chỉ công cộng của nhau qua máy chủ DERP, rồi hẹn gặp nhau ở giữa. Cách này thành công rất thường xuyên, kể cả sau CGNAT. Nó thất bại khi NAT gán một cổng khác nhau cho mỗi đích đến, vì khi đó địa chỉ mà máy kia vừa học được đã không còn đúng nữa. Hole punching thất bại thì Tailscale chuyển sang relay.

DERP (Designated Encrypted Relay for Packets) là mạng máy chủ chuyển tiếp của Tailscale. Nó chỉ chuyển tiếp gói đã mã hóa: nội dung vẫn do WireGuard mã hóa đầu cuối, máy relay không đọc được. Cái giá phải trả là quãng đường. Gói tin từ laptop ở Hà Nội tới VPS của chính bạn có thể phải chạy sang một relay ở nước khác rồi quay về.

Cài client từ gói chính thức

Gói cho Debian và Ubuntu đến từ kho của chính Tailscale tại pkgs.tailscale.com, không phải từ kho của Ubuntu. Với Ubuntu 24.04:

sudo mkdir -p --mode=0755 /usr/share/keyrings
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.noarmor.gpg | sudo tee /usr/share/keyrings/tailscale-archive-keyring.gpg >/dev/null
curl -fsSL https://pkgs.tailscale.com/stable/ubuntu/noble.tailscale-keyring.list | sudo tee /etc/apt/sources.list.d/tailscale.list
sudo apt-get update && sudo apt-get install tailscale
sudo tailscale up

Debian 12 dùng đúng các lệnh trên, chỉ đổi ubuntu/noble thành debian/bookworm. tailscale up in ra một dòng To authenticate, visit: kèm đường dẫn. Mở đường dẫn đó trên trình duyệt và đăng nhập, máy sẽ vào tailnet. Sau đó kiểm tra ngay:

tailscale status

Mỗi dòng là một thiết bị. Dòng có chữ direct nghĩa là hai máy đang nói chuyện thẳng với nhau. Dòng có chữ relay nghĩa là đang đi vòng qua DERP. Đây là thông tin quan trọng nhất của cả bài, và nó nằm trên màn hình của bạn chứ không nằm trong bài viết này.

Tự đo bằng tailscale netcheck

tailscale netcheck
tailscale ping <tên-máy>

netcheck in một báo cáo bắt đầu bằng Report:, gồm các dòng như UDP, IPv4, IPv6, MappingVariesByDestIP, Nearest DERP và bảng độ trễ tới từng vùng DERP. Đọc theo thứ tự sau.

  • UDP: false nghĩa là không gói UDP nào ra được. Mọi kết nối sẽ phải đi relay qua TCP cổng 443, nên nó chậm và không bao giờ lên direct. Nguyên nhân thường là một tường lửa đang chặn UDP đi ra.
  • IPv6: yes kèm một địa chỉ là tin tốt. Nếu cả hai đầu đều có IPv6 định tuyến được, chúng có thể bắt tay thẳng mà không quan tâm tới CGNAT, vì IPv6 không đi qua NAT.
  • MappingVariesByDestIP: true nghĩa là NAT của bạn gán cổng khác nhau cho từng đích. Đây đúng là kiểu NAT làm hole punching thất bại, và nó giải thích vì sao máy bạn dính relay trong khi máy của người khác thì không.
  • Nearest DERP cùng bảng độ trễ cho biết relay nào đang được chọn và đi tới đó mất bao lâu. Con số đó là của riêng đường truyền của bạn tại thời điểm bạn chạy lệnh.

tailscale ping <tên-máy> cho câu trả lời trực tiếp nhất. Vài dòng đầu thường báo đi qua DERP, rồi nếu đục lỗ thành công, một dòng sau đó báo via kèm địa chỉ IP và cổng thật của máy kia. Nếu chạy hết mười dòng mà vẫn chỉ thấy DERP, đường trực tiếp không mở được. Bài Tailscale chậm: đường trực tiếp khác đường qua relay thế nào đi sâu vào cách đọc các dòng này.

Vì sao đứt cáp quang biển làm tailnet chậm mà web trong nước vẫn nhanh

Việt Nam nối ra thế giới qua một số tuyến cáp quang biển (AAG, APG, IA, AAE-1). Khi một tuyến gặp sự cố, lưu lượng quốc tế dồn sang các tuyến còn lại, và độ trễ đi ra nước ngoài tăng lên. Lưu lượng trong nước đi qua điểm trung chuyển nội địa nên gần như không bị ảnh hưởng. Vì vậy các trang trong nước vẫn mở nhanh trong lúc mọi thứ đi ra ngoài đều ì ạch.

Bây giờ ghép hai chuyện lại. Nếu tailnet của bạn đang đi relay ở nước ngoài, mỗi gói tin SSH của bạn vượt đường quốc tế hai lần, dù laptop và máy đích đều đang ở Việt Nam. Đó là lý do một sự cố cáp biển hiện ra thành "Tailscale chậm" trong khi duyệt web vẫn bình thường. Cách xác nhận: chạy lại tailscale netcheck, so bảng độ trễ DERP với lần đo trước, rồi chạy tailscale ping tới đúng máy đang chậm. Nếu kết quả là relay, nguyên nhân nằm trên đường quốc tế chứ không nằm ở máy chủ của bạn.

Hãy lưu lại kết quả netcheck lúc mạng bình thường. Không có mốc để so, lần sau bạn chỉ đoán.

Cách 1: một VPS ở khu vực gần, làm exit node hoặc subnet router

Một VPS ở khu vực gần Việt Nam đổi bài toán theo hai hướng. Nó có IP công cộng thật, nên laptop của bạn gần như luôn mở được đường trực tiếp tới nó kể cả khi bạn ở sau CGNAT. Và vì nó gần về mặt mạng, đường đi không còn vòng qua nửa vòng trái đất.

Trên VPS, bật chuyển tiếp gói rồi quảng bá:

printf 'net.ipv4.ip_forward = 1\nnet.ipv6.conf.all.forwarding = 1\n' \
  | sudo tee /etc/sysctl.d/99-tailscale.conf
sudo sysctl --system
sysctl net.ipv4.ip_forward
sudo tailscale up --advertise-exit-node

Lệnh sysctl net.ipv4.ip_forward phải in ra net.ipv4.ip_forward = 1. Nếu nó là 0, nhân Linux vứt bỏ mọi gói không gửi cho chính máy đó, nên exit node nhận gói rồi không chuyển đi đâu cả, và người dùng thấy đúng triệu chứng "kết nối được nhưng không vào được mạng". Viết vào /etc/sysctl.d/ chứ đừng dùng sysctl -w, vì bản ghi tạm đó mất sau lần khởi động lại kế tiếp.

Sau đó vào trang quản trị tailnet và duyệt exit node, vì Tailscale không tự bật nó. Trên laptop:

sudo tailscale up --exit-node=<tên-máy-vps>

Nếu thứ bạn cần chỉ là chạm tới một dải mạng phía sau VPS, ví dụ mạng riêng giữa các máy chủ của bạn, chứ không phải toàn bộ lưu lượng ra Internet, thì dùng subnet router: chạy sudo tailscale up --advertise-routes=10.0.0.0/24 trên VPS, thêm --accept-routes trên máy khách, và cũng phải duyệt route trong trang quản trị. Hai bài dựng subnet router trên một VPS và biến VPS thành exit node cho tailnet đi qua từng bước, kèm phần tường lửa. Còn nếu bạn muốn mở một dịch vụ ở nhà ra cho cả Internet chứ không riêng tailnet, đường hầm ngược qua VPS cho máy nằm sau CGNAT là cách làm cũ và vẫn đúng.

Cách 2: giữ cho đường trực tiếp mở được

Cách này không tốn tiền, nên thử trước.

  • Bật IPv6 trên modem và trên VPS. Khi cả hai đầu có IPv6 định tuyến được, đường trực tiếp thường lên ngay, vì IPv6 không phải chui qua CGNAT.
  • Bật UPnP hoặc NAT-PMP trên modem nếu nhà mạng cho phép. Dòng PortMapping trong netcheck cho biết có dùng được hay không.
  • Đừng chặn UDP đi ra trên máy. Tailscale ưu tiên UDP cổng 41641 và cần gửi UDP tới các cổng tùy ý.
  • Với đầu có IP công cộng, mở cổng UDP vào máy đó: sudo ufw allow 41641/udp. Chỉ cần một đầu nhận được gói trực tiếp thì đầu còn lại ở sau CGNAT vẫn bắt tay được.
  • Hỏi nhà mạng về IP tĩnh. Gói doanh nghiệp thường có, gói dân dụng thường không.

Bạn không kiểm soát được CGNAT của nhà mạng. Nếu làm hết những việc trên mà MappingVariesByDestIP vẫn là true và tailscale status vẫn in relay, hãy dừng lại và chuyển sang cách 1.

Cách 3: tự host Headscale

Headscale là bản cài đặt mã nguồn mở của control plane Tailscale. Bạn chạy nó trên VPS của mình, client trỏ vào nó bằng sudo tailscale up --login-server=https://hs.example.com, và từ đó danh sách thiết bị cùng khóa công khai nằm trên máy chủ của bạn. Hướng dẫn dựng Headscale đi qua chi tiết. Trước khi quyết định, đọc control plane thấy gì và không thấy gì: nó không giữ khóa nào giải mã được lưu lượng của bạn, nhưng nó quyết định máy nào biết về máy nào.

Hiểu đúng thứ Headscale giải quyết. Nó thay control plane. Nó không làm đường trực tiếp tự mở ra, vì CGNAT vẫn nằm nguyên đó. Mặc định client vẫn dùng bản đồ DERP công khai, nên nếu phải relay thì vẫn relay qua máy chủ ở nước ngoài, trừ khi bạn tự chạy thêm một máy chủ DERP riêng và khai báo nó vào cấu hình. Đổi lại, bạn nhận toàn bộ phần vận hành: cập nhật, sao lưu cơ sở dữ liệu, và một máy chủ mà khi nó chết thì thiết bị mới không đăng nhập được.

Cái nào đáng tiền với một người dùng

Trả lời thẳng. Với một người, một laptop, một VPS và một máy ở nhà: làm cách 2 trước vì nó miễn phí, rồi thuê một VPS nhỏ ở khu vực gần nếu vẫn phải relay. Headscale không nên là lựa chọn đầu tiên.

Lý do rất đơn giản. VPS nhỏ giải quyết đúng vấn đề bạn đang gặp, tức quãng đường của gói tin, và cái VPS đó còn dùng được vào nhiều việc khác. Headscale giải quyết một vấn đề khác hẳn là quyền sở hữu control plane, và nó đổi tiền thuê máy lấy thời gian vận hành của bạn. Nếu lý do bạn nghĩ tới Headscale là chi phí, hãy xem gói miễn phí của Tailscale cho phép bao nhiêu người dùng và thiết bị trước đã. Phần lớn người dùng cá nhân không bao giờ chạm tới giới hạn đó.

Lỗi hay gặp và cách đọc chúng

Mọi thiết bị đều hiện relay, kể cả hai máy trong cùng một nhà. Chạy netcheck. Nếu UDP: false, có thứ gì đó đang chặn UDP đi ra, trên máy hoặc trên modem. Nếu UDP: true mà MappingVariesByDestIP: true, đó là NAT của nhà mạng.

tailscale ping chạy tốt nhưng SSH vào địa chỉ 100.x.y.z thì treo. Tailscale đã thông, vấn đề nằm ở dịch vụ. Chạy ss -tlnp trên VPS và xem sshd đang nghe ở địa chỉ nào, rồi kiểm tra tường lửa có chặn dải tailnet hay không.

Bật exit node xong thì laptop mất Internet. Kiểm tra trên VPS rằng sysctl net.ipv4.ip_forward trả về 1, và nhớ rằng exit node phải được duyệt trong trang quản trị thì mới thực sự hoạt động.

Máy mới không đăng nhập được, trình duyệt mở trang xác thực rồi treo. Bước đăng nhập đi tới login.tailscale.com qua HTTPS cổng 443. Khi đường quốc tế đang có sự cố, việc thêm máy mới sẽ chậm hoặc lỗi trong khi tailnet sẵn có vẫn chạy bình thường.

FAQ

Tailscale có dùng được trên mạng Viettel, VNPT hay FPT không?

Được. Về mặt kỹ thuật, client cần gửi UDP ra ngoài tới các cổng tùy ý và cần HTTPS cổng 443 tới máy chủ điều phối. Khi UDP không đi ra được, Tailscale tự lùi về relay DERP chạy trên TCP cổng 443, nên kết nối vẫn lên, chỉ chậm hơn. Cách duy nhất để biết đường của bạn ra sao là chạy tailscale netcheck và đọc dòng UDP, rồi chạy tailscale status xem thiết bị hiện direct hay relay.

Vì sao tailnet của tôi chậm mà mạng trong nước vẫn nhanh?

Vì hai thứ đó đi hai đường khác nhau. Trang trong nước đi qua hạ tầng nội địa. Còn nếu tailnet của bạn đang đi relay, gói tin phải ra một máy chủ ở nước ngoài rồi quay lại, tức là vượt đường quốc tế hai lần, kể cả khi hai máy đều ở Việt Nam. Chạy tailscale ping tới máy đang chậm: nếu kết quả báo đi qua DERP thì nguyên nhân là quãng đường quốc tế, không phải cái VPS của bạn.

Tôi có cần bật exit node không?

Không, nếu việc bạn cần chỉ là SSH vào VPS, chạm tới máy ở văn phòng và mở một dịch vụ ở nhà. Những việc đó chạy trên tailnet mà không cần exit node, và lưu lượng duyệt web của bạn vẫn đi đường bình thường của nhà mạng. Exit node là một lựa chọn riêng biệt bạn phải tự bật, nó khiến toàn bộ lưu lượng ra Internet đi qua một máy cụ thể trong tailnet, nên hãy bật khi bạn thực sự muốn điều đó.

Tự host Headscale có làm tailnet nhanh hơn không?

Không, trừ khi bạn chạy thêm máy chủ DERP của riêng mình ở gần. Headscale thay phần điều phối, tức là nơi lưu danh sách thiết bị và khóa công khai. Nó không đụng gì tới CGNAT của nhà mạng, và mặc định client vẫn dùng các relay công khai. Nếu mục tiêu của bạn là tốc độ, một VPS ở khu vực gần làm exit node hoặc subnet router cho kết quả rõ ràng hơn nhiều với cùng số tiền.