Tự host relay RustDesk trên VPS: cài hbbs, hbbr
Chạy hbbs và hbbr trên VPS riêng với key Ed25519, image tag cố định, port được khóa và cách tính bandwidth relay mà gói VPS của bạn phải trả.
RustDesk relay server tự host là gì
RustDesk relay server tự host gồm hai daemon chạy trên một VPS. hbbs là server ID và rendezvous: nó đăng ký mọi ID client và kết nối hai client với nhau. hbbr là relay server: nó truyền tải dữ liệu phiên làm việc, nhưng chỉ dành cho các phiên không thể kết nối trực tiếp. Hầu hết các hướng dẫn chỉ dừng lại ở việc cài đặt cả hai và ghép nối thành công. Phần dưới đây là các công việc còn lại: key dùng để kiểm soát truy cập, các cổng, nâng cấp và băng thông.
Cả hai daemon đều có trong cùng một image, rustdesk/rustdesk-server, và trong thiết lập dưới đây, cả hai đều đọc cùng một cặp key Ed25519 từ cùng một thư mục. Đây là cấu hình bạn phải thực hiện, không phải mặc định: hbbs tự tải hoặc tạo cặp key, nhưng hbbr sẽ bỏ qua các key trừ khi bạn khởi chạy nó kèm theo key. Ed25519 là một cơ chế chữ ký khóa công khai. Cặp key đó quyết định server của bạn sẽ giao tiếp với client nào, và không có cơ sở dữ liệu người dùng nào phía sau nó.
hbbs và hbbr: daemon nào làm tốn bandwidth
Traffic của hbbs nhỏ và ổn định: đăng ký ID, heartbeat và một lượt trao đổi ngắn để giới thiệu hai peer với nhau. hbbs chạy cả ngày nhưng gần như không tốn bandwidth.
Traffic của hbbr chính là session. Frame màn hình đi theo một chiều, bàn phím và chuột đi theo chiều ngược lại. Mỗi byte được relay đều đi vào VPS của bạn rồi lại đi ra. Nếu provider chỉ tính egress, một session relay sẽ tốn khoảng bằng tốc độ của session. Nếu provider tính tổng transfer, chi phí sẽ khoảng gấp đôi.
Relay là phương án dự phòng, không phải đường đi thông thường. Trước tiên hbbs cố kết nối trực tiếp 2 client bằng hole punching qua NAT (network address translation) đang đứng trước mỗi client. Nếu kết nối thành công, session không đi qua hbbr và không làm giảm transfer allowance của bạn. Nếu một phía nằm sau NAT cấp port mới cho từng destination, hoặc firewall chặn đường đi được tạo bằng hole punching, session sẽ chuyển sang hbbr. Khi đó mọi frame đều đi qua VPS của bạn.
Một biến môi trường sẽ loại bỏ lựa chọn này. ALWAYS_USE_RELAY=Y trên hbbs buộc mọi session đi qua hbbr. Tài liệu RustDesk có dùng biến này trong một ví dụ Compose, nên nó thường bị sao chép theo. Biến này làm kết nối dễ dự đoán hơn, đồng thời khiến egress thực sự phát sinh. Chỉ đặt biến này khi bạn đã chủ động quyết định, không phải vì dán nguyên cấu hình mẫu.
Các cổng cần mở cho RustDesk server tự host
Các số cổng dưới đây đã được kiểm tra dựa trên tài liệu của RustDesk server và kho lưu trữ rustdesk-server vào ngày 10 tháng 10 năm 2026.
- TCP 21115, trên hbbs: kiểm tra loại NAT.
- UDP 21116, trên hbbs: đăng ký ID và heartbeat. Đây là đường truyền mặc định mà client sử dụng.
- TCP 21116, trên hbbs: đăng ký ID cho các client chỉ thiết lập dùng TCP, cùng với TCP hole punching và dịch vụ kết nối.
- TCP 21117, trên hbbr: relay. Đây là cổng truyền tải dữ liệu phiên làm việc, vì vậy đây là cổng tiêu tốn băng thông của bạn.
- TCP 21118 trên hbbs và TCP 21119 trên hbbr: WebSocket, được sử dụng bởi trình duyệt client. Hãy đóng cả hai nếu bạn không sử dụng tính năng này.
- TCP 21114 là HTTP API server trong RustDesk Server Pro. Bản build mã nguồn mở không lắng nghe trên cổng này.
Cài đặt hbbs và hbbr với image tag cố định
services:
hbbs:
container_name: hbbs
image: rustdesk/rustdesk-server:1.1.16
command: hbbs
volumes:
- ./data:/root
network_mode: "host"
depends_on:
- hbbr
restart: unless-stopped
hbbr:
container_name: hbbr
image: rustdesk/rustdesk-server:1.1.16
command: hbbr -k _
volumes:
- ./data:/root
network_mode: "host"
restart: unless-stoppedmkdir -p ~/rustdesk
cd ~/rustdesk
# save the block above as ~/rustdesk/compose.yml before this line
sudo docker compose up -d
sudo docker compose psCả hai dịch vụ cần đọc running. Hãy xác nhận các listener đã tồn tại trước khi bạn đụng đến firewall.
sudo ss -tlnp | grep -E ':2111[5-7]'
sudo ss -ulnp | grep ':21116'Bạn sẽ thấy các TCP listener trên cổng 21115, 21116 và 21117, cùng một UDP listener trên cổng 21116. Nếu thiếu dòng UDP, nghĩa là hbbs không chạy, vì hbbs mở listener đó khi khởi động và đây là cổng mà các client mặc định dùng để đăng ký.
Có bốn điểm trong file đó là cố ý. Tag là 1.1.16, vẫn là bản release hiện tại tính đến tháng 10 năm 2026, được phát hành ngày 20 tháng 7 năm 2026, thay vì dùng latest. Lý do là latest có nghĩa là bất cứ thứ gì được đẩy lên gần đây nhất, và một docker compose pull vào sáu tháng tới có thể mang đến cho bạn một server mà bạn chưa từng kiểm thử. network_mode: "host" bind trực tiếp vào các interface của host, đây là cách mà tài liệu RustDesk khuyến nghị và nó quyết định cách firewall của bạn hoạt động. ./data:/root map thư mục làm việc của image ra host, để cặp key nằm ở nơi bạn có thể backup. Và hbbr -k _ là thay đổi duy nhất so với ví dụ gốc, vì cấu hình mặc định sẽ để relay của bạn mở cho bất kỳ ai. Nếu bạn mới làm quen với Compose, chạy Docker Compose trên VPS sẽ bao quát định dạng file và các lệnh quản lý vòng đời.
Nếu hbbr chuyển sang server thứ hai, hbbs cần được chỉ định nơi nó chuyển đến: truyền tham số -r relay.example.com:21117, hoặc thiết lập biến môi trường RELAY-SERVERS. Trên một máy đơn lẻ, bạn không cần làm điều này.
Cặp key Ed25519 là cơ chế kiểm soát quyền truy cập
Khi khởi động lần đầu, hbbs tạo id_ed25519 và id_ed25519.pub trong thư mục làm việc của nó. Với mount ở trên, cả hai file này đều xuất hiện trên host.
ls -l ~/rustdesk/data/
sudo cat ~/rustdesk/data/id_ed25519.pubid_ed25519.pub chứa một chuỗi base64. Nhập chuỗi này vào trường Key trên mọi client. id_ed25519 là phần private và không bao giờ rời khỏi server. Public key không phải thông tin bí mật vì nó vốn được sao chép vào cấu hình của mọi client. Private key là thông tin bí mật: bất kỳ ai có nó đều có thể dựng một server mà client của bạn sẽ tin cậy.
Hãy backup cả hai file ngay bây giờ, trước khi bạn cấu hình 20 client.
sudo tar czf ~/rustdesk-keys.tgz -C ~/rustdesk/data id_ed25519 id_ed25519.pub
sudo chmod 600 ~/rustdesk-keys.tgzSao chép archive đó ra khỏi máy. Đây là lý do bước này quan trọng hơn mọi bước khác. Nếu xóa ~/rustdesk/data hoặc rebuild trên một VPS mới mà không sao chép file này, hbbs sẽ tạo một cặp key mới ở lần khởi động tiếp theo. Mọi client vẫn chứa public key cũ, nên hbbs từ chối chúng và client chuyển sang offline. Chạy sudo cat ~/rustdesk/data/id_ed25519.pub rồi so sánh kết quả với trường Key trên bất kỳ client nào: hai chuỗi không còn khớp, và chính sự không khớp đó gây ra toàn bộ lỗi. Muốn sửa, bạn phải chỉnh settings thủ công trên từng máy, kể cả những máy bạn dựa vào RustDesk để truy cập.
Key không phải session password. Nhầm lẫn hai thứ này khiến nhiều người bỏ qua một trong hai. Key quyết định server sẽ giao tiếp với những client nào. Permanent password hoặc one time code trên máy được điều khiển quyết định ai được mở session trên máy đó. Bạn cần cả hai. Có một thứ không thể bù cho thứ còn lại nếu nó yếu.
Tại sao relay không xác thực lại là một vấn đề
Theo mặc định, hbbr không kiểm tra bất cứ thứ gì. Tài liệu cấu hình RustDesk nêu rõ: một key trống cho phép các client không có key khớp vẫn có thể sử dụng relay. Giá trị mặc định trống này tồn tại để người dùng mới không gặp lỗi sai lệch key ngay lần chạy đầu tiên. Cái giá phải trả là bất kỳ ai tìm thấy địa chỉ của bạn trên cổng TCP 21117 đều có thể đẩy lưu lượng phiên làm việc của họ qua VPS của bạn, sử dụng hạn mức truyền tải của bạn và từ địa chỉ IP của bạn.
command: hbbr -k _ giải quyết vấn đề đó. Đối số _ yêu cầu hbbr tải cặp key từ thư mục làm việc của nó, hoặc tạo mới nếu chưa có, và vì cả hai container đều mount cùng một ./data, đó chính là cặp key mà hbbs sử dụng. Không có gì phải sao chép thủ công, nên không thể xảy ra sai lệch.
Volume dùng chung là phần mọi người thường làm sai. Nếu cấp cho hbbr một thư mục riêng, nó sẽ tạo ra một cặp key khác. Khi đó hbbs và hbbr không khớp nhau, mọi phiên relay đều thất bại, trong khi các phiên kết nối trực tiếp vẫn hoạt động. Triệu chứng này gây khó hiểu: RustDesk kết nối được với một số peer nhưng không kết nối được với các peer khác, tùy thuộc vào việc hole punching có thành công hay không. Một ls -l ~/rustdesk/data/ hiển thị một cặp id_ed25519 duy nhất sẽ loại trừ khả năng sai lệch đó. Nó không chứng minh được relay đã kiểm tra key, vì hbbr sẽ bỏ qua các file đó trừ khi nó được khởi chạy với một key không trống, vì vậy hãy xác nhận cả lệnh đang chạy:
ps -eo args | grep '[h]bbr'Lệnh đó sẽ in ra hbbr -k _. Một lệnh hbbr trơ trọi nghĩa là relay vẫn đang mở, bất kể có gì nằm trong thư mục đó.
Trỏ các client về server của bạn
Trên mỗi máy, mở RustDesk, sau đó vào Settings, chọn Network, rồi đến ID/Relay Server.
- ID Server: hostname của bạn, ví dụ
rustdesk.example.com. Client sử dụng cổng 21116 trừ khi bạn chỉ định một cổng khác. - Relay Server: để trống nếu hbbr chạy trên cùng host với hbbs.
- API Server: để trống. Phiên bản mã nguồn mở không cung cấp tính năng này.
- Key: chuỗi base64 từ
id_ed25519.pub, dán chính xác, không có khoảng trắng thừa ở cuối.
Cửa sổ chính sau đó sẽ báo rằng client đã sẵn sàng. Nếu không, và client đang chạy với thiết lập mặc định, nguyên nhân thường là do UDP 21116 không tới được hbbs, vì đó là nơi client mặc định đăng ký và gửi tín hiệu heartbeat. Tuy nhiên, trạng thái ID offline không tự khẳng định điều này. Một client đã thiết lập tùy chọn disable-udp thành Y sẽ đăng ký qua TCP 21116 thay vì dùng UDP 21116, vì vậy với client đó, hãy kiểm tra TCP 21116 trước.
Giới hạn các cổng để relay không trở thành dịch vụ mở
Vì các container sử dụng host networking, không có quy tắc Docker NAT nào đứng trước chúng, nên các quy tắc ufw sẽ áp dụng đúng như bạn mong đợi.
sudo ufw allow 22/tcp
sudo ufw allow 21115:21117/tcp
sudo ufw allow 21116/udp
sudo ufw enable
sudo ufw status numberedChỉ thêm 21118:21119/tcp nếu bạn chạy client trình duyệt. Hãy giữ một phiên SSH thứ hai mở trong khi bạn bật ufw, để một sai sót trong quy tắc SSH không khiến bạn bị khóa khỏi máy chủ của chính mình. Các kiến thức cơ bản về tường lửa ufw cho VPS bao gồm các chính sách mặc định và thứ tự quy tắc.
Bây giờ là cái bẫy. Nếu bạn chuyển sang publish cổng bằng khối ports:, cách mà nhiều ví dụ về RustDesk container đơn lẻ sử dụng, Docker sẽ tự ghi các quy tắc DNAT của riêng nó và các gói tin sẽ đến container mà không đi qua chuỗi chứa các quy tắc ufw của bạn. Khi đó, lệnh ufw deny trên cổng 21117 sẽ không có tác dụng, và relay vẫn mở ra Internet trong khi ufw status lại báo ngược lại. Docker published ports bỏ qua ufw giải thích về thứ tự chuỗi này. Host networking tránh được vấn đề này hoàn toàn. Nếu bạn thực sự cần publish một cổng, hãy bind nó vào một địa chỉ cụ thể, như trong "127.0.0.1:21118:21118" phía sau một reverse proxy.
Việc giới hạn theo địa chỉ nguồn chỉ hiệu quả khi các client của bạn có địa chỉ ổn định.
sudo ufw allow from 203.0.113.0/24 to any port 21115:21117 proto tcp
sudo ufw allow from 203.0.113.0/24 to any port 21116 proto udpLaptop trên mạng khách sạn không có địa chỉ ổn định, đó chính là lý do tại sao key trên hbbr thực hiện công việc bảo mật thực tế ở đây nhiều hơn là tường lửa.
Nâng cấp stack chứa key của bạn
Key nằm trong bind mount, không nằm bên trong container, nên việc nâng cấp an toàn miễn là bạn không thay đổi ./data.
- Sao lưu thư mục dữ liệu trước:
sudo tar czf ~/rustdesk-data-backup.tgz -C ~/rustdesk data. - Đọc release notes của tag mới trên trang releases của rustdesk-server.
- Chỉnh sửa
compose.ymlvà thay đổi cả hai dòngimage:thành tag mới. - Chạy
sudo docker compose pull, sau đó chạysudo docker compose up -d. - Chạy
sudo cat ~/rustdesk/data/id_ed25519.pubvà xác nhận chuỗi này giống với chuỗi mà các client hiện đang lưu.
Bước 5 là bước kiểm tra quan trọng nhất, vì key bị thay đổi sẽ không tạo ra cảnh báo trên server nhưng làm hỏng kết nối của mọi client cùng lúc. Rollback bằng cách đặt lại tag cũ rồi chạy lại up -d. Cách này chỉ hoạt động vì bạn đã pin tag: với latest, docker compose pull đã chuyển tên sang image mới, nên không còn tag nào trỏ đến image cũ.
Cách thường làm mất key không phải là docker compose down, vì lệnh này không thay đổi bind mount. Nguyên nhân thường là khi chuyển sang VPS mới và chỉ sao chép compose.yml. Hãy sao chép cả ./data.
Giám sát lưu lượng egress trên gói có giới hạn transfer
hbbr là thành phần duy nhất trong stack này có thể tiêu thụ transfer allowance. FAQ của RustDesk ước tính một kết nối được relay trên màn hình 1920x1080 sử dụng từ 30 KB/s đến 3 MB/s, còn tác vụ văn phòng thông thường khoảng 100 KB/s. Đây là số liệu được công bố cho một session đơn lẻ, không phải kết quả đo trên setup của bạn. Nhân với sáu mươi giờ mỗi tháng, tương đương hai giờ mỗi ngày, ta có các mức sau.
Dữ liệu đằng sau biểu đồ này
[
{
"label": "Low end, 30 KB/s",
"gb_per_month": 6.5
},
{
"label": "Office work, 100 KB/s",
"gb_per_month": 21.6
},
{
"label": "High end, 3 MB/s",
"gb_per_month": 648
}
]Ở mức sử dụng cho tác vụ văn phòng, một session tiêu tốn khoảng 21.6 GB mỗi tháng, mức mà mọi plan đều không đáng kể. Ở mức cao nhất trong khoảng được công bố, cùng sáu mươi giờ đó tiêu tốn 648 GB, và hai session đồng thời ở mức này sẽ vượt allowance 1 TB trong tháng. Mức thấp nhất là 6.5 GB. Ở đây, gigabyte được tính là 1000 MB, đúng với cách các transfer allowance thường được tính.
docker stats không thể phân tích riêng phần này cho bạn, vì container dùng host networking sẽ chia sẻ network namespace của host, nên các counter của nó cũng chính là counter của host. Có hai công cụ khác thực hiện được việc này. vnstat đo toàn bộ máy:
sudo apt install -y vnstat
sudo systemctl enable --now vnstat
vnstat -mToàn bộ máy nghĩa là toàn bộ máy: nếu VPS này cũng chạy một dịch vụ truyền dữ liệu thực, chẳng hạn một trong các photo server tự host lấy thư viện ảnh từ điện thoại lên mỗi đêm, lưu lượng upload của nó sẽ được tính chung vào mức sử dụng hàng tháng với lưu lượng relay. Media server cũng tương tự theo chiều ngược lại, vì một dịch vụ như Halcyon, biến thư viện Jellyfin thành một video store thập niên 90 có thể duyệt được sẽ stream dữ liệu ra cho người xem, và lưu lượng egress đó dùng chung allowance với relay.
Một counter của nftables đo riêng relay:
sudo nft add table inet relaymeter
sudo nft add chain inet relaymeter out '{ type filter hook output priority 0 ; }'
sudo nft add rule inet relaymeter out tcp sport 21117 counter
sudo nft list table inet relaymeterRule này không có verdict, nên chỉ đếm packet và byte mà không thay đổi lưu lượng nào được phép đi qua. Nó nằm trong một table riêng để không ảnh hưởng đến ufw. Counter này không persistent: nếu muốn nó hoạt động lại sau reboot, hãy thêm các dòng tương tự vào /etc/nftables.conf. Counter chỉ tăng khi một session thực sự được relay. Nếu counter tiếp tục tăng trong khi không máy nào của bạn đang kết nối, nghĩa là có người khác đã tìm thấy relay của bạn. Đây là tình huống hbbr -k _ được tạo ra để ngăn chặn. Vì bạn sẽ không đọc nft list mỗi sáng, hãy đặt một cron job để so sánh số byte với một threshold và gửi push alert khi vượt ngưỡng. Đây là việc phù hợp với ntfy server của riêng bạn.
hbbr cũng có rate limit mà bạn có thể hạ xuống. SINGLE_BANDWIDTH mặc định là 128 Mb/s cho mỗi kết nối relay, còn TOTAL_BANDWIDTH là 1024 Mb/s cho toàn bộ các kết nối. Đặt SINGLE_BANDWIDTH=8 sẽ giới hạn một session ở khoảng 1 MB/s. Thiết lập này giới hạn tốc độ, không giới hạn tổng dung lượng hàng tháng. Vì vậy, hãy xem đây là cách ngăn một session chiếm hết bandwidth của link, không phải công cụ kiểm soát ngân sách.
Khi bạn hoàn toàn không cần relay
Với thiết lập cá nhân, câu trả lời chính xác là bạn có thể không cần bất kỳ thành phần nào trong số này. Đưa cả hai máy vào một mesh VPN và kết nối trực tiếp bằng địa chỉ của tunnel. Không cần hbbs, không cần hbbr, không có relay egress và không cần container trên VPS để nâng cấp.
Trên máy bạn muốn điều khiển, bật quyền truy cập IP trực tiếp trong phần cài đặt bảo mật của RustDesk. Trường port mặc định là 21118. Kiểm tra port đang listening trước khi thử kết nối:
ss -tlnp | grep 21118Sau đó kết nối đến địa chỉ VPN của peer đó thay vì dùng ID. FAQ của RustDesk cho biết kết nối trong chế độ này không được mã hóa, vì vậy hãy chạy nó bên trong tunnel và tuyệt đối không kết nối qua Internet công cộng. Tunnel mới là thành phần cung cấp mã hóa.
Hãy chọn mô hình dựa trên việc ai sở hữu các máy. Tự host hbbs và hbbr phù hợp khi bạn hỗ trợ các máy không thuộc sở hữu của mình hoặc người dùng sẽ không bao giờ cài VPN client, vì phía họ chỉ cần dùng ID và password. Mesh VPN với quyền truy cập IP trực tiếp phù hợp khi mọi máy đều thuộc sở hữu của bạn và có thể lưu một key. WireGuard so với Tailscale trình bày hai cách phổ biến để xây dựng mesh đó, còn chạy remote desktop trên Linux VPS trình bày trường hợp còn lại, khi máy bạn muốn xem màn hình chính là server.
FAQ
Mọi phiên RustDesk có đi qua relay của tôi không?
Không. hbbs trước tiên cố gắng kết nối trực tiếp hai client bằng cách sử dụng hole punching qua NAT phía trước mỗi máy. Chỉ những phiên thất bại mới chuyển sang dùng hbbr, và chỉ những phiên đó mới tiêu tốn băng thông của bạn. Ngoại lệ là ALWAYS_USE_RELAY=Y trên hbbs, nó ép mọi phiên phải đi qua hbbr bất kể có đường truyền trực tiếp hay không. Nếu biến đó được thiết lập trong file Compose của bạn, mọi byte của mọi phiên đều sẽ tính vào hóa đơn lưu lượng của bạn.
Key của RustDesk server được lưu ở đâu, và nếu mất thì sao?
hbbs tạo ra id_ed25519 và id_ed25519.pub trong thư mục làm việc của nó ở lần khởi động đầu tiên. Thư mục đó là /root bên trong image chính thức, vì vậy với volume mount như đã hiển thị ở trên, các file này sẽ xuất hiện tại ./data trên host. Hãy backup cả hai file này ra khỏi server. Nếu bị mất, hbbs sẽ tạo một cặp mới ở lần khởi động tiếp theo, và mọi client vẫn giữ public key cũ sẽ bị từ chối. Không có cách khôi phục nào khác ngoài việc phải chỉnh sửa thủ công trường Key trên từng client.
Tôi cần mở những cổng nào cho RustDesk server tự host?
TCP 21115, 21116 và 21117, cộng với UDP 21116. hbbs dùng 21115 để kiểm tra loại NAT, và 21116 để đăng ký ID và heartbeat qua UDP, cũng như để đăng ký và hole punching qua TCP. hbbr dùng 21117 cho relay. TCP 21118 và 21119 là các cổng WebSocket cho client trên trình duyệt, vì vậy hãy đóng chúng nếu bạn không sử dụng. TCP 21114 thuộc về Pro HTTP API server và bản open source không cần dùng đến nó.
Người lạ có thể sử dụng relay RustDesk tự host của tôi không?
Có, nếu bạn chạy hbbr với cấu hình mặc định. Tài liệu của RustDesk nêu rằng một key trống cho phép các client không có key khớp vẫn sử dụng được relay, vì vậy bất kỳ ai biết hostname và cổng 21117 của bạn đều có thể đẩy lưu lượng qua server của bạn. Hãy chạy hbbr với -k _ để nó load cùng cặp key mà hbbs sử dụng từ volume ./data dùng chung. Sau đó, chỉ những client được cấu hình với public key của bạn mới có thể relay qua server của bạn.