MoveCar:開源 Cloudflare Workers 挪車通知系統,留電話給人聯絡卻不暴露號碼的自架方案

傳統挪車碼做的事很直接:把你的手機號碼印在一張紙或貼紙上,貼在擋風玻璃,等需要挪車的人自己打電話。這個設計的代價也直接,號碼一旦露出,任何路過的人都能記下來,後續推銷、詐騙、惡意檢舉都從同一個破口進來。MoveCar 想換掉的就是這個動作:掃一個二維條碼,對方在網頁上按「通知車主」,你的手機收到推播,雙方在頁面上交換位置,整個過程對方拿不到你的號碼。 這個構想不算新鮮,市面上早就有人賣挪車碼代收服

用 AI 摘要這篇文章:

傳統挪車碼做的事很直接:把你的手機號碼印在一張紙或貼紙上,貼在擋風玻璃,等需要挪車的人自己打電話。這個設計的代價也直接,號碼一旦露出,任何路過的人都能記下來,後續推銷、詐騙、惡意檢舉都從同一個破口進來。MoveCar 想換掉的就是這個動作:掃一個二維條碼,對方在網頁上按「通知車主」,你的手機收到推播,雙方在頁面上交換位置,整個過程對方拿不到你的號碼。

這個構想不算新鮮,市面上早就有人賣挪車碼代收服務。MoveCar 比較特別的地方是它把整套邏輯塞進一支 Cloudflare Worker,原始碼開源、單檔 37KB、沒有後端伺服器、沒有資料庫,狀態全存在 Cloudflare 的 KV 暫存裡。對想自己架、不想把聯絡邏輯交給第三方服務的人來說,這個位置是有吸引力的。本文要拆的是:它把「號碼外露」這個風險,究竟換成了什麼風險;以及在本地部署它裝得起來,卻會繼承幾個不是為台灣設計的預設。

我沒有實際把這支 Worker 部署到自己的 Cloudflare 帳號、也沒有實機掃碼觸發一次通知。底下的判斷來自我讀它的原始碼 movecar.js(1145 行,含應用程式介面與兩份內嵌網頁)、READMELICENSE 檔,以及 GitHub 上的 issues 與 commit 紀錄。這是認識層級的拆解,不是效果實測,所以我不會告訴你「推播送達多快」「免費額度真的夠用」這類我沒有量過的事,只會把原始碼實際怎麼做、跟 README 哪裡對不上講清楚。

電話號碼不外露為真,但它把風險換去位置那一端

從原始碼看,電話號碼的處理確實如 README 所宣稱。號碼只放在 PHONE_NUMBER 這個環境變數裡(movecar.js 第 168 行用 typeof 檢查它是否存在),推播訊息的內容(第 119 行組出來的 Bark 網址)完全沒有把號碼帶出去。對方掃碼之後,只看得到一個「通知車主」的按鈕;車主這一端收到的 Bark 推播,內含的是對方留的訊息、地圖連結與一個確認網址。換句話說,陌生人拿不到你的號碼這件事,原始碼層級成立。

但這個設計同時把風險搬了家。請求者的地理座標會被寫進 Cloudflare 的 KV 暫存(movecar.js 第 103 到 107 行 MOVE_CAR_STATUS.put('requester_location', ...)),存活時間是 3600 秒,也就是一小時後自動清掉(第 5 行的 CONFIG.KV_TTL)。車主確認時,自己的座標也走同一條路進 KV(第 146 到 152 行)。另外有一個記錄狀態的旗標 notify_status 存活 600 秒,那是請求狀態用的,不是位置資料。KV 是 Cloudflare 基礎設施上的暫存,不是端到端加密的通道。所以更精確的說法是:MoveCar 沒有把你的號碼暴露給陌生人,卻把雙方的位置交給 Cloudflare 的 KV 暫存一小時。

這筆交換值不值得,取決於你怎麼衡量兩種風險。號碼外露是「永久且可大量複製」的破口,一個人記下來可以轉賣、可以反覆騷擾;位置暫存一小時則是「有時限且會自動消失」的暴露,但它的信任邊界落在 Cloudflare 這個營運商身上。如果你本來就把郵件、網站、DNS 交給 Cloudflare,那再交出一小時的位置暫存,風險增量有限;如果你對把任何資料交給單一雲端營運商是有意見的,那 MoveCar 並沒有解掉這個疑慮,只是把它從電信公司(號碼)搬到雲端商(位置)。一小時比號碼永久露出短得多,但比你想像中「掃碼完就結束」要長。

反騷擾的設計也在原始碼裡看得到。如果請求者拒絕分享位置,movecar.js 第 115 到 116 行會讓 Worker 等 30 秒才送出推播(await new Promise(resolve => setTimeout(resolve, 30000)))。這個延遲的用意是提高惡意騷擾的成本,想亂按的人每按一次要等半分鐘,自動化的成本會被墊高。這算是小型工具裡少見、有把防濫用想進去的設計。

