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