全部文章

如何在 Node.js 中偵測 VPN(逐步指南)

一篇實用的 Node.js 教學:從後端調用 VPN 偵測 API,讀取判定結果與置信度分數,並據此控制註冊或登入流程。

2026年5月19日閱讀約 5 分鐘

這是一篇關於如何在 Node.js 後端偵測 VPN 流量的實用指南。我們會透過 VPN 偵測 API 查詢訪客的 IP,讀取判定結果與置信度分數, 並據此控制註冊流程。同樣的模式亦適用於登入與結帳情境。

開始之前

你需要一個 API 金鑰(免費方案已足夠測試),以及 Node 18 或以上版本,以便使用全域的 fetch。請將金鑰儲存於環境變數中,切勿寫入用戶端程式碼。

先用任意 IP 測試一下查詢效果

第一步:取得真實的用戶端 IP

在代理伺服器或負載平衡器之後,req.socket.remoteAddress 取得的是你的基礎設施位址,而非 使用者的真實位址。請讀取由你信任的代理伺服器所設定的轉發標頭:

function getClientIp(req) {
  const xff = req.headers['x-forwarded-for'];
  if (xff) return xff.split(',')[0].trim(); // left-most = original client
  return req.socket.remoteAddress;
}

只有在你自行掌控的代理伺服器設定了 X-Forwarded-For 時才應信任它,否則用戶端有可能偽造 該標頭。

第二步:調用偵測 API

將查詢邏輯封裝成一個小型輔助函式。它會回傳判定結果與分數,並在網絡發生錯誤時採取「開放 失敗」(預設放行)的做法,這樣偵測服務出現故障時也不會將使用者拒之門外:

const API_BASE = 'https://ipscanner.io';

async function checkVpn(ip) {
  try {
    const res = await fetch(`${API_BASE}/v1/vpn/${ip}`, {
      headers: { Authorization: `Bearer ${process.env.IPSCANNER_API_KEY}` }
    });
    if (!res.ok) throw new Error(`lookup failed: ${res.status}`);
    const data = await res.json();
    return { isVpn: Boolean(data.vpn), score: data.score ?? 0 };
  } catch (err) {
    console.error('vpn check error', err);
    return { isVpn: false, score: 0 }; // fail open
  }
}

第三步:根據結果控制註冊流程

現在利用這個分數來作決策:低於某個門檻便放行;處於中間區間則要求額外驗證;分數偏高便直接 阻擋:

app.post('/signup', async (req, res) => {
  const ip = getClientIp(req);
  const { isVpn, score } = await checkVpn(ip);

  if (score >= 70) {
    return res.status(403).json({ error: 'Signups from this network need verification.' });
  }
  if (isVpn || score >= 30) {
    req.session.requireEmailVerification = true; // add friction, don't block
  }

  // ...create the account...
  res.json({ ok: true });
});

請留意,在中間區間我們是要求額外驗證,而非直接阻擋。箇中原因可參閱 如何以聰明的方式阻擋 VPN 使用者

第四步:使用快取以節省查詢次數

同一個 IP 往往會反覆出現。使用短期快取可減少 API 調用次數,同時不致令資料過時:

const cache = new Map(); // ip -> { value, expires }

async function checkVpnCached(ip, ttlMs = 10 * 60 * 1000) {
  const hit = cache.get(ip);
  if (hit && hit.expires > Date.now()) return hit.value;
  const value = await checkVpn(ip);
  cache.set(ip, { value, expires: Date.now() + ttlMs });
  return value;
}

請將快取有效期設定得短一些(以分鐘計,而非以日計),因為 IP 的風險程度會隨時間變化。可 參閱何謂 IP 信譽

進一步了解

  • 在同一流程中加入代理伺服器偵測,這樣除了 VPN 之外,亦能 識別代理伺服器與 Tor。
  • 將各類訊號整合為單一的IP 詐騙分數,以這個數值作為決策依據。
  • 將同樣的模式應用於登入與結帳情境,並按不同操作調整門檻。

結論

在 Node.js 中偵測 VPN,本質上只是一次伺服器端的 API 調用:解析出真實的用戶端 IP, 加以查詢,然後根據判定結果與分數採取行動。出錯時預設放行,快取時間應保持較短,並在中間 風險區間要求額外驗證,而非直接一律阻擋。

常見問題

常見問題解答

用戶端檢查容易遭到竄改,亦會暴露你的 API 金鑰。應始終從後端調用偵測 API,這樣結果才可信,憑證亦能保持私密。

相關文章