SSD Nodes Learn Hosting plans →
Hướng dẫn Matt ConnorBởi Matt Connor · Cập nhật ngày 2026-09-11

Tailscale là gì và hoạt động như thế nào?

Tìm hiểu Tailscale: WireGuard mã hóa giữa các server, control plane phân phối key và ACL, NAT traversal, DERP relay cùng threat model cần biết.

Tailscale là gì?

Tailscale là một VPN kết nối trực tiếp các máy với nhau thay vì định tuyến toàn bộ lưu lượng qua một gateway do bạn tự vận hành. Mỗi node chạy WireGuard, vì vậy các gói tin được mã hóa khi truyền từ server này sang server khác và không thành phần nào trên đường truyền có thể đọc được chúng. Một server điều phối do Tailscale host xử lý việc thiết lập kết nối giữa các node. Server này lưu trữ và phân phối public key, đồng thời cho mỗi node biết vị trí của các node khác. Server cũng đẩy xuống các rule truy cập mà bạn đã viết.

Đó là toàn bộ thiết kế. Data plane hoạt động theo mô hình peer-to-peer và được mã hóa giữa các node. Control plane là một service do Tailscale vận hành thay cho bạn. Mọi câu hỏi đáng chú ý về Tailscale, kể cả những câu hỏi khó chịu về mức độ tin cậy, đều bắt nguồn từ hai thực tế này. Nếu bạn đã từng tự dựng một WireGuard VPN trên VPS, thì Tailscale chính là tunnel đó, với việc phân phối key và traversal qua firewall được thực hiện thay cho bạn.

Tailscale hoạt động như thế nào?

Mạng riêng gồm các node của bạn được gọi là tailnet. Khi một máy tham gia tailnet, 4 việc sẽ xảy ra.

  1. Daemon tailscaled khởi động, tạo một cặp key WireGuard và lưu trạng thái trong /var/lib/tailscale/tailscaled.state. Private key vẫn nằm trên máy đó. Tailscale nói rất rõ: “private key không bao giờ rời khỏi node của nó.”
  2. Node đăng nhập vào coordination server rồi tải lên public key cùng các địa chỉ mà nó cho rằng có thể dùng để truy cập đến nó. Tailscale mô tả server này là “một hộp thư dùng chung cho các public key.”
  3. Coordination server gửi lại network map: public key, địa chỉ tailnet, tên máy và các endpoint có thể dùng của mọi node mà node này được phép truy cập.
  4. Sau đó, từng cặp node cố gắng tạo một tunnel WireGuard trực tiếp giữa chúng. Nếu thất bại, chúng sẽ chuyển packet qua relay.

Mỗi node nhận một địa chỉ ổn định trong 100.64.0.0/10, dải carrier-grade NAT từ 100.64.0.0 đến 100.127.255.255. Tailscale dùng dải này vì nó được dành cho hạ tầng của nhà cung cấp, nên hiếm khi xung đột với các địa chỉ private mà server của bạn đang dùng. Trên Linux, tunnel xuất hiện dưới dạng interface tên tailscale0.

Phần triển khai WireGuard nằm trong tailscaled ở userspace, không nằm trong kernel module. Vì vậy Tailscale vẫn khởi động được trong môi trường container virtualisation, nơi sudo modprobe wireguard thất bại với Operation not supported. Điều này cũng có nghĩa là giới hạn throughput trên một máy cụ thể thấp hơn WireGuard chạy trong kernel. Đây là một trong các đánh đổi được trình bày trong Tailscale so với WireGuard thuần túy.

2 lệnh cho bạn biết trạng thái hiện tại.

tailscale ip -4
tailscale status

tailscale status in một dòng cho mỗi node; cột cuối cùng là cột cần chú ý.

100.101.102.103  web-1      you@  linux  -
100.101.102.104  db-1       you@  linux  active; direct 198.51.100.24:41641
100.101.102.105  ci-runner  you@  linux  active; relay "fra"

direct theo sau bởi một địa chỉ và port nghĩa là 2 máy đã tìm được đường kết nối với nhau và network traffic đang đi peer to peer. relay "fra" nghĩa là traffic đang đi qua một Tailscale relay tại Frankfurt. - nghĩa là hiện không có session đang hoạt động với node đó, điều này là bình thường.

Máy chủ điều phối có thể và không thể xem gì

Máy chủ điều phối lưu các public key và metadata. Nó biết tên máy, user hoặc tag nào sở hữu từng node, địa chỉ tailnet của từng node, các địa chỉ public mà node của bạn có thể được truy cập tại đó, thời điểm từng node online lần cuối và policy file bạn đã viết. Đây là bản đồ đầy đủ của toàn bộ fleet.

