Camino de yuwen-c

關於內網主機連線遇到的小麻煩

#macos #ssh #network #troubleshooting notes

前陣子在工作上遇到一個有點麻煩的事,從我的 Mac 筆電(在公司內網),用 SSH 去連同樣在公司內網的主機 (DGX Spark),在正常連線一段時間後(例如 1-2 小時),就會突然斷線。一開始我想,是不是主機休眠的問題?於是我在主機端本機操作、測試連線,我的筆電和主機間的連線就可以恢復。

試了幾次,我總結出暫時的解決辦法:只要一發生:「筆電 ping 主機 IP,開始 Request timeout 」時,我就去直接操作主機,去 ping 筆電,這時筆電對主機的連線就會瞬間恢復正常,屢試不爽,不過效期只有 1-2 個小時,就要重新來過。

sequenceDiagram
    participant Mac as Mac 筆電
    participant Host as DGX Spark 主機

    Mac--xHost: SSH / ping 失敗
    Note over Host: 到主機本機操作
    Host->>Mac: 反向 ping Mac
    Mac->>Host: 連線恢復

團隊成員用的是 Windows,我是唯一一台 Mac,他們說沒有遇到問題;再加上,公司的路由設定權限也不在我手上,無法得知詳細底層公司內網的路由設定。跟 gpt 來回很多次,只能得出,可能是因為 Windows 和 macOS 在 ARP cache 的行為不同,導致不同的連線結果。

於是我就過了一段這樣的無限輪迴:「啊,又連不上了 ⭢ 把主機插上鍵鼠組、螢幕,ping 我的筆電 ⭢ 連線成功」。但這個方法實在是太麻煩了,跟 gpt 討論後,他提供了一個方法:把主機的 IP/ MAC address 對應關係直接寫進筆電,讓 macOS 不用再靠動態 ARP 查詢。不過要稍微注意的是,有次我為了讓主機下載 LLM 模型的速度加快,改讓主機走有線網路,結果發現:走 Wi-Fi 和走有線網路,主機可能拿到不一樣的 IP,MAC address 也會是不同的,所以也要把這組對應關係加進來,才有辦法連。

flowchart LR
    host["<div class='dgx-gold-metallic'>DGX Spark 主機</div>"]

    subgraph laptop["Mac 筆電"]
        arp["把主機位置寫進筆電<br/>主機 IP + MAC address"]
    end

    laptop -->|直接找到主機,成功連線| host

    style laptop fill:#e8f2ff,stroke:#3b82f6,color:#1e3a8a
    classDef dgx fill:transparent,stroke:transparent,color:#3f2a00
    class host dgx

沒過多久,我又發現另一種更方便的解法,使用主機的 mDNS 名稱來連線。也就是,讓主機透過 mDNS 在區網內廣播自己的 .local 主機名稱,這樣只要是在同個區網的裝置,就可以直接用這個名稱連上主機,徹底解決我的問題!而且我後來才發現,原來 DGX Spark 的說明書封面,就印有這台主機的 .local 名稱,解答近在眼前,哈哈。

flowchart LR
    subgraph lan["同一個區網"]
        host["<div class='dgx-gold-metallic'>DGX Spark 主機</div>"]
        mdns(("mDNS multicast<br/>宣告名稱與 IP"))
        laptop["Mac 筆電"]
        other1["其他裝置"]
        other2["其他裝置"]
    end

    host -.->|發出| mdns
    mdns -.->|同區網可聽到| laptop
    mdns -.-> other1
    mdns -.-> other2
    laptop -->|用 .local 名稱連線| host

    classDef mac fill:#e8f2ff,stroke:#3b82f6,color:#1e3a8a
    classDef dgx fill:transparent,stroke:transparent,color:#3f2a00
    class laptop mac
    class host dgx

後記: 原本以為設定 mDNS 就是這次問題的終點,結果後來主機更新驅動程式版本後,斷線問題也跟著消失了。前面的 workaround 都可以省略,完全是意想不到的粗暴解法 🙃。