面向傳統挪車碼(號碼直印)MoveCar(掃碼推播)
車主暴露的資訊手機號碼(永久、可複製)位置(暫存一小時、自動清除)
聯絡路徑對方直接撥號對方網頁送出,車主收推播
反騷擾機制不分享位置者延遲 30 秒推播
信任邊界落在電信公司與印碼的紙Cloudflare KV 與推播服務商
是否需要後端伺服器否(Serverless),但依賴 Cloudflare 基礎設施
傳統挪車碼與 MoveCar 在聯絡方式與風險位置上的差異。

台灣讀者部署前,要先調三個中國本位預設

這個工具是作者為了自己被堵車的痛點做的,預設使用場景是中國大陸。對台灣讀者,它裝得起來,但有三個地方不是為台灣設計,照預設值跑會踩到。

先講地理座標系統,這是最隱形的。movecar.js 第 42 到 60 行有一段 wgs84ToGcj02 函式,做的是把全球通用的 WGS84 座標(GPS 與 Google 地圖用的那套)轉換成 GCJ02,也就是中國俗稱的火星座標系。這個轉換有一個 outOfChina 邊界檢查(第 59 到 60 行),只有在緯度 0.8293 到 55.8271、經度 72.004 到 137.8347 這個框裡才轉換。問題在於,台灣的座標(大約緯度 22 到 25、經度 120 到 122)正好落在這個邊界框裡,所以台灣請求者的位置會被套上一層偏移。實際看到的影響是地圖上的標記會偏,偏多少視地點而定,從數十到數百公尺都有可能。這是部署之後、實際用一次才會察覺的細節,原始碼層級就埋著。

地圖服務是另一處會踩到的地方。generateMapUrls 函式(第 79 到 84 行)只產生兩種地圖連結,一是高德地圖(amap),二是 Apple 地圖,沒有產生 Google 地圖連結。高德是中國的圖資服務,在台灣的覆蓋與精細度比 Google 地圖差一截。Apple 地圖在台灣能用,但台灣讀者多數看到地圖連結會直覺想開 Google 地圖,這裡得自己改一下函式,補一條 https://maps.google.com/?q=lat,lng 的網址。

最容易踩雷、也最需要先講的,是 README 那條「安全設置(推薦)」。作者因為曾被境外流量攻擊過,建議在 Cloudflare 的 WAF 加一條規則:Country does not equal ChinaBlock,也就是只放行中國境內流量。對台灣讀者來說,照這條規則設下去的結果,是你自己掃碼也會被擋在外面,因為台灣在 Cloudflare 的地理判定裡不等於 China。這條要嘛直接不加,要嘛改成「只放行台灣與你常在的地區」,別照 README 抄。

官方介面長怎樣

repo 裡放了兩份預覽頁,一份是請求者掃碼後看到的頁面(preview-requester.html),一份是車主收推播後點進去的確認頁(preview-owner.html),以及一張實體挪車碼的示意照(demo.jpg)。請求者頁的流程是留一句話、同意分享位置、按通知;車主頁則是看到對方位置、決定要不要回傳自己的位置。下圖是作者提供的挪車碼實體示意照。兩份頁面的 HTML 直接內嵌在 movecar.js 裡(第 172 行起、第 863 行起),所以部署時只需要貼一個檔案,不需要另外架前端。這是單檔 Worker 設計的好處,缺點是改版面等於改程式碼,不會自動更新的頁面不會分開部署。

MoveCar 挪車碼貼在車上的實體示意照,官方 repo 提供Pin
MoveCar 作者提供的挪車碼實體示意照。

這兩份預覽頁與示意照都是作者放在 repo 的官方資產,不是我自己跑出來的成品。它們能證明工具具備這套介面,但不能證實實際推播的送達速度或穩定度。

MoveCar 請求者頁面預覽,掃碼後填留言並通知車主的介面Pin
MoveCar 請求者掃碼後看到的通知頁面(官方預覽)。

它進不了自己最想服務的那個市場

這個工具最諷刺的地方,是它為了解中國大陸挪車痛點而生,預設的 *.workers.dev 網域卻剛好進不去那個市場。Cloudflare Workers 的預設網域在中國大陸的網路環境裡連不通,這件事在 repo 自己的 issues 裡就有回報。第 16 號 issue 標題寫著「這個部署在 cloudflare.com,中國國內訪問會有問題吧。我就訪問不了!」,第 20 號 issue 則是「你們都用的什麼網域,微信老是攔截」,講的是即便連得通,分享出來的連結也會被微信擋下。

這代表對作者原本鎖定的那些車主,想用這套工具得繞兩道:先綁一個自訂網域(而不是預設的 workers.dev),再想辦法讓那個網域不被微信攔截。對台灣讀者,這個限制剛好反過來:台灣連 *.workers.dev 是通的,所以你直接用預設網域就裝得起來,不需要綁自訂網域,部署門檻比目標市場還低。這是這個工具在「誰實際能用」這件事上,跟它被設計來服務的對象之間,一個有意思的錯位。

