如何讓 Muse 突破沙箱網路封鎖?

Muse 的沙箱不讓任何連線進來,我用家裡的代理和一條讓 Muse 自己撥出去的中繼,讓它在我電腦關機時也能盯 LinkedIn 和 Indeed,也記下沒拆乾淨的 429 變因。

更新日 12 min14 回表示記事の言語
著者John Hsieh

省流

Muse 的沙箱不讓任何連線從外面進來,往外的連線也都要經過沙箱。所以別想著連進去,讓 Muse 從裡面撥出來:想換出口,就讓它串到你放在公開網路上的代理;想看它的畫面,就讓它撥到你自己的中繼站。

我想讓 Muse 幫我盯 LinkedIn:有人私訊就提醒我、順便查這家公司和獵頭的風評、職缺照我的標準評分,而且我電腦關機也要能跑。

Muse 是 Meta 的 AI 助理,它有一台自己的雲端電腦,是一台 VM (租在雲上的虛擬電腦),可以開瀏覽器、跑程式、設排程。這台電腦的網路被包在一個沙箱裡,什麼能進、什麼能出都有規則。(Muse 能做什麼我之前寫過一篇〈Meta Muse 到底有啥用?〉。)

聽起來很完美。實際跑起來是這樣:Muse 開 LinkedIn 時好時壞 (大概是因為沙箱的出口 IP 很多人共用,LinkedIn 對這種 IP 本來就比較兇),好不容易讓它用上我的登入狀態,第一頁就噴 HTTP 429 (Too Many Requests,網站嫌你連太兇)。

這篇是我花了一整天,從這裡一路踩坑到跑通的紀錄。

標題的「突破」先講清楚:沙箱的規則我沒破。我做的是先搞懂它放行什麼,再在它允許的範圍裡找一條路出去。

另外,LinkedIn 和 Indeed 對自動化工具各有規定,能不能這樣用請你自己看條款判斷。我的用法是收件匣每 15 分鐘讀一次、職缺一天掃一次,只讀我自己的帳號,每一則要送出的訊息都要我確認過才會送。

Muse 的沙箱到底擋了什麼?

先講結論,因為我一開始就是不知道這件事,才繞了一大圈。

下面是我跟 Muse 一起實測歸納出來的,不是官方文件。

往外連有兩條路:

  • 程式有設代理:連線交給沙箱代理 (代理就是幫你轉送連線的中間人,網站看到的是代理的 IP)。程式用 CONNECT 跟代理說「幫我接通某某網址」,接通之後沙箱就原封不動地轉送、不拆開 (裡面如果是 HTTPS,內容本身是加密的)。port (同一台主機上用來區分不同服務的號碼,網頁通常是 443) 不是每個都放:22 逾時,我們實際用到的幾個 port,包含 443 和一個非標準的,都通。完整的放行清單我們沒測。Muse 的瀏覽器走的就是這一條。
  • 程式沒設代理、直接連:沙箱會把連線攔下來拆開,再用它自己簽的憑證重新包起來。憑證是網站用來證明「你連到的真的是我」的身分證,被換掉之後,程式要另外設定信任沙箱的 CA (簽發憑證的單位),不然會報錯。

剩下的全部擋:

  • 連私人 IP (10.x、192.168.x 這種只在區網裡有效、外面找不到的位址) 一律擋,往外連、從外面連進來都一樣。
  • 從外面連進 VM:沒有任何路。

還有一個跟網路無關、但後面一直咬我的:VM 會不定期重啟,跑著的程式全部死光,只有 home 目錄的檔案會留著。

Muse 的沙箱到底放行了什麼 · 在 Miro 開啟

整理成一句話:只有「Muse 主動往外、經過沙箱、連到公開位址」過得去。

第一招:VPN 接回家

其實在這之前,我就讓 Muse 用瀏覽器直接讀過 LinkedIn。那時它願意把瀏覽器畫面開給我登入,登入本身沒問題,也讀得到東西。但連續跑幾次就不穩,不是掉登入,就是跳驗證,拿來每 15 分鐘掃一次訊息、每天掃職缺撐不住。所以這次我想改用 LinkedIn MCP (MCP 是讓 AI 直接呼叫外部工具的介面,LinkedIn MCP 就是讓 Muse 讀我個人檔案、收件匣的那個工具)。

問題是 MCP 登入時會自己開一個瀏覽器視窗,這個畫面 Muse 從來沒開給我過。要在那個視窗裡登入 LinkedIn,我得自己想辦法看到它的畫面。

