测评环境设置

1, 苹果手机环境设置

在Pirvacy & Security中

2, 路由器 Wi-Fi BSSID设置

a): 要查看 BSSID/MAC 地址,有几种常见方法:

在手机上:

安卓:打开 Wi-Fi 设置 → 连接的网络 → 点击网络详情 → 通常能看到 BSSID(就是 AP 的 MAC 地址)。

iPhone:系统不会直接显示 BSSID,但可以通过 AirPort Utility(苹果官方工具) 扫描 Wi-Fi 才能看到。

在电脑上:

打开命令提示符,输入:

netsh wlan show interfaces

里面会显示 BSSID

Linux / macOS

亚马逊 App、Google、苹果定位服务都会把 BSSID + 信号强度 上传到定位数据库(类似 Wi-Fi 定位系统),即使你隐藏真实 GPS,也可能用 BSSID 反推位置。

iw dev wlan0 link   # Linux
airport -I          # macOS (需启用 airport 工具)

都能显示 BSSID/MAC。

b): 常用 MAC 地址厂商查询网站

IEEE 官方注册库(权威来源)
👉 IEEE OUI Lookup
(原始数据文件,更新最及时,但界面不太友好)

MAC Vendors(推荐)
👉 https://macvendors.com/
(输入 MAC 地址即可查询厂商,界面简洁)

MAC Lookup
👉 https://maclookup.app/
(支持输入完整 MAC 或前缀,结果详细)

Wireshark OUI Lookup
👉 https://www.wireshark.org/tools/oui-lookup.html
(由 Wireshark 提供,数据来源同 IEEE)

DNSChecker MAC Vendor Lookup
👉 https://dnschecker.org/mac-lookup.php
(支持批量查询,适合快速查路由器/交换机厂商)

BSSID 地理查询,以下代码示例