跟其他自架工具比起來,它的位置在哪

MoveCar 屬於那一類「把小事收進 Cloudflare Workers 自架」的工具,這個位置在 TechMoon 先前介紹過的工具裡有跡可循。SubsTracker 走的是同一條部署模型,把訂閱管理的後端收進一支 Worker;這條路的最大吸引力是免費額度跟零維運,但代價是工具的命運綁在 Cloudflare 的條款與基礎設施上。OtterHub 則把這個 Serverless 自架模型推到更隱私敏感的檔案儲存領域,同樣要面對「資料落在自己帳號,但運作在第三方雲端」這條界線。MoveCar 在這個光譜上偏輕量,它存的只是 60 分鐘的位置暫存,不是長期資料,所以這條邊界的風險相對小,但邏輯是一樣的。

跟掃碼觸發臨時通道的工具比,PrintRelay 那類掃碼傳檔做的是「短暫開一條路給資料走過去」,MoveCar 做的是「短暫開一條路給一次通知走過去」,兩者都是用掃碼把一次性的聯絡動作限定在當下,不留下常駐通道。這個設計模式的優點是攻擊面小,缺點是每一次聯絡都要重新掃一次碼。

它不是沒有限制。Bark 這個推播服務是為蘋果裝置設計的,作者自己在 README 也寫了「安卓用戶原理相通,把 Bark 替換成 Pushplus、Server醬 之類的服務即可」,但這代表如果你是 Android 用戶,預設部署完不會收到通知,得自己改推播這一段程式碼,作者宣稱替換可行,我沒有實際替換過。Cloudflare Workers 的免費額度作者宣稱「完全夠用」,這個判斷對個人挪車碼這種極低頻使用大概成立,但我沒有實際量過帳單。repo 本身的活躍度也是一個變數:主分支最後一次 commit 是 2025 年 12 月 31 日,到現在已經七個多月沒有新提交,沒有任何一個正式發布版本,現存 21 個未關單 issue(歷史上總共 23 件,只關過 2 件)。1163 顆星是在這七個月的停滯期裡累積的,所以這個數字反映的是傳播熱度,不是維護強度,別把星數當成活躍訊號。

想試的話,部署入口長這樣

MoveCar 採 MIT 授權,LICENSE 檔在 repo 根目錄,1070 位元組左右,是標準的 MIT全文,所以你可以自由修改、再散布、商業使用。部署的入口照 README 是五步:註冊 Cloudflare 帳號、建一個 Worker 把 movecar.js 整份貼進去、建一個名為 MOVE_CAR_STATUS 的 KV 命名空間並綁定到 Worker、在環境變數裡設 BARK_URL(你的 Bark 推播網址)與可選的 PHONE_NUMBER、最後把 Worker 網址產成二維條碼印出來。整個流程不需要架伺服器,也不需要資料庫,KV 與運算都算在 Cloudflare 免費額度裡。

部署完之後,回到前面那三個預設調一次:把 WAF 那條「擋非中國流量」的規則直接不要開,或者改成放行台灣;把 generateMapUrls 裡補一條 Google 地圖連結;座標轉換那一段如果在意偏移,可以在 outOfChina 的判斷裡把台灣的經緯度範圍排除掉,讓它直接用原始 WGS84。這三個調整都不是必須,不調也能跑,但調了才會是真正為台灣用地圖習慣設計的版本。

把號碼換成一小時的位置暫存,這筆交易誰划算

適合的是這樣的人:本來就用 Cloudflare、對改一小段 JavaScript 不陌生、開車會被擋車、不想把號碼印給陌生人看、能接受位置短暫走雲端暫存。對這群人,MoveCar 是一個授權乾淨、機制清楚、可以照自己意思改的小工具,部署成本主要花在申請 Bark 跟產二維條碼上。

不適合的也清楚。如果你要的是「連位置都不能交給任何雲端商」的等級,這套不適合,它的 KV 暫存就是交給了 Cloudflare。Android 用戶也要另外留意,預設只支援蘋果裝置,裝完不會收到通知,得自己改推播這一段。如果你把專案的活躍度看得很重,七個月沒有新 commit、沒有發布版本、現存 21 個未關單 issue,這個訊號也要算進去,雖然對一個已經能跑的小工具來說,停滯不等於不能用,但意味著後續遇到問題只能自己改。

把這幾條邊界畫清楚之後,MoveCar 的價值就清楚:它把「留電話給陌生人」這件高風險動作,換成「留一個掃碼動作給陌生人、自己收推播」的低風險版本,代價是位置暫存雲端一小時,以及你需要手動調幾個中國本位的預設。它需要先調過那幾個預設才會順手,這個調整成本是不是值得,取決於你有多在意號碼外露這件事。

Sliven 褚崇名
Sliven 褚崇名

每日分享科技新知、免費資源以及 WordPress、虛擬主機相關主題,任何問題歡迎在科技月球下方留言,或是發送 Email 至 [email protected] 與我聯繫。

文章: 759

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *


Share to...