瀏覽器,隨時隨地遠(yuǎn)程運維)
說個最近的遭遇人在外面手機上收到服務(wù)器告警磁盤快滿、日志刷屏、進(jìn)程被擠出。我身邊沒電腦手機上的終端客戶端在那種情況下根本用不上。折騰了半天我下決心給自己搭一套能放在瀏覽器里、隨時隨地打開就能連的 Web SSH。最后配合 Termix 把 SSH 會話橋接到了網(wǎng)頁端整個過程踩了不少坑。這篇是完整記錄想做這件事的原理、部署方式、安全加固和排錯經(jīng)驗都在里面。適合跟我一樣經(jīng)常不在電腦前的人也適合正在選型的小團(tuán)隊運維同學(xué)參考。1. 為什么我最后選擇自建 Web SSH而不是硬湊合1.1 傳統(tǒng) SSH 在移動場景下的四個尷尬我不是說命令行 SSH 不好它在正經(jīng)辦公環(huán)境里無可替代。但隨時隨地管服務(wù)器這六個字直接把傳統(tǒng)方式的臉打腫了第一客戶端依賴。公司電腦、客戶現(xiàn)場的機器、朋友借的筆記本不可能每臺都裝好 SSH 客戶端。遇到 Windows 默認(rèn)環(huán)境更強命令端都沒法直接用。手機端的 SSH 應(yīng)用倒是不少可屏幕小、鍵盤輸入難受、復(fù)制粘貼還經(jīng)常亂套。第二網(wǎng)絡(luò)環(huán)境限制。很多訪客網(wǎng)絡(luò)只放行 80 和 443 端口SSH 默認(rèn)的 22 端口直接被掐死。有的公司出口代理還要審計流量非標(biāo)準(zhǔn)端口很容易觸發(fā)告警。第三多臺機器管理碎片化。我得同時維護(hù)好幾臺服務(wù)器IP、端口、密鑰、用戶名光這些信息就夠記一堆。沒有一個統(tǒng)一的入口每次都是臨時去翻記錄效率極低。第四會話穩(wěn)定性。網(wǎng)絡(luò)一波動SSH 會話斷掉正在跑的任務(wù)可能跟著遭殃。雖然進(jìn)程層面有 tmux、screen 頂著但你在移動端重新連回去的體驗依然不痛快。1.2 Web SSH 的適用人群與場景邊界這套方案不是要取代桌面 SSH它解決的是輕量、臨時、跨設(shè)備的問題。最適合三類人個人開發(fā)者 / 獨立站長服務(wù)器不多但經(jīng)常外出需要快速看一眼服務(wù)狀態(tài)、重啟容器、看日志瀏覽器就能解決。小團(tuán)隊運維成員需要共用一個管理入口但不想給每個人都開服務(wù)器系統(tǒng)賬號又想留操作記錄?;旌檄h(huán)境使用者公司內(nèi)網(wǎng)有一批機器家里有一批機器想要一個統(tǒng)一的管理頁面。不適合誰如果你的運維流程已經(jīng)重度依賴堡壘機、審計系統(tǒng)或者有嚴(yán)格的等保需求那就沒必要自建直接走企業(yè)級方案。Web SSH 適合夠用就好的人。1.3 別人家的方案 vs 自己搭市面上現(xiàn)成的方案并不少云廠商控制臺里基本都有網(wǎng)頁終端也有在線 SSH 工具網(wǎng)站。但我個人不愿意接受兩個限制一是賬號系在特定平臺上換一家云廠商、換一臺非公有云機器就用不了二是中間鏈路自己不可控在線工具相當(dāng)于把服務(wù)器會話交給了第三方安全性我說服不了自己。Termix 這種自建方案最大的價值就是自主權(quán)會話數(shù)據(jù)跑在自己控制的鏈路上認(rèn)證規(guī)則自己定日志自己留。雖然搭建花費一些時間但長期用下來很值。2. Termix 的工作機制SSH 是怎么被塞進(jìn)瀏覽器的2.1 整體結(jié)構(gòu)三個角色各司其職在真正動手之前我建議先花十分鐘理解這套東西的運行邏輯。用一句話概括瀏覽器負(fù)責(zé)顯示終端界面服務(wù)端負(fù)責(zé)代替你完成 SSH 協(xié)議通信兩者之間用實時通道連接起來。拆開看分成三層前端層瀏覽器里跑的終端模擬組件負(fù)責(zé)把字符流渲染成一個可交互的終端窗口同時把鍵盤輸入捕獲并發(fā)送出去。橋接層也就是 Termix 服務(wù)端本身接收瀏覽器的實時連接請求解析會話指令然后在服務(wù)器本地創(chuàng)建一個真正可用的 SSH 會話。目標(biāo)層你要管理的目標(biāo)服務(wù)器Termix 服務(wù)端以普通 SSH 客戶端的方式連接它。整個過程里瀏覽器并沒有直接跟目標(biāo)服務(wù)器建立 SSH 連接它只跟 Termix 服務(wù)通信。2.2 一次會話的完整數(shù)據(jù)流我畫一下我在腦子里理的流程對這個部分新手容易暈?zāi)阍跒g覽器里打開 Termix 頁面先做登錄認(rèn)證服務(wù)端發(fā)給你一個有效的會話令牌。你在頁面里輸入目標(biāo)服務(wù)器的地址、端口、用戶名或者選擇一個預(yù)配置的主機。Termix 服務(wù)端收到請求后校驗權(quán)限然后替你執(zhí)行一次 SSH 連接。連接建立后目標(biāo)服務(wù)器的 stdout 輸出被編碼成數(shù)據(jù)幀通過實時通道推給瀏覽器。瀏覽器里的終端模擬組件把數(shù)據(jù)幀還原成文字和顏色顯示在頁面上。你在頁面敲下的每個按鍵也被封裝成數(shù)據(jù)幀回傳到服務(wù)端服務(wù)端把它寫入 SSH 會話的標(biāo)準(zhǔn)輸入。實際用下來感覺就和本地終端幾乎一樣。2.3 為什么要用 WebSocket 而不是普通 HTTP 請求這里解釋一個關(guān)鍵選型點。SSH 會話是雙向、持續(xù)、實時的通信每個按鍵都要很快響應(yīng)服務(wù)端的輸出也要連續(xù)推給瀏覽器。如果用普通 HTTP 輪詢你每敲一個字符就要發(fā)一次完整請求服務(wù)端有輸出還要另外拉一次延遲和資源消耗都受不了。Termix 的橋接通道用的是 WebSocket。它的核心優(yōu)勢是建立一次連接之后雙向推送數(shù)據(jù)不需要反復(fù)握手也不存在短輪詢的延遲問題。體驗上接近原生 SSH能做到輸入即時回顯、輸出持續(xù)滾動。在反向代理層處理的關(guān)鍵就是把這個 WebSocket 升級請求正確放行后面第五節(jié)我會詳細(xì)講踩坑過程。2.4 會話管理與終端類型協(xié)商還有一個容易被忽略的細(xì)節(jié)是終端類型協(xié)商。傳統(tǒng) SSH 會自動協(xié)商一個終端類型比如xterm-256color影響顏色顯示和快捷鍵行為。Web SSH 同樣要做這個事情Termix 在建立會話時會帶上預(yù)設(shè)的終端類型保持顏色主題、光標(biāo)定位、快捷鍵組合能正常工作。如果協(xié)商不對最常見的癥狀是top、htop的界面刷不出來或者 vim 里的方向鍵變成字符A、B、C、D。3. 從零搭起Termix 部署全流程記錄3.1 部署前的準(zhǔn)備工作先說硬件和環(huán)境需求。我用的是一臺 1 核 1G 的小機器CentOS 7 系統(tǒng)內(nèi)存小了點但只跑 Termix 完全夠。如果你要同時承載多人使用建議 2 核 2G 起步。需要一個域名用來配置 HTTPS不然瀏覽器里的部分高級能力比如剪貼板讀取會被限制。域名解析到這臺機器上并確保 80、443 端口在防火墻里放行。注意放行 443 端口之后如果這臺服務(wù)器本身就是你的目標(biāo)機器之一請確認(rèn)你沒有把 22 端口暴露到公網(wǎng)。Termix 服務(wù)本身應(yīng)當(dāng)通過系統(tǒng)防火墻只允許本地回環(huán)訪問真正對外暴露的只有 443。3.2 安裝與初始化配置Termix 的安裝包跟一般軟件不大一樣不同版本的目錄結(jié)構(gòu)和命令會存在差異。下面這套步驟是我基于常見實踐整理的通用流程你拿到具體版本后要對照官方說明調(diào)整目錄和配置文件路徑。# 1. 創(chuàng)建獨立運行用戶避免以 root 身份常駐服務(wù) useradd -m -s /bin/bash termix # 2. 切換到該用戶并下載安裝包解壓到指定目錄 su - termix mkdir -p ~/termix tar -xzf termix-release.tar.gz -C ~/termix cd ~/termix # 3. 生成初始配置模板 ./termix init初始化完成后目錄下會有一個termix.yaml配置模板。我個人的習(xí)慣是把配置項按三塊分監(jiān)聽地址、認(rèn)證策略、會話上限。最開始什么都不用想復(fù)雜只改監(jiān)聽地址server: listen: 127.0.0.1:8080 # 只監(jiān)聽本地回環(huán) session_timeout: 1800 # 會話空閑超時單位秒 auth: mode: password # 先用密碼登錄后邊再加 TOTP session_ttl: 7200 # 登錄態(tài)過期時間用./termix start啟動服務(wù)telnet 127.0.0.1 8080能通就說明基礎(chǔ)服務(wù)起來了。這時瀏覽器訪問需要先想辦法打通外網(wǎng)訪問路徑推薦的做法是交給反向代理來處理。3.3 初始化配置的可操作細(xì)節(jié)我第一次搭的時候在配置上犯過一個低級錯誤把監(jiān)聽地址配成了服務(wù)器公網(wǎng) IP。這樣 Termix 服務(wù)本身直接暴露在公網(wǎng)省掉反向代理的部署看起來更簡單但后續(xù)想加 HTTPS、做訪問控制就非常痛苦而且 8080 端口很容易被掃描工具盯上。正確做法是只監(jiān)聽 127.0.0.1讓外部流量經(jīng)過反向代理轉(zhuǎn)發(fā)進(jìn)來。這樣 Termix 永遠(yuǎn)只面對本機的 Web 服務(wù)器公網(wǎng)攻擊者看不到它。3.4 反向代理與 HTTPS 配置我用的主機的 Web 服務(wù)器是常見開源方案給 Termix 加一段反向代理配置。這里有個關(guān)鍵要求必須放行 WebSocket 升級請求。以我的配置片段為例server { listen 443 ssl; server_name term.example.com; ssl_certificate /etc/ssl/term/term.example.com.pem; ssl_certificate_key /etc/ssl/term/term.example.com.key; location /termix/ { proxy_pass http://127.0.0.1:8080; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection upgrade; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; } }如果你的 Web 服務(wù)器可以自動申請和續(xù)期 HTTPS 證書那更容易直接把域名指過來配一個反向代理就好。注意http與https的自動跳轉(zhuǎn)、請求體大小限制要放開SSH 會話傳輸?shù)牧魇綌?shù)據(jù)并不大不會被 Nginx 限制困擾但 WebSocket 幀的讀取超時要給足。默認(rèn)超時經(jīng)常是 60 秒終端長時間沒有輸出時會被主動斷開建議把讀取超時調(diào)大例如 300 秒以上。配好后瀏覽器訪問https://term.example.com/termix/看到登錄頁說明整套鏈路已經(jīng)通了。4. 公網(wǎng)暴露的 Web SSH這些安全加固必須做4.1 我只跑了兩天就被掃描了這套服務(wù)上線后我特意觀察了幾天日志。第一天就有來自不同來源的掃描請求試圖猜登錄口令。這給我提了一個醒Web SSH 是價值非常高的攻擊目標(biāo)因為它一旦被攻破等于把服務(wù)器權(quán)限交出去了。所以安全這塊不是可選項是必選項。攻擊面主要有三塊登錄前暴力破解、弱口令嘗試、未知路徑探測。會話中令牌泄露、被中間人截獲、多用戶會話隔離不足。系統(tǒng)層Termix 服務(wù)本身上線后如果某個未知接口被調(diào)用了安全隱患會放大。4.2 登錄認(rèn)證升級從單層密碼到兩層保護(hù)密碼登錄在公網(wǎng)上撐不了多久。我的建議是至少做到兩層第一層密碼驗證第二層動態(tài)驗證碼。Termix 支持在登錄認(rèn)證基礎(chǔ)上掛載動態(tài)口令驗證我用的是常見的開源動態(tài)口令庫生成方式是基于時間的一次性密碼。手機端裝一個標(biāo)準(zhǔn)認(rèn)證類應(yīng)用掃描 Termix 生成的二維碼以后每次登錄都要輸入 6 位動態(tài)碼。這樣做的好處是即使密碼因為某種原因泄露沒有動態(tài)碼也進(jìn)不來。我還順手做了失敗次數(shù)限制同一 IP 連續(xù)失敗 5 次就臨時封禁 15 分鐘。這個可以在 Web 服務(wù)器層實現(xiàn)也可以在 Termix 內(nèi)啟用看各自版本支持情況。4.3 IP 白名單、訪問路徑與來源控制如果你的使用場景相對固定可以在 Web 服務(wù)器層加 IP 限制。只允許公司出口 IP、家里寬帶 IP 訪問/termix/路徑其它來源一律返回 403。這個策略簡單有效能過濾掉 80% 的掃描流量。如果活動范圍確實不固定至少可以設(shè)置賬號級登錄地點提醒登錄成功之后把本次來源 IP 顯示在頁面上發(fā)現(xiàn)不對立刻手動失效全部會話。4.4 會話隔離與超時策略多人共用這套系統(tǒng)時每個用戶的 SSH 會話必須相互隔離。Termix 的每個連接在服務(wù)端有獨立的會話映射互不干擾。我配置了空閑超時自動斷開默認(rèn)為 30 分鐘如果 30 分鐘內(nèi)沒有鍵盤輸入會話自動終止避免人走開以后會話被接管。注意這里的會話超時和系統(tǒng)層的 idle session 不是一回事。系統(tǒng)層的會話可能還會因為服務(wù)端線路問題懸掛著Web SSH 的會話超時只是指瀏覽器與 Termix 之間的連接。真正要杜絕懸掛連接建議同時配合使用ClientAliveInterval這類 SSH 服務(wù)端參數(shù)。4.5 審計日志是最容易被忽視的一環(huán)我建議從第一天就開啟操作日志。這個日志至少需要記錄四個要素誰、在什么時間、連了哪臺機器、執(zhí)行了什么操作。如果只記錄登錄成功但沒記錄具體命令出問題的時候你連攻擊者做了什么都不知道。Termix 大部分版本可以配置將日志輸出成文本落盤。我的做法是直接寫到日志目錄下然后定期歸檔。終端輸出和鍵盤輸入如果都記錄日志文件會增長得很快但如果連續(xù)記錄兩個月對磁盤占用完全可接受換來的排查能力非常值得。風(fēng)險點常見攻擊方式我采用的加固措施登錄口令暴力破解、撞庫密碼 動態(tài)驗證碼失敗次數(shù)限制訪問來源全網(wǎng)掃描Web 服務(wù)器層 IP 白名單非白名單 403 拒絕會話劫持令牌泄露、中間人強制 HTTPS會話空閑自動過期越權(quán)操作賬號共用、權(quán)限過大獨立系統(tǒng)賬號映射按需分配主機權(quán)限事后溯源證據(jù)缺失記錄登錄時間、來源、命令輸出、目標(biāo)主機5. 實測踩坑記錄從能用到好用的關(guān)鍵修復(fù)5.1 復(fù)制粘貼失靈和方向鍵亂碼第一次跑通之后我用 vim 編輯文件發(fā)現(xiàn)方向鍵每次都會插入字符A、B、C、D復(fù)制粘貼也完全不受控。一開始以為是 Termix 的問題排查之后確認(rèn)是終端類型協(xié)商的問題。因為某些終端組件默認(rèn)以極小型的終端類型連接老舊的程序不支持功能鍵轉(zhuǎn)義序列。解決方式有兩種把終端類型固定為xterm-256color在 Termix 的會話配置里指定終端類型參數(shù)。檢查瀏覽器頁面是否啟用了正確的終端模擬組件的鍵位映射有些組件默認(rèn)不開啟應(yīng)用光標(biāo)模式。真正把終端類型改成xterm-256color之后vim 的體驗立刻正常了。復(fù)制粘貼要注意頁面上提供的安全上下文權(quán)限首次使用會要授權(quán)剪貼板讀取允許一次后就不再彈。5.2 WebSocket 被反向代理掐斷的完整排查鏈路這個問題很典型值得寫出來。上線前一天我測試一切正常第二天再打開頁面輸入密碼后能建立會話但終端沒有任何輸出幾秒后提示連接已斷開。看 Termix 服務(wù)端日志發(fā)現(xiàn)瀏覽器發(fā)起 WebSocket 升級請求服務(wù)端已經(jīng)接受了但反向代理層沒有正確轉(zhuǎn)發(fā)。排查過程是這樣的先用瀏覽器的開發(fā)者工具抓請求確認(rèn) WebSocket 握手請求返回了 200 而不是 101。200 說明反向代理沒有把它當(dāng)一個升級請求而是當(dāng)成普通 GET 請求處理了。檢查反向代理配置發(fā)現(xiàn)我第一版配置里沒有設(shè)置Upgrade和Connection請求頭。最初補上了Connection upgrade的配置接上發(fā)現(xiàn)還是不穩(wěn)因為代理的讀取超時太短長連接閑置一會兒就被切斷。最后調(diào)整代理讀取超時參數(shù)把超時加大問題徹底消失。這里最容易被忽略的是很多反向代理默認(rèn)不保留長連接升級請求一旦走默認(rèn)處理WebSocket 就廢了。這種問題不是一眼能看出來的要認(rèn)真翻一下層層的日志。5.3 多人同時登錄同一主機的會話串?dāng)_有同事在同一時間登錄同一臺目標(biāo)服務(wù)器出現(xiàn)了一種奇怪現(xiàn)象兩邊敲的命令偶爾會跑到對方會話里。排查后發(fā)現(xiàn)問題不在 Termix 本身而是我們兩個人用的系統(tǒng)賬號是同一個。當(dāng)兩個 Web SSH 會話映射到同一個系統(tǒng)用戶時服務(wù)端交互式會話會沖突。解決辦法是給每個人分配獨立的系統(tǒng)賬號并且 Termix 配置里把賬號與主機訪問權(quán)分開控制。如果只是臨時用一下至少要讓每個人手動指定--identity參數(shù)連接不同會話避免復(fù)用同一個默認(rèn)賬號。5.4 手機端體驗優(yōu)化的一些細(xì)節(jié)瀏覽器能開網(wǎng)頁就能連服務(wù)器但手機端有幾個地方值得打磨把頁面添加到主屏幕全屏顯示體驗接近原生應(yīng)用。開啟頁面自帶的字號調(diào)整選項手機端字號適中才不費眼。把常用主機預(yù)存在 Termix 的配置里連接時只需要點一下選擇不用敲 IP。開小鍵盤出來會很占屏盡量用終端操作少開輸入法。我實際在手機上用它修過一次配置錯誤人在地鐵上服務(wù)告警我打開手機瀏覽器點兩下進(jìn)了頁面改掉了配置服務(wù)恢復(fù)。以前這種場景基本是等回電腦再說。一些我最后想分享的使用習(xí)慣Termix 這套體系用了幾個月后我總結(jié)了幾條自己的習(xí)慣?,F(xiàn)在每周都會檢查一次登錄日志看看有沒有陌生 IP 的嘗試記錄。動態(tài)驗證碼讓密碼泄露的風(fēng)險變低但并不能完全代替定期更換密碼。所有目標(biāo)服務(wù)器的密鑰盡量都采用密鑰登錄并且 Termix 服務(wù)端保存密鑰文件的位置要設(shè)置嚴(yán)格權(quán)限其它用戶不可讀。如果你準(zhǔn)備給團(tuán)隊使用建議最開始就約定賬號命名規(guī)范和目標(biāo)主機分組規(guī)則不然人一多就會亂。如果你已經(jīng)有一臺可以訪問公網(wǎng)的服務(wù)器搭這套東西一兩個小時就能搞定真正花時間的其實是被攻擊之后怎么應(yīng)對。能把這套東西認(rèn)真跑起來的人運維效率會提升很大。希望你也能從這套方案里受益。