為什麼不讓 Muse 自己打帳密? 一來 LinkedIn 登入常常跳驗證碼和二階段驗證,總要有人在畫面前面處理;二來我不想把密碼交給它。

我家路由器本來就有架 VPN,直覺就是讓 Muse 連上來,它就等於在我家了吧?

WireGuard 一開始就排除了:它走 UDP,沙箱代理只轉 TCP (UDP 和 TCP 是兩種傳資料的方式,網頁走的是 TCP)。我在路由器上另外開一個 OpenVPN 的 TCP 版,讓它經過沙箱代理連回家,這次真的連上了。

然後呢? 沒用。

  • Muse 在 VM 裡開了 noVNC (把一台電腦的畫面變成網頁,用瀏覽器就能看、能點),給我一個 VPN 裡的網址。打不開。從路由器 ping Muse 有回應,但真的去連 noVNC,對面一個字都不回。隧道裡跑的東西沙箱代理看不到,所以我猜擋下這條連線的是 VM 自己網路層的規則:ping 用的那種封包放行,從外面進來的連線不放。確切機制我沒查。
  • 順便發現出口 IP 也沒變。VPN 改的是路由,決定封包從哪張網卡出去;但 Muse 的瀏覽器設定裡寫的是「連線交給沙箱代理」,那是應用程式自己指定的下一站,路由表管不到。所以它上網還是從沙箱出去。

Cloudflare 的 cloudflared 開臨時通道也試過,失敗。它不吃 HTTP 代理設定,換了三種設定都報一樣的錯:tls: first record does not look like a TLS handshake,意思是它等著跟 Cloudflare 做加密握手,收到的卻是一段 HTTP 回應。

看畫面這條路暫時走不通,我退而求其次:把我電腦上 Chrome 的 LinkedIn cookie (網站用來記住你已經登入的小檔案) 匯出來,搬進 Muse 的瀏覽器。

結果第一頁就 429。😱

第二招:在家裡架一個代理

第一個懷疑當然是 IP。沙箱的出口 IP 大家共用,被 LinkedIn 盯上很合理。那就讓 Muse 從我家出去。

VPN 改路由沒用,代理不一樣。代理是應用程式自己指定的下一站,既然 Muse 的瀏覽器本來就在用沙箱代理,那就在它後面再串一個我家的代理。

我在路由器上裝了 tinyproxy (一個很小的代理軟體),開一個對外的 port,設了三道限制:

  1. 要帳號密碼才能用。
  2. 網域白名單:只放行 LinkedIn、Indeed (linkedin.com、licdn.com 這些),後來為了 Indeed 的 Google 登入又加了整個 Google。白名單以外的網站和我家內網一律擋。這是在幫損害設上限,帳密就算外流,也只能拿我家的 IP 去連這幾個網站。
  3. 只允許 CONNECT 到目的地的 443 port,也就是只能開 HTTPS 的通道。

串法是這樣:Muse 在 VM 裡跑一個小小的本機轉送程式,瀏覽器的代理就設成它。它先請沙箱代理 CONNECT 到我家的代理,再透過這條通道請我家的代理 CONNECT 到 LinkedIn。瀏覽器跟 LinkedIn 之間的 TLS (網址前面那個鎖頭,負責加密和驗證網站身分) 在最裡面,從頭到尾沒被拆過。

Muse 的瀏覽器 → VM 裡的本機轉送 → 沙箱代理 → proxy.example.com(我家,要帳密)→ www.linkedin.com

有一件事要先講:我家代理用的是最基本的帳密驗證,帳密本身沒有加密。從 VM 到我家這整段,連沙箱自己都看得到這組帳密。所以它是專用的、哪裡都沒有重複用,真正擋損害的是白名單。把整個 Google 加進去,等於把上限放寬了一些,換來 Indeed 能用 Google 登入。這個取捨我接受。

這次出口終於是我家的 IP。我還讓 Muse 開一個檢查連線特徵的網站確認:看到的憑證是正常的公開 CA 簽的,連線特徵也是真的 Chrome。沙箱確實沒拆這一條,跟上面「有設代理就不拆」對得起來。

結果 LinkedIn 還是 429。😭

我真的卡成狗。

光換 IP 救不了 429