Máy chủ này không giữ private key, nên không thể giải mã traffic giữa hai node. Việc mã hóa diễn ra end-to-end giữa các WireGuard peer, còn máy chủ điều phối không phải là một peer.

Nó có thể phân phối key. Bất kỳ máy chủ điều phối nào, dù do bên khác host hay do bạn tự vận hành, đều được tin cậy để cho các node biết public key nào thuộc tailnet. Đây là điểm then chốt trong threat model được trình bày ở phần sau, đồng thời là lý do tồn tại của Headscale, một máy chủ điều phối mã nguồn mở do bạn tự vận hành.

Cách hai máy chủ sau các firewall khác nhau kết nối trực tiếp

NAT (network address translation) cho phép nhiều máy dùng chung một địa chỉ public. VPS của bạn thường có địa chỉ public riêng, nhưng các máy khác bạn muốn đưa vào tailnet thường không có: server ở nhà, build runner trong mạng văn phòng hoặc một máy nằm sau firewall của nhà cung cấp mà bạn không thể chỉnh sửa.

Tailscale tìm đường truyền bằng các kỹ thuật dựa trên các tiêu chuẩn STUN (session traversal utilities for NAT) và ICE. Mỗi node gửi một gói UDP nhỏ đến STUN server để biết địa chỉ public và port mà router đã gán cho socket đó. Cả hai node gửi các candidate này đến coordination server, rồi server chuyển chúng cho phía còn lại. Sau đó, hai node bắt đầu gửi packet cho nhau cùng lúc. Mỗi router thấy packet outbound trước, nên tạo mapping và chấp nhận reply đến từ chính địa chỉ đó. Không phía nào cần rule inbound trên firewall.

Các port được quy định cụ thể. Tunnel WireGuard trực tiếp dùng UDP với source port mặc định là 41641. STUN chạy trên UDP 3478 đến relay server của Tailscale. Kết nối control và mọi dữ liệu được relay dùng HTTPS trên TCP 443. Hầu hết thời gian, bạn không cần mở gì inbound. Tuy nhiên, trên mạng có NAT khó vượt qua, cho phép UDP 41641 inbound sẽ tăng khả năng thiết lập kết nối trực tiếp.

tailscale netcheck

Đọc 2 dòng trong report đó. UDP: true nghĩa là UDP có thể rời khỏi máy, còn UDP: false nghĩa là mọi kết nối từ node này sẽ được relay. MappingVariesByDestIP: true nghĩa là router gán một public port khác nhau cho từng đích, nên việc dự đoán địa chỉ như trên không thể hoạt động và các node đó thường vẫn phải dùng relay.

Khi Tailscale dùng DERP relay thay thế

DERP (designated encrypted relay for packets) là cơ chế dự phòng. Tailscale vận hành các relay ở nhiều khu vực, có thể truy cập qua TCP 443. Node không thể thiết lập đường truyền trực tiếp sẽ gửi các packet WireGuard qua một relay.

Các packet vẫn được mã hóa. Tailscale nêu rõ: “DERP server không bao giờ có thể giải mã traffic của bạn. Nó chỉ chuyển tiếp nguyên trạng traffic đã được mã hóa từ node này sang node khác.” Relay thấy ciphertext và biết node nào đang giao tiếp với node nào.

Relay cũng chuyển tiếp những packet đầu tiên của hầu hết các connection. Việc tìm đường truyền trực tiếp cần một khoảng thời gian ngắn. Vì vậy, session thường bắt đầu qua relay rồi chuyển sang đường truyền trực tiếp ngay trong session khi hai node tìm thấy nhau. Bạn có thể theo dõi quá trình này.

tailscale ping db-1

Các phản hồi đầu tiên quay về qua via DERP(fra). Sau đó, một dòng log xuất hiện với nội dung tương tự via 198.51.100.24:41641. Thay đổi này cho biết tunnel đã chuyển sang kết nối trực tiếp. Nếu trạng thái không thay đổi, hãy chạy tailscale netcheck ở cả hai đầu. Đường truyền qua relay vẫn hoạt động. Tuy nhiên, latency sẽ cao hơn vì mỗi packet phải đi vòng qua một máy thứ ba.

Thêm VPS vào tailnet

Script cài đặt hỗ trợ Ubuntu và Debian.

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

sudo tailscale up in ra một URL. Mở URL đó, xác thực, rồi node sẽ xuất hiện trong admin console. Sau đó xác nhận daemon khởi động lại sau reboot, vì đây là bước nhiều người bỏ qua.