<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>BSSID 地理查询(Mylnikov / MLS)</title>
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css">
<style>
  :root { --bg:#0f172a; --card:#111827; --fg:#e5e7eb; --muted:#9ca3af; --ok:#22c55e; --bad:#ef4444; }
  body { margin:0; font:15px/1.6 system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial; background:var(--bg); color:var(--fg); }
  .wrap { max-width:980px; margin:32px auto; padding:0 16px; }
  .card { background:var(--card); border:1px solid #1f2937; border-radius:14px; padding:18px; box-shadow:0 6px 20px rgba(0,0,0,.15);}
  h1 { margin:0 0 10px; font-size:20px; }
  .note { color:var(--muted); margin:6px 0 14px; }
  label { display:block; margin:8px 0 6px; color:#cbd5e1;}
  input[type=text] { width:100%; padding:10px 12px; border-radius:10px; border:1px solid #334155; background:#0b1220; color:var(--fg);}
  .row { display:flex; gap:10px; flex-wrap:wrap; }
  .row > * { flex:1 1 220px; }
  button { border:1px solid #334155; background:#0b1220; color:var(--fg); padding:10px 14px; border-radius:10px; cursor:pointer; }
  button.primary { background:var(--ok); border-color:var(--ok); color:#03110a; font-weight:600; }
  .btns { display:flex; gap:10px; flex-wrap:wrap; margin:10px 0 0; }
  .grid { display:grid; grid-template-columns:1fr 1fr; gap:14px; margin-top:14px; }
  .stat { background:#0b1220; border:1px solid #334155; border-radius:10px; padding:10px; min-height:64px; }
  .k { color:#9ca3af; }
  .v { font-family:ui-monospace,Menlo,Consolas,monospace; }
  .ok { color:var(--ok); } .bad { color:var(--bad); }
  #map { height:380px; border-radius:12px; border:1px solid #1f2937; }
  @media (max-width:800px){ .grid{ grid-template-columns:1fr; } }
</style>
</head>
<body>
<div class="wrap">
  <div class="card">
    <h1>BSSID 地理查询</h1>
    <div class="note">说明:优先调用 <b>Mylnikov</b>(免注册),备选 <b>Mozilla Location Service</b>。若库中无记录或被 CORS 限制,可能查不到。</div>

    <label>BSSID / MAC(格式:AA:BB:CC:DD:EE:FF)</label>
    <input id="mac" type="text" value="C8:BF:4C:A4:02:E5" />

    <div class="btns">
      <button class="primary" id="query">查询</button>
      <button id="tryMLS">尝试 MLS 备选</button>
      <span id="status" class="note"></span>
    </div>

    <div class="grid">
      <div class="stat">
        <div class="k">查询状态</div>
        <div id="state" class="v">等待中…</div>
      </div>
      <div class="stat">
        <div class="k">坐标 (lat, lon)</div>
        <div id="coords" class="v">—</div>
      </div>
      <div class="stat">
        <div class="k">国家 / 城市(近似)</div>
        <div id="place" class="v">—</div>
      </div>
      <div class="stat">
        <div class="k">数据来源</div>
        <div id="source" class="v">—</div>
      </div>
    </div>

    <div style="margin-top:14px">
      <div id="map"></div>
    </div>

    <div class="note" style="margin-top:10px">
      * 国家/城市是通过公开逆地理接口近似推断,仅供参考;结果受数据覆盖与时间影响。
    </div>
  </div>
</div>

<script src="https://unpkg.com/[email protected]/dist/leaflet.js"></script>
<script>
let map, marker;
function initMap(){
  map = L.map('map').setView([20, 0], 2);
  L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
    maxZoom: 19, attribution: '&copy; OpenStreetMap'
  }).addTo(map);
}
initMap();

const el = id => document.getElementById(id);
const fmt = n => (Math.round(n*1e6)/1e6).toFixed(6);

function setStatus(msg, cls){ el('status').textContent = msg || ''; el('state').innerHTML = cls ? `<span class="${cls}">${msg}</span>` : msg; }
function setResult(lat, lon, source){
  el('coords').textContent = `${fmt(lat)}, ${fmt(lon)}`;
  el('source').textContent = source;
  if (marker) { map.removeLayer(marker); }
  marker = L.marker([lat, lon]).addTo(map);
  map.setView([lat, lon], 14);
  reverseGeocode(lat, lon);
}
async function reverseGeocode(lat, lon){
  // Nominatim 反向地理(轻量使用)
  try{
    const url = `https://nominatim.openstreetmap.org/reverse?format=jsonv2&lat=${lat}&lon=${lon}&zoom=10&accept-language=zh-CN`;
    const r = await fetch(url, { headers: { 'User-Agent': 'bssid-lookup-demo' }});
    const j = await r.json();
    const country = j.address?.country || '未知国家';
    const city = j.address?.city || j.address?.town || j.address?.county || j.address?.state || '未知城市';
    el('place').textContent = `${country} / ${city}`;
  } catch {
    el('place').textContent = '反向地理失败';
  }
}

async function queryMylnikov(mac){
  setStatus('Mylnikov 查询中…');
  const url = `https://api.mylnikov.org/geolocation/wifi?v=1.1&bssid=${encodeURIComponent(mac)}`;
  const r = await fetch(url);
  if (!r.ok) throw new Error('Mylnikov 请求失败');
  const j = await r.json();
  // 成功:{ result:200, data:{ lat, lon, range, time } }
  if (j.result === 200 && j.data && typeof j.data.lat === 'number' && typeof j.data.lon === 'number'){
    return { lat: j.data.lat, lon: j.data.lon, provider: 'Mylnikov' };
  }
  throw new Error('Mylnikov 无记录');
}

async function queryMLS(mac){
  setStatus('MLS 查询中…');
  const url = 'https://location.services.mozilla.com/v1/geolocate?key=test';
  const body = { wifiAccessPoints: [{ macAddress: mac }] };
  const r = await fetch(url, { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify(body) });
  if (!r.ok) throw new Error('MLS 请求失败(可能 CORS 或配额)');
  const j = await r.json();
  if (j && j.location && typeof j.location.lat === 'number'){
    return { lat: j.location.lat, lon: j.location.lng, provider: 'Mozilla MLS' };
  }
  throw new Error('MLS 无记录');
}

async function run(primary='mylnikov'){
  el('place').textContent = '—';
  el('coords').textContent = '—';
  el('source').textContent = '—';
  const mac = el('mac').value.trim();
  if (!/^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$/.test(mac)){
    setStatus('请输入有效的 MAC/BSSID(AA:BB:CC:DD:EE:FF)', 'bad');
    return;
  }
  try{
    let res;
    if (primary === 'mylnikov'){
      res = await queryMylnikov(mac);
    } else {
      res = await queryMLS(mac);
    }
    setStatus('查询成功', 'ok');
    setResult(res.lat, res.lon, res.provider);
  } catch(e1){
    setStatus((primary==='mylnikov'?'Mylnikov':'MLS')+' 无结果/失败:'+e1.message, 'bad');
    // 自动尝试备选
    try{
      const res = await (primary==='mylnikov' ? queryMLS(mac) : queryMylnikov(mac));
      setStatus('使用备选源成功', 'ok');
      setResult(res.lat, res.lon, res.provider);
    } catch(e2){
      setStatus('两种来源都未获取到位置记录', 'bad');
    }
  }
}

el('query').onclick = ()=> run('mylnikov');
el('tryMLS').onclick = ()=> run('mls');
</script>
</body>
</html>

BSSID 工具,测试(最好用当地国家使用的路由器MAC)

<!doctype html>
<html lang="zh-CN">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<title>OUI 学习与测试 BSSID 工具(合规版)</title>
<style>
:root{--bg:#0f172a;--card:#111827;--fg:#e5e7eb;--muted:#94a3b8;--ok:#22c55e;--err:#ef4444;--bd:#283142;}
*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--fg);font:15px/1.6 system-ui,-apple-system,Segoe UI,Roboto,Helvetica,Arial;}
.wrap{max-width:980px;margin:36px auto;padding:0 16px}
.card{background:var(--card);border:1px solid var(--bd);border-radius:14px;padding:18px;margin-bottom:16px;box-shadow:0 6px 20px rgba(0,0,0,.15)}
h1{font-size:20px;margin:0 0 8px}h2{font-size:17px;margin:6px 0 10px}
.note{color:var(--muted)}
label{display:block;margin:8px 0 6px;color:#cbd5e1}
input,select,button{padding:10px 12px;border-radius:10px;border:1px solid #334155;background:#0b1220;color:var(--fg)}
button{cursor:pointer}
button.primary{background:var(--ok);border-color:var(--ok);color:#03110a;font-weight:600}
.row{display:flex;gap:10px;flex-wrap:wrap}
.row>*{flex:1 1 260px}
code{font-family:ui-monospace,Menlo,Consolas,monospace;background:#0b1220;border:1px solid #334155;border-radius:8px;padding:6px 8px}
.kv{display:grid;grid-template-columns:140px 1fr;gap:8px 12px;align-items:center}
.bad{color:var(--err)}.ok{color:var(--ok)}
table{width:100%;border-collapse:collapse;font-size:14px}
th,td{border-bottom:1px dashed #334155;padding:8px 6px;text-align:left}
</style>
</head>
<body>
<div class="wrap">
<div class="card">
<h1>OUI 学习与测试 BSSID 工具(合规版)</h1>
<p class="note">用途:学习 OUI/厂商与 MAC 的关系、验证已有 BSSID 的厂商;生成的“测试 BSSID”仅为<strong>本地管理(LAA)</strong>地址,适合实验室测试,<b>不用于伪装真实设备/热点</b>。</p>
</div>
<div class="card">
<h2>① 常见厂商 OUI(示例,非完整库)</h2>
<div class="row">
<div>
<label>按厂商筛选</label>
<select id="vendorSel"></select>
</div>
<div>
<label>按 OUI 前缀筛</label>
<input id="ouiFilter" placeholder="如 00:1B:2F" />
</div>
</div>
<div style="margin-top:10px;overflow:auto;max-height:320px">
<table id="tbl">
<thead><tr><th>厂商</th><th>OUI 前缀(前 24bit)</th><th>备注</th></tr></thead>
<tbody></tbody>
</table>
</div>
<p class="note">说明:OUI = MAC 的前三字节。下表仅示例,供学习/验证;不建议用真实 OUI 生成可被误用的地址。</p>
</div>
<div class="card">
<h2>② 校验已有 MAC/BSSID 的厂商归属</h2>
<div class="row">
<div>
<label>输入 MAC/BSSID</label>
<input id="macIn" placeholder="AA:BB:CC:DD:EE:FF" />
</div>
<div style="align-self:end">
<button class="primary" id="chk">校验厂商</button>
</div>
</div>
<div class="kv" style="margin-top:12px">
<div>识别结果</div><div id="chkOut" class="note">—</div>
</div>
</div>
<div class="card">
<h2>③ 生成测试用 BSSID(本地管理 LAA,非真实厂商)</h2>
<div class="row">
<div>
<label>可选种子(任意文字,保证可复现)</label>
<input id="seed" placeholder="留空则随机" />
</div>
<div style="align-self:end">
<button class="primary" id="gen">生成 LAA 测试 BSSID</button>
</div>
</div>
<div class="kv" style="margin-top:12px">
<div>结果</div><div><code id="bssid">—</code></div>
<div>合法性</div><div id="valid" class="note">—</div>
</div>
<p class="note">规则:生成的地址将设置为<strong>本地管理 (LAA)</strong>且<strong>单播</strong>(不使用任何真实 OUI)。请仅在受控环境中测试。</p>
</div>
<div class="card">
<h2>合规提醒</h2>
<ul class="note">
<li>不要使用真实厂商 OUI 生成地址去冒充真实热点或设备。</li>
<li>不要用于逃避平台风控或误导式定位。</li>
<li>若做商业/产品化,请遵从各平台/法律与隐私条款。</li>
</ul>
</div>
</div>
<script>
// 少量“常见厂商 OUI 示例”(用于学习/校验;非完整库)
const OUIS = [
{ vendor: "Netgear",  oui: "00:1B:2F", note:"家用路由常见" },
{ vendor: "Netgear",  oui: "18:67:9F", note:"" },
{ vendor: "Linksys",  oui: "00:1E:4F", note:"Belkin/Linksys" },
{ vendor: "Linksys",  oui: "00:24:E8", note:"" },
{ vendor: "ARRIS",    oui: "14:C5:9D", note:"ISP 网关常见" },
{ vendor: "ARRIS",    oui: "00:03:02", note:"" },
{ vendor: "TP-Link",  oui: "30:8C:FB", note:"普及品牌" },
{ vendor: "TP-Link",  oui: "54:27:1E", note:"" },
{ vendor: "Belkin",   oui: "C0:25:E9", note:"家用品牌" },
{ vendor: "Belkin",   oui: "F4:0E:11", note:"" },
{ vendor: "Google",   oui: "24:C6:62", note:"Nest / 家用热点" },
{ vendor: "Google",   oui: "34:AB:F5", note:"" },
{ vendor: "Comcast",  oui: "58:6D:8F", note:"运营商网关" },
{ vendor: "Ubiquiti", oui: "F0:9F:C2", note:"家庭/中小企 AP" },
];
const $ = id => document.getElementById(id);
const tblBody = document.querySelector("#tbl tbody");
const vendorSel = $("vendorSel");
function renderTable(filterVendor = "", filterOUI = "") {
tblBody.innerHTML = "";
const rows = OUIS.filter(r =>
(filterVendor ? r.vendor === filterVendor : true) &&
(filterOUI ? r.oui.startsWith(filterOUI.toUpperCase()) : true)
);
for (const r of rows) {
const tr = document.createElement("tr");
tr.innerHTML = `<td>${r.vendor}</td><td><code>${r.oui}</code></td><td class="note">${r.note||""}</td>`;
tblBody.appendChild(tr);
}
if (!rows.length) {
const tr = document.createElement("tr");
tr.innerHTML = `<td colspan="3" class="note">无匹配</td>`;
tblBody.appendChild(tr);
}
}
function initVendors() {
const vendors = Array.from(new Set(OUIS.map(x => x.vendor))).sort();
vendorSel.innerHTML = `<option value="">(全部厂商)</option>` + vendors.map(v => `<option>${v}</option>`).join("");
}
initVendors();
renderTable();
vendorSel.onchange = () => renderTable(vendorSel.value, $("ouiFilter").value.trim());
$("ouiFilter").oninput = () => renderTable(vendorSel.value, $("ouiFilter").value.trim());
// ② 校验已有 MAC/BSSID 的厂商
$("chk").onclick = () => {
const mac = $("macIn").value.trim().toUpperCase();
const out = $("chkOut");
const m = mac.match(/^([0-9A-F]{2}:){5}[0-9A-F]{2}$/);
if (!m) { out.innerHTML = `<span class="bad">格式无效</span>`; return; }
const oui = mac.slice(0,8);
const hit = OUIS.find(x => x.oui === oui);
out.innerHTML = hit
? `<span class="ok">${hit.vendor}</span>(匹配 OUI ${hit.oui})`
: `<span class="note">本地示例库未收录此 OUI(可能属其他厂商或需外部数据库查询)</span>`;
};
// ③ 生成“本地管理 LAA”测试 BSSID
function h2(n){ return n.toString(16).padStart(2,"0").toUpperCase(); }
function setLAAUnicast(b){ return (b & 0b11111110) | 0b00000010; } // 单播且 LAA
async function genLAA(){
const seed = $("seed").value.trim() || (crypto.getRandomValues(new Uint32Array(4)).join("-"));
const data = new TextEncoder().encode(seed);
const hash = await crypto.subtle.digest("SHA-256", data);
const mac = new Uint8Array(hash).slice(0,6);
mac[0] = setLAAUnicast(mac[0]);
const out = Array.from(mac).map(h2).join(":");
$("bssid").textContent = out;
const ok = ((mac[0] & 1) === 0) && ((mac[0] & 2) === 2);
$("valid").innerHTML = ok ? `<span class="ok">有效:LAA + 单播(测试用途)</span>` : `<span class="bad">无效</span>`;
}
$("gen").onclick = genLAA;
</script>
</body>
</html>