器地址與Key)
最近又把 RustDesk 的自建鏈路完整走了一遍服務(wù)器端自己編譯 hbbs/hbbr客戶端也自己編譯并且把自建 ID 服務(wù)器地址和 key 直接寫進了客戶端里。折騰完之后最大的感受是一旦服務(wù)器和 key 不用手動填整個分發(fā)體驗完全不一樣——給別人發(fā)一個安裝包對方裝上打開就能連你自己的服務(wù)器不用解釋什么叫 ID 服務(wù)器、什么叫 key更不用在多個輸入框之間來回切。這篇文章我就把整個過程中我認為最關(guān)鍵的幾個環(huán)節(jié)包括服務(wù)端部署、客戶端編譯、以及三種把服務(wù)器信息固化進客戶端的方法原原本本記錄下來給打算自己搞一套 RustDesk 遠程方案的朋友做個參考。1. 為什么非要把服務(wù)器和 key 編進客戶端不可1.1 公共服務(wù)器與自建服務(wù)器的差距RustDesk 官方公共服務(wù)器對個人偶爾用一下來說是夠的但一旦你把它當日常工具問題馬上會浮現(xiàn)高峰期連接不穩(wěn)、跨地域延遲忽高忽低、中繼帶寬有限。更重要的是數(shù)據(jù)鏈路完全不受你控制這對企業(yè)用戶或者對隱私比較敏感的人來講始終是個心結(jié)。自建之后整套鏈路都在自己手里客戶端向你的 ID 服務(wù)器注冊身份、兩個設(shè)備互相發(fā)現(xiàn)、中繼服務(wù)器轉(zhuǎn)發(fā)流量全走你自己的機器和帶寬。這在企業(yè)內(nèi)網(wǎng)、跨地域小團隊、或者單純喜歡數(shù)據(jù)可控的個人場景里價值非常明顯。1.2 真正的痛點不是部署而是客戶端配置服務(wù)端部署好之后你自己用很簡單填一下地址和 key 就行。但如果你要把客戶端分發(fā)給同事、客戶或者家里好幾臺設(shè)備重裝系統(tǒng)問題就來了——非技術(shù)用戶面對ID 服務(wù)器中繼服務(wù)器Key這幾個輸入框很容易卡住。key 尤其容易錯。它是服務(wù)器生成的 ed25519 公鑰一長串 base64 字符串復(fù)制粘貼時前面多一個空格、或者換行被帶進去都會導(dǎo)致連接失敗界面上彈出一個很費解的提示。我見到的key 值未知錯誤多半就是這么來的。1.3 三種寫入方式的利弊對比把服務(wù)器地址和 key 固化進客戶端常見有三條路編譯期改默認值、預(yù)置配置文件、安裝后腳本注入。我分別試過先給個對比。方案侵入性分發(fā)體驗適用場景編譯期改默認值每次升級要重新改最好開箱即用固定服務(wù)器的團隊長期使用預(yù)置配置文件/數(shù)據(jù)庫無拷貝文件即可好但要在首次啟動前放好批量機器、臨時分發(fā)界面手動填寫無差依賴使用者操作個人自用、個位數(shù)設(shè)備實際項目中我傾向于組合使用編譯期改默認值解決開箱即用的問題配置文件預(yù)置應(yīng)對那些老版本客戶端或者不想重新編譯的機器。2. 服務(wù)端先行hbbs/hbbr 部署與 key 生成2.1 服務(wù)端源碼編譯RustDesk 的服務(wù)端是獨立倉庫rustdesk-server包含兩個核心二進制hbbs是 ID 服務(wù)器和信令服務(wù)器負責(zé)設(shè)備注冊與連接協(xié)商hbbr是中繼服務(wù)器負責(zé)在無法直連時為兩端轉(zhuǎn)發(fā)流量。編譯過程很簡單git clone https://github.com/rustdesk/rustdesk-server.git cd rustdesk-server cargo build --release編譯產(chǎn)物在target/release/目錄下我們需要的是hbbs和hbbr這兩個文件。如果你的服務(wù)器內(nèi)存偏小編譯時間會比較長建議放到 2G 內(nèi)存以上的機器上操作或者干脆用官方 release 里的預(yù)編譯二進制。標題既然講自己編譯這里就走源碼編譯路線。2.2 首次運行生成 key把hbbs、hbbr放到服務(wù)器的固定目錄比如/opt/rustdesk-server/然后第一次啟動cd /opt/rustdesk-server ./hbbs -r your-server.com:21117 ./hbbr第一次運行后目錄下會生成id_ed25519和id_ed25519.pub兩個文件。id_ed25519.pub里的內(nèi)容就是客戶端設(shè)置界面需要填的那個 key。這串公鑰相當于服務(wù)器身份憑證客戶端拿著它才能確認自己連的服務(wù)器確實是你搭的那臺防止中間人冒充。這里有一個非常容易踩的坑id_ed25519私鑰必須備份好并且不要隨意刪除。一旦服務(wù)端目錄被清空導(dǎo)致重新生成密鑰所有已經(jīng)配置好的客戶端都會彈出 key 不匹配的提示全部要重新改配置相當痛苦。2.3 端口清單與防火墻放行服務(wù)端需要放行的端口有規(guī)律整理成一張表方便對照端口協(xié)議用途21115TCPNAT 類型檢測21116TCP UDP客戶端注冊與信令交換UDP 為主21117TCPhbbr 中繼數(shù)據(jù)傳輸21118TCPWeb 客戶端支持可選21119TCPWeb 中繼支持可選如果你在云服務(wù)器上部署除了服務(wù)器本身的防火墻iptables/firewalld/ufw還要檢查云控制臺的安全組規(guī)則兩個地方都得放行。國內(nèi)用戶如果喜歡用寶塔面板也要在面板防火墻里同步放行這些端口不然客戶端能 ping 通機器但連接總是超時。2.4 用 systemd 守護進程nohup ... 在調(diào)試階段沒問題但生產(chǎn)環(huán)境我更推薦用 systemd 托管防止進程掛掉后沒人管。寫兩個 service 文件分別守護hbbs和hbbr啟動命令里帶上-r參數(shù)指定中繼地址并設(shè)置開機自啟。# /etc/systemd/system/rustdesk-hbbs.service [Unit] DescriptionRustDesk ID Server Afternetwork.target [Service] Typesimple WorkingDirectory/opt/rustdesk-server ExecStart/opt/rustdesk-server/hbbs -r your-server.com:21117 Restartalways RestartSec3 [Install] WantedBymulti-user.targethbbr的 service 文件照葫蘆畫瓢ExecStart 換成/opt/rustdesk-server/hbbr即可。3. 客戶端編譯環(huán)境版本選型與依賴準備3.1 RustDesk 客戶端的兩個時代RustDesk 客戶端源碼變化很大網(wǎng)上教程用的是老版本v1.1.xSciter UI而現(xiàn)在已經(jīng)普遍切換到 Flutter UI 的新版本v1.2、v1.3。兩代產(chǎn)品的編譯方式和源碼路徑都不一樣如果你跟著老教程走很可能會卡在某一步找不到對應(yīng)文件。我的建議是直接用當前官方 release tag比如 v1.3.x不要盲目追 master。master 分支處于持續(xù)開發(fā)狀態(tài)今天能編譯明天可能因為一個依賴變更就報錯。鎖定穩(wěn)定版本遇到問題也好查。git clone https://github.com/rustdesk/rustdesk.git cd rustdesk git checkout v1.3.x3.2 Linux 編譯環(huán)境在 Linux 下編譯 Linux 客戶端需要準備 Rust 工具鏈和一堆系統(tǒng)依賴。Rust 安裝用 rustup 官方腳本即可curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh系統(tǒng)庫方面Ubuntu/Debian 系大致需要這些sudo apt install build-essential pkg-config cmake git \ libgtk-3-dev libssl-dev libasound2-dev libavcodec-dev \ libavformat-dev libavutil-dev libswscale-dev \ libx11-dev libxext-dev libxinerama-dev libxcursor-dev \ libxdamage-dev libxfixes-dev libxi-dev libxkbcommon-dev \ libvpx-dev libopus-dev不同版本的依賴列表會變最權(quán)威的還是倉庫里的 README 和build.py腳本。我的經(jīng)驗是把build-essential、pkg-config、libssl-dev、libgtk-3-dev這幾個裝好大部分編譯錯誤就能消掉一半。3.3 Windows 編譯環(huán)境Windows 下編譯 Windows 客戶端條件會多一點安裝 Visual Studio Build Tools 2019 或 2022勾選使用 C 的桌面開發(fā)工作負載。安裝 Rust 的 MSVC 工具鏈。安裝 vcpkg并配置VCPKG_ROOT環(huán)境變量。通過 vcpkg 安裝 RustDesk 依賴的 C 庫比如libvpx。git clone https://github.com/microsoft/vcpkg.git cd vcpkg .\bootstrap-vcpkg.bat .\vcpkg install libvpx:x64-windows-static $env:VCPKG_ROOT C:\path\to\vcpkg在 Windows 上最穩(wěn)妥的編譯方式是用x64 Native Tools Command Prompt for VS打開終端再執(zhí)行 cargo 命令。否則容易遇到link.exe找不到的問題。3.4 新版 Flutter UI 的額外步驟如果你拉取的是 Flutter UI 版本編譯時還需要 Flutter SDK。桌面客戶端通常是先編譯 Rust 核心再構(gòu)建 Flutter 界面層。手動步驟繁瑣官方提供了build.py腳本建議直接用python build.py --flutter --release這個腳本會處理 Rust 和 Flutter 兩部分的構(gòu)建并且自動把它們打包成安裝包。如果你想驗證自己的代碼修改也可以先只跑cargo build --release構(gòu)建單獨的 Rust 可執(zhí)行文件。4. 把 ID 服務(wù)器和 key 寫進客戶端的三種做法4.1 做法一編譯期改默認常量這是最徹底的方案也是標題里說的寫入客戶端的標準做法。思路很簡單RustDesk 客戶端源碼里必然存在一組默認服務(wù)器地址和默認 key程序首次啟動時會讀這些默認值。我們只要把它們改成自己的服務(wù)器和公鑰就行。問題是不同版本的源碼位置差別很大不能直接告訴你改哪個文件。我提供的通用定位方法是用 grep 搜索# 在 RustDesk 客戶端源碼根目錄執(zhí)行 grep -rn rustdesk.com --include*.rs src libs 2/dev/null grep -rn rendezvous --include*.rs -i src libs 2/dev/null在 v1.1.x 時代常見位置是src/common/constants.rs里面會有一個類似RENDEZVOUS_SERVER的常量。在較新的版本中這些默認值可能挪到了libs/hbb_common/src/config.rs之類的地方。找到之后把默認服務(wù)器地址改成你自己的域名或 IP把默認 key 改成id_ed25519.pub的內(nèi)容。下面是一個示意性的修改片段不同版本字段名和路徑可能不同核心思路是一樣的// 示意代碼實際位置以你搜索到的源碼為準 pub const RENDEZVOUS_SERVER: str your-server.com; pub const KEY: str 你的 ed25519 公鑰字符串一長串 base64;改完重新編譯客戶端一啟動就會拿這些值去連接你的服務(wù)器。這里有個非常關(guān)鍵的前提目標機器上不能有舊的 RustDesk 配置。如果客戶端已經(jīng)運行過一次本地存儲的配置優(yōu)先級高于編譯期默認值你改半天編譯配置也不會生效。測試時要把~/.config/rustdeskLinux或%APPDATA%\RustDeskWindows刪掉再啟動。4.2 做法二預(yù)置配置文件編譯期改默認值有個問題每次升級版本都要重新改、重新編譯。如果你只是想快速批量設(shè)置一批機器配置文件預(yù)置法更省事。具體流程是這樣的準備一臺干凈的測試機安裝官方或自編譯的客戶端。打開設(shè)置界面手動填入 ID 服務(wù)器地址、中繼服務(wù)器地址和 key確認能正常連接。關(guān)閉客戶端找到配置文件。Windows 在%APPDATA%\RustDesk\Linux 在~/.config/rustdesk/。把里面保存服務(wù)器信息的文件通常是RustDesk.toml或類似配置復(fù)制出來作為模板。這里必須提醒一個非常容易翻車的細節(jié)不要整個配置目錄都拷走。config下還有id_ed25519和id_ed25519.pub那是客戶端自己的身份密鑰如果每臺機器都用同一份后果就是所有設(shè)備共享同一個設(shè)備 ID互相搶注冊連接會變得一團亂。另外數(shù)據(jù)庫文件包含地址簿等隱私數(shù)據(jù)也不適合批量分發(fā)。正確的做法是只提取跟服務(wù)器、key 相關(guān)的配置內(nèi)容或者干脆把配置好的內(nèi)容做成一個批處理/Shell 腳本在客戶端首次運行前寫入目標機器的配置目錄。Windows 下大致是這樣一個思路echo off mkdir %APPDATA%\RustDesk\config 2nul echo [options] %APPDATA%\RustDesk\config\RustDesk.toml echo custom-rendezvous-serveryour-server.com %APPDATA%\RustDesk\config\RustDesk.toml echo keyyour-public-key %APPDATA%\RustDesk\config\RustDesk.toml字段名還是那句話以你實際配置生成的真實文件為準不要照抄網(wǎng)上任何一個模板。每個版本的存儲結(jié)構(gòu)都可能調(diào)整最穩(wěn)的方法永遠是先手動配置再復(fù)制真實內(nèi)容。4.3 做法三安裝后腳本注入做法三適合已經(jīng)裝好客戶端、跑過幾次但配置不對的場景。它的本質(zhì)跟做法二差不多只是把寫入配置的時機從首次啟動前挪到安裝之后??梢杂门幚砟_本、PowerShell 腳本或者組策略來推送配置文件。如果你管理了一批已然運行過客戶端的電腦刪配置目錄會影響它們的設(shè)備身份所以我不建議直接刪了重來而是只更新配置文件里服務(wù)器和 key 相關(guān)的條目然后重啟客戶端。這種方式的好處是不用重新編譯壞處是命令行里寫明文 key腳本本身的保管要注意權(quán)限別讓無關(guān)人員看到你的服務(wù)器公鑰和地址。其實公鑰本身不算敏感但配合服務(wù)器地址暴露在公網(wǎng)上容易被別人掃描利用后面講安全時再說。4.4 我的選擇編譯期為主配置兜底三種方式按實際使用場景分開自己主力機、給家人朋友分發(fā)編譯期改默認值一勞永逸。給公司同事批量部署預(yù)置配置腳本推送節(jié)省重編譯成本。臨時幫別人調(diào)一下遠程指導(dǎo)手動填或者腳本修一下配置。我最推薦的組合是編譯期默認值 配置文件雙保險。編譯期保證全新安裝的機器開箱即連配置文件應(yīng)對那些需要差異化覆蓋的單臺機器。5. 完整編譯流程與實測記錄5.1 Linux 下編譯 Linux 客戶端我在一臺 Ubuntu 22.04 機器上完整跑過一次記錄一下流程# 1. 安裝系統(tǒng)依賴 sudo apt update sudo apt install build-essential pkg-config cmake git \ libgtk-3-dev libssl-dev libasound2-dev libavcodec-dev \ libavformat-dev libavutil-dev libswscale-dev \ libx11-dev libxext-dev libxinerama-dev libxcursor-dev \ libxdamage-dev libxfixes-dev libxi-dev libxkbcommon-dev \ libvpx-dev libopus-dev # 2. 安裝 Rust curl --proto https --tlsv1.2 -sSf https://sh.rustup.rs | sh source ~/.cargo/env # 3. 拉源碼并切換到穩(wěn)定版本 git clone https://github.com/rustdesk/rustdesk.git cd rustdesk git checkout v1.3.x # 4. 修改默認服務(wù)器地址和 key按第四章做法一 # 5. 編譯 cargo build --release編譯產(chǎn)物在target/release/rustdesk。首次編譯時間比較長取決于機器性能二十分鐘到一小時都正常建議耐心等不要中途 CtrlC。我看到很多新手在編譯時看到一長串 warning 就以為報錯了其實只要最后沒有error字樣就是成功。在啟動自己編譯的客戶端之前務(wù)必先清理舊配置rm -rf ~/.config/rustdesk然后運行./target/release/rustdesk打開設(shè)置界面就能看到服務(wù)器地址已經(jīng)變成了自己填的那個。5.2 Windows 下編譯 Windows 客戶端Windows 編譯流程我在一臺 Windows 11 機器上跑過。重點是要用 VS 的開發(fā)者命令行否則后面鏈接階段會找不到環(huán)境變量。git clone https://github.com/rustdesk/rustdesk.git cd rustdesk git checkout v1.3.x # 設(shè)置 vcpkg 環(huán)境變量如果還沒設(shè)置 $env:VCPKG_ROOT C:\vcpkg # 編譯 cargo build --release編譯產(chǎn)物在target\release\rustdesk.exe。如果是 Flutter UI 版本可以先執(zhí)行python build.py --flutter --release最終產(chǎn)物在target\release\下。5.3 我踩過的編譯錯誤把幾個典型報錯和處理方式整理出來應(yīng)該能幫大家省不少時間。錯誤現(xiàn)象原因解決辦法link.exe not found或找不到 MSVC 鏈接器沒有使用 VS 開發(fā)者命令行打開 x64 Native Tools Command Prompt 再執(zhí)行 cargovcpkg 安裝依賴超時失敗網(wǎng)絡(luò)原因或依賴較多重試必要時配置鏡像源OpenSSL 頭文件找不到缺少libssl-dev/pkg-configLinux 安裝libssl-devWindows 通過 vcpkg 安裝 opensslFlutter 構(gòu)建報錯或卡住Flutter 版本不一致或依賴未拉取執(zhí)行flutter upgrade flutter pub get磁盤空間不足Rust 編譯緩存很大清理target目錄或用外置盤做編譯還有一個通用建議編譯這類大型 Rust 項目把CARGO_HOME和target目錄放到空間充足的磁盤上SSD 優(yōu)先。機械硬盤編譯 RustDesk 會讓人懷疑人生。5.4 驗證編譯產(chǎn)物確實寫入了默認配置編譯完成后怎么確認默認值真的生效可以先用一個干凈環(huán)境運行客戶端然后直接看設(shè)置界面顯示的是不是你自己的服務(wù)器。更快的辦法是在源碼里搜索替換后的字符是否還在grep -rn your-server.com target/release/ 2/dev/null不過二進制里字符串不一定明文可見最靠譜的還是實機驗證。我自己的測試流程是清空配置目錄、啟動客戶端、觀察日志、開兩臺設(shè)備實際連一次。兩臺設(shè)備建立連接的那一刻整套方案才算真正跑通。6. 上線后的排查手段與安全邊界6.1 key 值未知的完整排查鏈路這個報錯可能是 RustDesk 自建玩家最常見的求助熱點。所謂key 值未知本質(zhì)是客戶端本地保存的 key 和服務(wù)器實際公鑰對不上。排查鏈路按順序走一遍登錄到服務(wù)器進入 hbbs 部署目錄用cat id_ed25519.pub查看當前公鑰。在客戶端設(shè)置界面把 key 更新為剛才看到的完整字符串。復(fù)制時注意開頭結(jié)尾有沒有多出空格、是不是被換行截斷了。如果更新后仍然報錯關(guān)閉客戶端刪除本地配置目錄再重新啟動輸入。如果服務(wù)器有多臺實例、或者曾經(jīng)把舊目錄拷貝過確保客戶端連的確實是生成這份公鑰的那臺機器。我遇到最多的情況是服務(wù)端透過寶塔或者其他面板重啟過目錄被重建密鑰重新生成了客戶端還拿著舊 key 在連接。備份的重要性在這里體現(xiàn)得很充分。6.2 連不上 ID 服務(wù)器時的排查鏈路客戶端如果一直顯示無法連接服務(wù)器不要急著懷疑源碼。按這個順序查檢查端口是否可達nc -z -v your-server.com 21115 nc -z -v your-server.com 21116 nc -z -v your-server.com 21117檢查服務(wù)器防火墻ufw status或firewall-cmd --list-all確認 21115-21119 已放行。檢查云安全組很多云廠商的安全組默認全關(guān)單獨放行端口才有效。查看 hbbs 日志啟動 hbbs 時不要加--quiet日志里會打印客戶端注冊、注冊失敗的詳細信息。有個容易被忽略的坑21116 端口同時需要 TCP 和 UDP 放行。很多網(wǎng)絡(luò)環(huán)境只放行 TCP客戶端能完成一部分握手但后續(xù)的 UDP 通信直接被丟現(xiàn)象就是反復(fù)超時。6.3 中繼服務(wù)器不轉(zhuǎn)發(fā)的幾個原因兩臺設(shè)備無法直連時流量會走 hbbr。中繼不工作現(xiàn)象是對方設(shè)備一直顯示連接中然后失敗。常見原因21117 端口沒放行客戶端與 hbbr 建立不了連接。客戶端填的中繼服務(wù)器地址不對。新版客戶端可以單獨設(shè)置中繼服務(wù)器務(wù)必和 hbbs 的-r參數(shù)保持一致。hbbr 進程沒起來或死循環(huán)了。ps aux | grep hbbr看一眼配合 systemd 的Restartalways解決。如果確認端口和進程都正常用兩臺不同網(wǎng)絡(luò)環(huán)境比如一個在移動網(wǎng)絡(luò)、一個在寬帶的設(shè)備再測一次很多時候是測試環(huán)境里兩臺機器其實可以直連流量根本沒走中繼導(dǎo)致你以為中繼壞了。6.4 安全邊界與隱私保護RustDesk 的 key 機制需要澄清一個概念key 是服務(wù)器身份公鑰不是訪問密碼。拿到服務(wù)器地址和公鑰的人可以嘗試向你的 ID 服務(wù)器注冊自己的設(shè)備所以服務(wù)器暴露在公網(wǎng)上時必須有額外的保護意識。幾個我自己長期在用的安全習(xí)慣id_ed25519私鑰視為最高機密絕不公開、不隨客戶端分發(fā)。如果條件允許在服務(wù)器防火墻層面限制來源 IP。只給自己固定出口 IP 放行 21115-21119能擋掉大量掃描。每臺被控設(shè)備設(shè)置強訪問密碼。這是連接設(shè)備時真正起攔截作用的憑證。定期備份 hbbs 部署目錄。密鑰丟了或變了所有客戶端都要重新配置代價太大。域名和服務(wù)器 IP 盡量不要頻繁變更。客戶端里寫死的地址一旦變更同樣需要重新配置。6.5 順手還能改的客戶端名稱與圖標既然已經(jīng)走到編譯客戶端這一步很多人會順手把軟件名稱、圖標一起改掉讓整個工具看起來更像自家產(chǎn)品。這個需求一般涉及資源文件和界面文案Windows 圖標和版本信息在.rc資源文件里Flutter UI 的文字在flutter/lib/下的源碼里。改起來不難但每次升級版本都要維護一份 patch個人自用的話自己權(quán)衡一下值不值。最后的幾點體會把服務(wù)器地址和 key 編進客戶端這個事真正做起來比想象中簡單難點反而在版本差異的適配和舊配置的清理上。我個人現(xiàn)在已經(jīng)養(yǎng)成了習(xí)慣拿到新版本源碼先 grep 默認服務(wù)器常量的位置改完再編譯同時保留一份配置文件模板用于那些沒法重編譯的環(huán)境。整套方案跑順之后RustDesk 的使用體驗基本可以做到發(fā)給別人就用不用任何解釋。最后再提醒一句最關(guān)鍵的話服務(wù)器端id_ed25519私鑰千萬保管好丟一次所有客戶端的 key 都要跟著重配那種批量改配置的酸爽體驗過一次就再也不想體驗第二次了。