sudo systemctl is-enabled tailscaled
tailscale status

is-enabled phải in ra enabled, còn tailscale status phải liệt kê node mới cùng địa chỉ 100.x của nó. Với server được dựng bằng script, URL tương tác không hữu ích. Hãy tạo auth key trong admin console rồi truyền key đó cùng một tag để ghi rõ loại máy này.

sudo tailscale up --auth-key=tskey-auth-REPLACE-ME --advertise-tags=tag:server

Node có tag thuộc quyền quản lý của tag thay vì người đã chạy command, nên vẫn tiếp tục hoạt động sau khi tài khoản của người đó bị xóa. Trước tiên, phải khai báo tag trong policy file tại tagOwners, nếu không command sẽ bị từ chối. Việc gắn tag cũng thay đổi cách máy được tính vào plan, vì resource có tag được tính giá riêng với các device của cá nhân, còn phần free tier thực sự bao gồm những gì giải thích các giới hạn đó.

Có 2 thiết lập quan trọng khi quản lý nhiều máy. Node key mặc định hết hạn sau 180 ngày (tính đến tháng 8 năm 2026). Khi key hết hạn, "các kết nối đến/từ endpoint đó sẽ ngừng hoạt động" cho đến khi có người đăng nhập lại. Vì vậy, hãy mở dòng của máy trong admin console và chọn Disable Key Expiry trên các server không có người trực tiếp quản lý. MagicDNS, được bật mặc định cho các tailnet tạo từ ngày 20 tháng 10 năm 2022 trở đi, cấp cho mỗi node một tên như db-1.yak-bebop.ts.net và phân giải tên đó bằng stub resolver tại 100.100.100.100. Hãy dùng tên thay vì địa chỉ, vì node được dựng lại sẽ nhận địa chỉ mới nhưng vẫn giữ tên cũ.

Nếu quá trình cài đặt bị lỗi với apt hoặc repository, các lỗi cài đặt Tailscale thường gặp trên Ubuntu trình bày cách khắc phục.

Truy cập một service bind vào localhost

Đây là lúc tailnet phát huy tác dụng, đồng thời cũng là chỗ nhiều người bị vướng. Tham gia tailnet không khiến service loopback có thể được truy cập.

ss -tlnp | grep 3000

Nếu lệnh đó in ra 127.0.0.1:3000, socket chỉ chấp nhận các packet có địa chỉ đích là 127.0.0.1. Request từ node khác đến với địa chỉ đích là địa chỉ 100.x của node này, nên kernel không có listener nào nhận request đó và trả về TCP reset. Client báo Connection refused. Tunnel vẫn hoạt động bình thường. Vấn đề nằm ở listener.

Có 2 cách xử lý đúng. Bind service vào địa chỉ tailnet của node. Cách này giữ service không nằm trên public interface và không cần proxy: truyền --bind 100.101.102.104 hoặc tùy chọn tương đương trong config; với container, publish port dưới dạng -p 100.101.102.104:3000:3000. Hoặc giữ service trên loopback và đặt Tailscale phía trước service.

tailscale serve 3000

Cách này proxy các request đến http://127.0.0.1:3000 và phục vụ chúng bên trong tailnet bằng tên ts.net qua HTTPS, sau khi bật chứng chỉ HTTPS cho tailnet. Service vẫn chỉ private đối với các node của bạn. Phiên bản public của cùng cách này là Funnel; Tailscale serve so với funnel giải thích nên dùng cách nào.

2 tác vụ liên quan có trang hướng dẫn riêng. Để truy cập toàn bộ private network chưa cài Tailscale, bạn cần subnet router trên VPS. Để định tuyến traffic Internet outbound của một node qua node khác, bạn cần exit node.

Đóng các cổng không còn cần thiết

Khi mọi quản trị viên đều truy cập máy chủ qua tailnet, cổng public 22 không còn tác dụng. Đây là lợi ích thực tế: cổng đã đóng thì không thể bị brute force, đồng thời log không còn đầy các lần thử truy cập.

Thứ tự thực hiện rất quan trọng. Hãy thêm quyền truy cập qua tailnet, xác nhận bạn có thể đăng nhập qua đó từ một session thứ hai, rồi mới xóa rule public.

sudo ufw allow in on tailscale0
sudo ufw status verbose

Sau đó, xóa rule SSH public và kết nối lại bằng tên MagicDNS. Lưu ý ufw allow in on tailscale0 thực sự làm gì: nó tin cậy mọi lưu lượng đi vào tunnel, vì vậy file policy của Tailscale sẽ trở thành cơ chế kiểm soát truy cập thay cho ufw. Hãy viết policy dựa trên điều đó.

