Hướng dẫn liên quan
Tìm hiểu WireGuard: nguyên lý hoạt động và lịch sử phát triển
Cập nhật
WireGuard là một giao thức VPN mã nguồn mở do Jason A. Donenfeld thiết kế, công bố khoảng năm 2015 và chính thức vào nhân Linux năm 2020. Đặc điểm của nó gói gọn trong một chữ: ít. Ít mã: phần lõi chỉ vài nghìn dòng, trong khi OpenVPN và IPsec là hàng trăm nghìn dòng. Ít tùy chọn: chỉ có một bộ thuật toán mã hóa cố định, không cho bạn chọn. Ít trạng thái: không có khái niệm “đang kết nối” hay “đã ngắt”, có dữ liệu thì gửi, không có thì im lặng. Cái “ít” đó mang lại tốc độ, tiết kiệm pin, dễ kiểm tra mã, và cũng mang lại các giới hạn của nó: chỉ dùng UDP, không ngụy trang, không lo chuyện phân phối khóa. Dưới đây trước hết là cách nó hoạt động, sau đó là con đường để nó từng bước trở thành nền tảng của thế hệ VPN mới.
Ý tưởng thiết kế: làm VPN giống như một card mạng
Trước WireGuard, lựa chọn phổ biến là IPsec và OpenVPN. IPsec là cả một họ tiêu chuẩn, vô số mục cấu hình, nối thiết bị của các hãng khác nhau với nhau nổi tiếng là phiền; OpenVPN chạy ở chế độ người dùng (user space), dựa vào thư viện TLS đồ sộ, linh hoạt nhưng chậm. Lượng mã của cả hai đều lớn tới mức khó có ai kiểm tra trọn vẹn một lượt.
WireGuard nghĩ theo hướng ngược lại: chỉ làm một việc, và làm cho đúng. Trong hệ thống, nó hiện ra như một card mạng ảo (ví dụ wg0). Bạn gán cho card này khóa riêng của mình và khóa công khai của vài đầu bên kia; gói tin gửi vào nó sẽ được mã hóa rồi gửi đi, gói nhận về được giải mã rồi đi ra từ nó. Mọi việc còn lại như định tuyến, tường lửa, cấp địa chỉ đều giao cho các công cụ sẵn có trong hệ thống.
Những việc nó cố tình không làm cũng rất rõ: không thương lượng thuật toán, không quản lý tài khoản mật khẩu, không cấp địa chỉ, không ngụy trang lưu lượng. Những thứ này hoặc bị coi là nguồn gốc của lỗ hổng, hoặc để lại cho công cụ ở tầng trên.
Định tuyến bằng khóa: khóa công khai chính là danh tính
Trong WireGuard, mỗi thiết bị có một cặp khóa, khóa công khai chính là danh tính của nó, giống cách dùng SSH: hai bên ghi khóa công khai của nhau vào cấu hình của mình là đã tin nhau, không có chứng chỉ, không có tên người dùng mật khẩu.
Cấu hình ghi cho mỗi đầu bên kia một dòng “địa chỉ được phép” (AllowedIPs). Dòng này quản cả hai chiều: khi gửi, địa chỉ đích nằm trong phạm vi của ai thì mã hóa bằng khóa công khai của người đó và gửi cho người đó; khi nhận, giải mã xong xem địa chỉ nguồn có nằm trong phạm vi được phép của đầu bên kia không, không thì bỏ. Cách làm này gọi là định tuyến bằng khóa (cryptokey routing): bảng định tuyến và kiểm soát truy cập gộp làm một.
Vì thế, ghi địa chỉ được phép của một đầu bên kia là 0.0.0.0/0 nghĩa là “mọi lưu lượng giao cho nó”, tức VPN toàn cục như người ta hay nói; chỉ ghi một dải mạng nội bộ thì chỉ khi truy cập dải đó mới đi qua đường hầm.
Bắt tay và mã hóa: một bộ thuật toán cố định
Trước lần liên lạc đầu tiên, hai thiết bị phải bắt tay: bên khởi xướng gửi một gói, bên đáp lại trả một gói, một đi một về là xong, hai bên có một bộ khóa phiên chỉ dùng trong khoảng thời gian đó. Bước bắt tay dựa trên khung giao thức Noise, dùng khóa dài hạn của hai bên để xác thực lẫn nhau, đồng thời dùng khóa tạm thời để bảo đảm bí mật chuyển tiếp (forward secrecy): kể cả sau này khóa riêng dài hạn bị lộ, lưu lượng đã bị ghi lại trước đó cũng không giải mã được.
Khóa phiên tự đổi sau mỗi vài phút, toàn bộ quá trình người dùng không thấy, và cũng không có chuyện “kết nối lại”.
Thuật toán mã hóa là cố định: trao đổi khóa dùng Curve25519, mã hóa dữ liệu dùng ChaCha20-Poly1305, băm dùng BLAKE2s. Không thương lượng thì cũng không có tấn công hạ cấp: kẻ tấn công không thể dụ hai bên chuyển sang thuật toán yếu hơn. Nếu sau này một thuật toán nào đó bị phá, cách xử lý là ra phiên bản giao thức mới thay thế toàn bộ, chứ không thêm một tùy chọn.
Ngoài ra có thể thêm một khóa chia sẻ trước (pre-shared key), dùng chồng lên cơ chế khóa công khai, để phòng nguy cơ máy tính lượng tử sau này đe dọa thuật toán khóa công khai.
Chỉ dùng UDP, không trả lời người lạ, đổi mạng không rớt
- Chỉ dùng UDP: WireGuard mã hóa riêng từng gói tin rồi bỏ vào một gói UDP gửi đi. Không dùng TCP là có chủ ý: chạy TCP bên trong TCP thì cả hai lớp cùng gửi lại, khi mất gói sẽ kéo nhau xuống.
- Không trả lời người lạ: gói nào chưa qua xác thực đều không được trả lời. Với kẻ quét cổng, cổng này trông như chưa mở, không có cách nào biết trên đó đang chạy WireGuard.
- Chuyển vùng (roaming): WireGuard không nhận “kết nối”, chỉ nhận khóa công khai. Đầu bên kia đổi địa chỉ, như điện thoại chuyển từ Wi‑Fi sang dữ liệu di động, thì chỉ cần gói tiếp theo nó gửi tới qua được xác thực, bên này tự gửi gói trả lời tới địa chỉ mới. Vì vậy đổi mạng mà đường hầm không đứt.
- Im lặng: khi không có dữ liệu cần gửi, đường hầm không tạo ra lưu lượng nào, nhờ vậy rất tiết kiệm pin trên điện thoại. Chỉ khi thiết bị nằm sau router mà vẫn cần luôn được bên kia tìm thấy, mới phải bật giữ kết nối định kỳ (PersistentKeepalive), cứ vài chục giây gửi một gói nhỏ để duy trì bảng ánh xạ trên router.
Vì sao nhanh
- Chạy trong nhân: trên Linux, WireGuard là một mô-đun nhân, gói tin không phải sao chép qua lại giữa nhân và chương trình người dùng; OpenVPN theo truyền thống chạy ở chế độ người dùng, mỗi gói phải đi vòng thêm một vòng.
- Thuật toán hợp với mọi CPU: ChaCha20 không cần lệnh tăng tốc phần cứng chuyên dụng, đặc biệt có lợi trên chip không có lệnh AES như điện thoại hay router.
- Bắt tay ngắn: một đi một về là gửi được dữ liệu, thiết lập kết nối gần như không phải chờ.
- Ít mã: đường xử lý ngắn, mọi tối ưu đều dồn vào vài bước then chốt.
- Cần lưu ý, những điều trên nói về chi phí của bản thân giao thức và phần cài đặt. Tốc độ thực tế trên đường truyền quốc tế phụ thuộc nhiều hơn vào tỷ lệ mất gói của đường truyền và thái độ của nhà mạng với UDP.
Lịch sử: từ dự án một người tới nhân Linux
- Khoảng năm 2015: Jason A. Donenfeld bắt đầu phát triển và công bố WireGuard, ban đầu là một mô-đun nhân độc lập trên Linux.
- Năm 2017: bài báo mô tả thiết kế của nó được trình bày tại hội nghị an ninh mạng NDSS, sau đó giao thức qua nhiều lần kiểm chứng hình thức độc lập. Cũng khoảng năm đó, các nhà cung cấp VPN như Mullvad bắt đầu cho kết nối bằng WireGuard.
- Năm 2018: Linus Torvalds, người sáng lập Linux, khen mã của nó trên danh sách thư và nói so với OpenVPN và IPsec thì nó đúng là một tác phẩm nghệ thuật; câu nói này khiến nó nổi tiếng trong giới lập trình.
- Năm 2019: Cloudflare phát hành BoringTun, bản cài đặt chạy ở chế độ người dùng viết bằng Rust, và dùng WireGuard cho WARP; NordVPN ra mắt NordLynx dựa trên WireGuard; Tailscale cũng khởi đầu trong giai đoạn này với WireGuard làm tầng dữ liệu.
- Tháng 3 năm 2020: WireGuard chính thức vào nhánh chính của nhân cùng Linux 5.6, đồng thời phát hành bản 1.0. Từ đó các bản phân phối Linux phổ biến đều có sẵn WireGuard, không phải cài thêm mô-đun. Cùng năm, OpenBSD cũng đưa nó vào nhân.
- Năm 2021: Windows có bản cài đặt chạy trong nhân là WireGuardNT, hiệu năng cao hơn hẳn bản chạy ở chế độ người dùng trước đó; FreeBSD sau đó cũng có bản trong nhân.
- Hiện nay: Windows, macOS, Linux, iOS, Android đều có ứng dụng chính thức, hệ thống router và NAS như OpenWrt, Synology phần lớn hỗ trợ sẵn, và đại đa số VPN thương mại đưa nó vào làm giao thức mặc định hoặc tùy chọn.
Những gì nó không làm, và giới hạn kéo theo
- Không lo phân phối khóa: mỗi lần thêm một thiết bị, phải ghi khóa công khai của nó vào cấu hình của các thiết bị khác. Thiết bị nhiều lên là quản không xuể, đó chính là lý do các công cụ như Tailscale ra đời.
- Không cấp địa chỉ động: địa chỉ nội bộ của mỗi đầu bên kia được ghi cứng trong cấu hình, không có cơ chế “kết nối xong thì cấp một địa chỉ” như OpenVPN. VPN thương mại khi dùng nó đều phải tự làm thêm một lớp bên ngoài.
- Băn khoăn về quyền riêng tư: máy chủ phải nhớ địa chỉ công khai gần nhất của mỗi đầu bên kia thì mới gửi gói trả lời được. Nhà cung cấp VPN cam kết “không lưu log” thường phải xử lý thêm (ví dụ xóa định kỳ, chuyển đổi địa chỉ hai lần).
- Chỉ có UDP: trên mạng chặn hoặc bóp UDP thì không thông hoặc rất chậm. Muốn cho nó đi TCP hay cổng 443, chỉ có cách bọc thêm một lớp công cụ khác bên ngoài.
- Không ngụy trang: định dạng và độ dài của gói bắt tay và gói dữ liệu đều có dấu hiệu cố định, rất dễ bị nhận ra. Mục tiêu thiết kế của nó là an toàn và đơn giản, không phải chống kiểm duyệt.
- Không có hệ thống tài khoản: trong giao thức không có khái niệm tên người dùng, mật khẩu, ngày hết hạn, nó chỉ nhận khóa công khai.
So với OpenVPN và IPsec
- Lượng mã: lõi WireGuard vài nghìn dòng; OpenVPN cộng thư viện TLS mà nó dựa vào, và các bản cài đặt IPsec, đều ở mức hàng trăm nghìn dòng.
- Truyền tải: WireGuard chỉ có UDP; OpenVPN dùng được cả hai, có thể đi TCP 443 lẫn vào cổng của lưu lượng HTTPS; IPsec dùng số hiệu giao thức riêng và UDP 500 / 4500.
- Cấu hình: WireGuard mỗi đầu bên kia vài dòng; file cấu hình OpenVPN nhiều tùy chọn nhưng rất linh hoạt; IPsec phức tạp nhất.
- Hiệu năng: trên mạng sạch, WireGuard thường nhanh nhất, tiết kiệm pin nhất; OpenVPN bản mới cũng đã có tăng tốc trong nhân (DCO), khoảng cách đang thu hẹp.
- Tính năng: xác thực bằng tài khoản mật khẩu, đẩy địa chỉ và định tuyến động, đi TCP, những thứ này OpenVPN có sẵn, còn WireGuard đều phải nhờ hệ thống bên ngoài bù vào.
- Thiết bị hỗ trợ: OpenVPN lâu đời, router cũ, NAS, đủ loại thiết bị nhúng gần như đều nhận; WireGuard đã phổ biến trên các hệ thống vài năm gần đây, thiết bị cũ thì chưa chắc có.
Những thứ mọc lên trên nền WireGuard
- Tailscale: thêm đăng nhập, phân phối khóa, xuyên NAT và chuyển tiếp lên trên WireGuard, thành một hệ thống tự động nối mạng; xem Tìm hiểu Tailscale. Headscale là bản máy chủ điều khiển mã nguồn mở của nó.
- Netmaker, NetBird, Firezone…: cũng là các sản phẩm nối mạng hoặc zero-trust theo kiểu “WireGuard làm tầng dữ liệu, tự làm tầng quản lý”.
- Cloudflare WARP: ứng dụng WireGuard cho người dùng phổ thông, đưa lưu lượng vào mạng của Cloudflare.
- Bản đóng gói riêng của VPN thương mại: NordLynx và các bản tương tự, thêm một lớp cấp địa chỉ và xử lý quyền riêng tư bên ngoài WireGuard.
- Các biến thể như AmneziaWG: sửa phần đầu gói và thêm phần đệm để che dấu hiệu cố định của WireGuard, dùng cho mạng kiểm tra gắt; chúng không tương thích với ứng dụng WireGuard chuẩn.
Trên mạng ở Trung Quốc
- Dùng được hay không, trước hết là do UDP: nhiều mạng cố định và di động bóp tốc độ UDP lưu lượng lớn, biểu hiện là mới kết nối thì nhanh, chạy một lúc thì chậm đi, hoặc giờ cao điểm buổi tối giật rõ.
- Kết nối thẳng qua biên giới dễ bị nhận ra: gói bắt tay của WireGuard có dấu hiệu cố định, trên đường truyền quốc tế có thể bị nhận diện và can thiệp, biểu hiện là không bắt tay được hoặc dùng một lúc thì mất luồng dữ liệu. Đây là hệ quả trực tiếp của việc giao thức không ngụy trang.
- Nối mạng giữa các thiết bị cùng ở trong Trung Quốc (công ty với nhà, điện thoại với NAS) không đi qua đường truyền quốc tế, thường không gặp vấn đề này, chỉ chịu ảnh hưởng của việc bóp UDP và tỷ lệ xuyên NAT thành công.
- Vì vậy nó hợp hơn với việc nối mạng và truy cập từ xa; muốn vượt biên ổn định lâu dài thì cần kết hợp với cách có ngụy trang hoặc đi được TCP / TLS; so sánh các giao thức xem bài So sánh giao thức VPN.
LeoTun dùng WireGuard ở đâu
Mục Mạng riêng của LeoTun dùng Tailscale, tầng dữ liệu chính là WireGuard: đường hầm giữa các thiết bị, đường hầm tới các node cổng ra ở từng khu vực, đều do nó mã hóa và truyền tải. Bạn không cần tự tạo khóa hay viết cấu hình, đăng nhập tài khoản trên trang của chúng tôi là ứng dụng tự làm hết. Cách dùng xem bài Mạng riêng (Tailscale) là gì, lối vào ở trang Mạng riêng.
Ngoài Mạng riêng, cùng tài khoản đó còn có những cách không phụ thuộc UDP: Cisco (AnyConnect) chạy TLS, OpenVPN đi được TCP, còn Hiddify (Hysteria2) chuyên trị mạng mất gói. Khi Mạng riêng vừa chậm vừa chập chờn trên mạng bạn đang dùng, cứ đổi sang cách khác; xem bài Mỗi cách kết nối hợp với tình huống nào.
FAQ
WireGuard hay OpenVPN tốt hơn?
Trên mạng sạch, không hạn chế UDP, WireGuard nhanh hơn, tiết kiệm pin hơn, đổi mạng không rớt; khi cần đi TCP, cần đăng nhập bằng tài khoản mật khẩu, hoặc thiết bị đã cũ thì OpenVPN hợp hơn. Cả hai đều là giao thức mã nguồn mở đã được kiểm nghiệm lâu dài, về độ an toàn đều đáng tin.
WireGuard có an toàn không?
Nó dùng một bộ thuật toán hiện đại nhưng thận trọng, giao thức đã qua kiểm chứng hình thức, mã ít nên dễ kiểm tra, hiện chưa có cách phá nào được biết tới trên thực tế. Cần lưu ý là nó không lo việc cất giữ và phân phối khóa: khóa riêng bị lộ, hoặc ghi khóa công khai nhầm đối tượng, thì bản thân giao thức không giúp được bạn.
Sao WireGuard chỉ hỗ trợ UDP?
Đó là lựa chọn thiết kế. Chạy TCP bên trong một kết nối TCP thì khi mất gói cả hai lớp cùng gửi lại, hiệu năng tụt mạnh; hơn nữa UDP giúp việc “không trả lời người lạ” và chuyển vùng dễ làm hơn. Cái giá là không dùng được trên mạng chặn UDP.
WireGuard có dùng được ở Trung Quốc không?
Nối mạng giữa các thiết bị cùng ở trong Trung Quốc thường là được. Kết nối thẳng qua biên giới thì không ổn định: lưu lượng của nó không ngụy trang, dễ bị nhận ra và can thiệp, cộng thêm một số đường truyền bóp UDP. Cần vượt biên ổn định thì phải kết hợp với cách có ngụy trang hoặc chạy TLS.
Ai phát triển WireGuard, vào nhân Linux khi nào?
Do Jason A. Donenfeld thiết kế và phát triển, công bố khoảng năm 2015; tháng 3 năm 2020 vào nhánh chính của nhân cùng Linux 5.6, đồng thời phát hành bản 1.0.
Tailscale có phải chính là WireGuard không?
Không phải cùng một thứ. WireGuard là giao thức đường hầm mã hóa; Tailscale là một hệ thống nối mạng dùng WireGuard để truyền dữ liệu, và giải quyết thêm chuyện đăng nhập, phân phối khóa, xuyên NAT và chuyển tiếp. Chi tiết xem Tìm hiểu Tailscale.
Dùng WireGuard có phải tự cấu hình khóa không?
Dùng WireGuard trực tiếp thì có: mỗi thiết bị tạo khóa, rồi ghi khóa công khai, địa chỉ, địa chỉ đầu bên kia vào cấu hình. Dùng qua Tailscale hoặc ứng dụng của VPN thương mại thì phần mềm làm thay. Với Mạng riêng của LeoTun, chỉ cần đăng nhập tài khoản.