這段是整天最燒腦的地方。能查的我們都查了:

  • IP 有沒有被整個擋:用同一條代理、同一個出口,不帶 cookie 直接打 /feed/,拿到的是正常的轉址,把我導去登入頁,不是 429。這只證明這個 IP 沒被 LinkedIn 整個擋掉。我自己電腦上的 Chrome 開 feed 也正常,帳號沒被限制。
  • 請求量:我家代理的 log 只看得到每條 CONNECT 連去哪個網域 (HTTPS 裡面的內容它看不到)。Muse 那次只開了兩條連到 www.linkedin.com 的通道,連 static.licdn.com (放圖片和程式碼的地方) 都沒去,第一個 HTML 就被擋了。量根本不大。
  • 瀏覽器身分:cookie 是從我的 Windows Chrome 搬來的,Muse 跑的是 Linux 的 Chromium。我們讓它對外報的版本、平台跟實際對上,也確認連線特徵是真的 Chrome。對齊完,還是 429。

查到這裡,最可疑的變成 cookie 本身:它是在我的電腦上登入產生的,突然出現在另一台、另一個作業系統的瀏覽器上。LinkedIn 實際怎麼判斷我不知道,但我決定不搬了,回頭走最一開始那條路:在 Muse 自己的瀏覽器裡登入。

讓 Muse 從裡面撥出來

要在 Muse 的瀏覽器裡登入,我得看得到它的畫面。MCP 的登入視窗 Muse 不給我,第一招也已經試過:從外面連進去,沒有路。

那就反過來。我在自己的一台雲端主機上開一個中繼站 (一台我自己管、放在公開網路上的伺服器,負責在 Muse 和我中間轉接),讓 Muse 從裡面撥出來接上它:

  • Muse 在 VM 裡跑瀏覽器、虛擬螢幕和 noVNC。
  • Muse 用 chisel 從裡面連到我的中繼站,把 noVNC 反向轉過去。chisel 是一個把連線包在一般網頁連線 (WebSocket) 裡送出去的小工具,可以設 HTTP 代理,所以它走的是沙箱代理那條路。中繼站開了 443 和另一個非標準 port 兩個入口,都通。
  • 我用手機打開中繼站的網頁 (網頁前面一層密碼,noVNC 自己再一層),看到的就是 Muse 的瀏覽器,親自登入、處理驗證碼。

為什麼不用 SSH 反向轉發? 沙箱代理連 SSH 的 22 port 直接逾時。把 SSH 改開在 443 也許行,但我沒試:我的主機 443 已經跑著網頁伺服器,chisel 走的是 HTTP,可以直接掛在那個網頁伺服器後面,不用另外開 port。

最後是怎麼接起來的 · 在 Miro 開啟

GitHub 不需要我家的 IP,所以沒有走我家的出口,直接經沙箱出去。

登入用的是 LinkedIn MCP 自己的 --login,這次它開的視窗終於透過中繼站出現在我的手機上。登入完,讀個人檔案、讀收件匣,全部正常。沒有 429。

前面對齊版本、檢查連線特徵那一整個下午......最後一個都沒用上。

不過要老實講,這個結果證明不了「429 跟 IP 無關」。成功的那一次同時換了三件事:出口是我家、登入是在 Muse 的瀏覽器裡、而且是用 MCP 自己的 --login。「沙箱的 IP+在 Muse 的瀏覽器裡自己登入」我之前試過:登入沒問題,也讀得到東西,至少一開始不會 429。只是那次是讓 Muse 直接用瀏覽器讀,連續跑就掉登入、跳驗證。真正沒試過的是「沙箱的 IP+MCP 的 --login」:MCP 的登入畫面 Muse 從來不給我,等我透過中繼站看得到畫面時,出口已經換成我家了。所以變因還是沒拆乾淨。我能講的只有:光換 IP 救不了 429,在要用登入狀態的那個環境裡、用那個工具自己登入,就好了。

那為什麼最後還留著我家的出口? 因為「我家出口+在 Muse 裡用 --login 登入」是唯一驗證過能穩定跑的組合;沙箱的 IP 那套,前面已經看過連續跑會掉登入、跳驗證。我不想為了少一個代理再去賭。

踩過的坑