Một cảnh báo dành cho những ai đang chạy container. Docker port được publish sẽ tự cài các rule NAT riêng và bypass ufw, vì vậy ufw deny không đóng được port đó. Docker publish port bypass ufw giải thích cơ chế này. Publish port vào địa chỉ tailnet như trên sẽ tránh được vấn đề đó.

Tailscale bảo vệ những gì và không bảo vệ những gì

Cần nói rõ điều này, vì nội dung marketing thường làm mờ ranh giới.

Được bảo vệ: lưu lượng giữa hai node được mã hóa end-to-end bằng WireGuard, và không relay nào ở giữa có thể đọc được lưu lượng đó. Private key không bao giờ rời khỏi máy đã tạo ra nó. Node không cần mở public port inbound, nên Internet không có cổng 22 hoặc 5432 để quét. Quyền truy cập giữa các node được quyết định bằng policy file, không phải bởi bất kỳ ai biết địa chỉ.

Không được bảo vệ: coordination server nhìn thấy device graph của bạn. Riêng metadata này đã nhạy cảm, vì tên máy, chủ sở hữu, địa chỉ và thời điểm online mô tả hạ tầng của bạn. Server này cũng phân phối key, và đó mới là rủi ro nghiêm trọng hơn. Tailscale nói trực tiếp: "Nếu Tailscale là malicious và âm thầm chèn node mới vào network của bạn, Tailscale có thể gửi hoặc nhận traffic đến các node hiện có của bạn dưới dạng plaintext." Nhà cung cấp single sign-on của bạn nằm trong cùng trust path, vì bất kỳ ai có thể mint identity ở đó đều có thể thêm một node. Một node bị breach cũng là một peer bên trong tailnet, nên nó có thể tiếp cận những gì policy của bạn cho phép. Rủi ro này có chấp nhận được hay không phụ thuộc vào đối tượng mà bạn đang phòng thủ, và mô hình trust đầy đủ phân tích từng trường hợp, bao gồm cả những gì một tài khoản identity bị đánh cắp thực sự có thể làm.

Có 2 cách xử lý rủi ro trong việc phân phối key. Cách đầu tiên là tailnet lock. Tính năng này yêu cầu các node hiện có và được tin cậy phải ký bằng cryptographic signature cho node mới trước khi các node khác chấp nhận nó. Control plane thêm node mà không có signature hợp lệ sẽ bị bỏ qua. Admin console tạo chính xác dòng tailscale lock init cho các node dùng để ký, và mọi node đều có thể xác nhận thông tin mà nó nhận được.

tailscale lock status

Tất cả node phải báo cáo cùng một tập trusted signing key. Cách thứ hai là tự chạy control plane. Headscale coordination server tự host nói cùng protocol với cùng client, qua đó chuyển device graph và việc phân phối key lên phần cứng do bạn sở hữu. Khi đó, bạn cũng chịu trách nhiệm về uptime của server này. Nếu bạn vẫn đang so sánh các control plane tự host thay vì chọn giải pháp này, NetBird là một mesh VPN riêng, với server do bạn tự vận hành end-to-end trên một VPS.

Có một default cần sửa ngay trong ngày đầu tiên. Một tailnet mới được phát hành với cấu hình permissive: "policy file mặc định của tailnet cho phép giao tiếp giữa mọi device trong tailnet." Ngay khi bạn thêm một section acls, mô hình sẽ chuyển sang deny by default và chỉ các rule của bạn được phép đi qua.

{
  "tagOwners": {
    "tag:server": ["autogroup:admin"]
  },
  "acls": [
    {"action": "accept", "src": ["autogroup:member"], "dst": ["tag:server:22"]}
  ]
}

Policy này cho phép các thành viên tailnet truy cập SSH trên các server có tag và không truy cập được gì khác. Hãy thêm một rule cho từng service thay vì giữ wildcard, vì wildcard có nghĩa là một laptop bị đánh cắp key có thể truy cập database của bạn.

Các tình huống lỗi và chuỗi thông báo bạn sẽ thấy

tailscale status luôn hiển thị relay. Hai node không thiết lập được đường truyền trực tiếp. Chạy tailscale netcheck ở cả hai đầu. UDP: false có nghĩa là UDP bị chặn khi đi ra, vì vậy chỉ relay mới hoạt động được. MappingVariesByDestIP: true có nghĩa là có NAT cứng ở giữa, và cho phép UDP 41641 đi vào ở phía bạn kiểm soát thường sẽ khắc phục được lỗi này.