過程中和能跑之後還有一堆小坑,每一個都卡過我:

  1. 在 Muse 的瀏覽器登入了,MCP 還是說沒有登入狀態。中繼站剛通的時候,我是在 Muse 另外開的 Chromium 裡登入的,MCP 不認。查了才知道,這個 MCP 啟動時看的不是瀏覽器,而是一個紀錄檔 (source-state.json),正常是 --login 成功後寫下的。我們手上那份,是當初 Muse 把搬來的 cookie 轉成 MCP 格式時,匯入工具順手建的,所以後來清 cookie 時被當成同一批一起刪了。它說沒登入其實沒錯。改成直接跑 --login、從中繼站再登一次才好。(這次卡的是紀錄檔,不是 429。)
  2. VM 重啟,所有東西一起掛。--login 登到一半 VM 重啟,瀏覽器、noVNC、通道全沒了,中繼站網址直接打不開 (502)。操蛋的是代理密碼原本只放在執行中的程式裡,重啟後 Muse 也不知道密碼了。後來讓它把代理和中繼站的帳密存成只有它自己能讀的設定檔,排程開跑前先檢查虛擬螢幕、代理、Chrome 在不在,不在就重開。
  3. Indeed 用 Google 登入,Google 會跳到國家網域。一開始 accounts.google.com 被我家代理的白名單擋下來,放行後換 accounts.google.com.sg 被擋。最後我乾脆讓家裡代理長期放行整個 Google (就是上面說的取捨)。
  4. Indeed 有 Cloudflare 人機驗證。登入成功,開首頁讀「推薦給你的職缺」時又被要求驗證。我從中繼站點了一次「Verify you are human」。之後排程遇到驗證就停手通知我,不重試。
  5. Indeed 的官方 MCP 用不了。它要走 OAuth 授權 (就是「用某某帳號授權給這個 app」那套流程):我按同意之後,Indeed 會透過轉址把一組一次性的授權碼 (code) 送到 localhost,也就是「瀏覽器所在的那台電腦自己」,Muse 再拿這組 code 去換正式的通行證 (token)。問題是按同意的瀏覽器在我自己的裝置上,不在 VM 上,code 會跑到我自己的裝置,Muse 拿不到,也就換不到 token。理論上可以透過中繼站在 Muse 的瀏覽器裡按同意,或是把轉址後的整條網址手動貼回給 Muse。但它自動註冊出來的 client (DCR) 只拿得到 jobs.search 這一個權限,官方 API 也沒有「推薦給你的職缺」,做完也拿不到我要的東西,就放棄了。
  6. GitHub 連接器每次讀檔都跳授權卡。我的職缺評分標準放在 GitHub 上的 private repo,而且我很常改。Muse 原本把評分規則抄一份寫死在排程裡,三支排程抄的版本還不一樣。改成給它一組只能讀那一個 repo 的權限金鑰,排程每次開始先抓最新版,我 push 完下一輪就生效,也不用點任何授權。
Muse 回報 Indeed 官方 MCP 卡住的原因:redirect 用 localhost 時,按同意的瀏覽器不在沙箱 VM 上,授權碼回不到 Muse 這裡 上面第 5 點,這是 Muse 回報給我的話。裡面的「我這邊」指的是 Muse 自己;PKCE verifier 是拿 code 換 token 那一步要對上的一次性密碼。

最後跑起來的樣子

職缺評分照的是我在 LazyCV 裡定的標準,🟢 綠燈是最高等級。

現在 Muse 每 15 分鐘讀一次 LinkedIn 收件匣和好友邀請。訊息裡有職缺,它會查這家公司和獵頭的風評、照標準評分,再附上建議的回覆;資訊不夠就問我缺什麼。要回覆一定等我說「送出」,它不會自己回,也不會自己接受邀請。

另外每天掃一次 LinkedIn 的職缺、讀一次 Indeed 依我的 profile 推薦的職缺,去重、評分,只有綠燈才通知我。每次評分前,它都會先從 GitHub 抓最新的標準。這些我電腦關著也照跑。

沙箱網路的心智模型

回頭看,整天其實都在撞同一件事。

經過沙箱代理 CONNECT 到公開位址,port 也有放行的話,連得到,內容也不會被拆。沒設代理直接連,也連得到,但會被拆開重簽,程式得信任沙箱的 CA。私人 IP、22 這種沒放的 port、從外面連進 VM,全部到不了。UDP 我也沒找到出得去的路。

所以每次我想「從外面碰到 Muse」,最後能跑的都是反過來:在公開網路上放一個服務,讓 Muse 從裡面撥出去接它。家裡的代理是這樣,中繼站也是。VM 又隨時會重啟,帳密存檔、排程開跑前先檢查服務在不在,這兩件事我是被重啟搞過一次才補上的。

如果你也要在 Muse 上接自己的服務,第一步先讓它幫你測:在公開網路上開一個 HTTPS 服務,請 Muse 分別用有代理、沒代理去連,再換幾個 port 試試,哪條路通、哪條會被拆,幾分鐘就看得出來。

コメント(0)

まだコメントはありません。最初のコメントを書いてみませんか?