Một node đã hoạt động nhiều tháng đột nhiên biến mất. Node key của nó đã hết hạn theo mặc định sau 180 ngày. Máy được hiển thị là đã hết hạn trong admin console, và sudo tailscale up trên máy sẽ kích hoạt lại nó. Hãy tắt thời hạn key trên các server để lỗi này không lặp lại.

Các peer được liệt kê nhưng kết nối bị timeout. Kết nối mạng vẫn hoạt động và policy đang từ chối traffic. Kiểm tra phần acls để tìm rule áp dụng cho source, destination và port này. Packet bị từ chối sẽ bị drop thay vì nhận được phản hồi, nên bạn nhận timeout thay vì Connection refused.

Tên MagicDNS không phân giải được. ping db-1 bị lỗi trong khi ping 100.101.102.104 vẫn hoạt động. Có thành phần nào đó đã thay thế /etc/resolv.conf, vì vậy query không bao giờ đến stub resolver tại 100.100.100.100. Kiểm tra cat /etc/resolv.conf để tìm 100.100.100.100, đồng thời xem các thành phần khác trên máy có ghi vào file đó hay không. Đây là cùng một nhóm lỗi với DNS bị lỗi bên trong một tunnel WireGuard.

tailscale up từ chối tag của bạn. Tag chưa được khai báo bên dưới tagOwners trong policy file. Thêm tag vào đó, rồi chạy lại command.

FAQ

Tailscale là VPN hay mạng mesh?

Cả hai cách gọi đều đúng và mô tả các lớp khác nhau. Tunnel dùng WireGuard nên đây là VPN. Topology là mesh vì mỗi node tạo tunnel trực tiếp đến từng node mà nó giao tiếp, thay vì gửi mọi packet qua một server trung tâm. Coordination server chỉ nằm trên control path, không nằm trên data path. Vì vậy, nếu server này không thể truy cập, các tunnel hiện có vẫn tiếp tục chuyển traffic. Khi xảy ra outage, việc node mới tham gia và việc áp dụng thay đổi về key hoặc policy sẽ bị dừng.

Tailscale có thể đọc traffic của tôi không?

Không thể đọc nội dung traffic. WireGuard mã hóa traffic end-to-end giữa các node, private key không bao giờ rời khỏi node, còn một DERP relay chỉ chuyển tiếp packet mà không thể giải mã. Tailscale vẫn thấy metadata gồm tên máy, chủ sở hữu, public key, địa chỉ endpoint và thời điểm mỗi node online. Tailscale cũng phân phối key, nên coordination server bị compromise có thể cố đưa vào một node mà toàn bộ fleet của bạn sẽ tin cậy. Tailnet lock ngăn việc này bằng cách yêu cầu chữ ký từ các node đáng tin cậy của chính bạn. Headscale loại bỏ hosted control plane khỏi mô hình này.

Tôi có cần mở port trên firewall cho Tailscale không?

Hầu như không cần mở chiều inbound. Hướng dẫn của Tailscale nêu rõ rằng "most of the time, you don't need to open any firewall ports." Ở chiều outbound, node cần TCP 443 đến coordination server và các relay, cùng với UDP 3478 cho STUN. Tunnel trực tiếp dùng UDP với source port mặc định là 41641. Cho phép UDP 41641 inbound là tùy chọn và chỉ giúp các kết nối trực tiếp hoạt động trên những network khó xử lý.

Vì sao các node khác không thể truy cập service của tôi trên port 3000?

Trước tiên, hãy kiểm tra bind address bằng ss -tlnp. Listener trên 127.0.0.1:3000 sẽ từ chối các kết nối có địa chỉ đích là địa chỉ tailnet 100.x của node, vì socket đó chỉ chấp nhận destination loopback. Khi đó client sẽ nhận Connection refused. Hãy bind service vào địa chỉ tailnet hoặc chạy tailscale serve 3000 để proxy cho service. Nếu listener đã chạy trên 0.0.0.0 nhưng kết nối bị timeout thay vì bị từ chối, nguyên nhân là policy rule hoặc host firewall, không phải bind address.

Tôi có nên chạy Headscale thay cho coordination server của Tailscale không?

Hãy chạy Headscale khi device graph hoặc việc phân phối key phải nằm trên infrastructure do bạn kiểm soát, hoặc khi tailnet phải hoạt động mà không phụ thuộc vào một dịch vụ bên ngoài. Client và protocol vẫn giống nhau. Đổi lại, bạn phải tự vận hành coordination server. Khi server này outage, node mới không thể tham gia và các thay đổi policy không được áp dụng. Với fleet nhỏ, hosted control plane có bật tailnet lock thường là lựa chọn cân bằng hơn.