MAC 制造商

1, 美国用 Netgear, 英国用British Telecommunications plc

美国: 前缀 00:1B:2F → 例:00:1B:2F:11:61:70       //NETGEAR            
英国: 前缀 00:00:DB → 例:00:00:DB:01:23:45       //British Telecommunications plc

查询网址: https://maclookup.app/

Firewall 防火墙操作

1, firewall 允许与禁用端口

firewall-cmd --zone=public --add-port=54212/tcp --permanent    //允许 TCP 端口 
firewall-cmd --zone=public --add-port=54212/udp --permanent  

firewall-cmd --zone=public --remove-port=5421/tcp --permanent   //禁止 
firewall-cmd --zone=public --remove-port=5421/tcp --permanent

firewall-cmd --reload

firewall-cmd --state    # 确认 firewalld 是否运
firewall-cmd --list-all  
firewall-cmd --get-active-zones
firewall-cmd --zone=public --list-all

检查防火墙系统

systemctl is-active firewalld
systemctl is-active nftables
systemctl is-active iptables

/etc/firewalld/firewalld.conf     //NftablesTableOwner=yes    配置项控制

OpenWrt 安装Tun

OpenWrt 默认没有 modprobe,所以一般要先安装:

opkg update
opkg install kmod-tun

检查设备节点

ls -l /dev/net/tun

正常情况下应该有:

crw-rw-rw-    1 root     root      10, 200 Aug 20 20:20 /dev/net/tun

如果没有,说明 TUN 设备未启用

openwrt 安装 tcpdump 用于抓包, 在路由器中查看是否劫持客户端电脑的DNS

opkg update
# 体积小:功能裁剪版(多数场景够用)
opkg install tcpdump-mini

# 或者安装完整版(建议,过滤器/解析功能更全)
opkg install tcpdump

路由器抓包看 WAN 口是否有 53 出去

tcpdump -ni eth_wan 'port 53'
tcpdump -ni eth0 'udp and port 443'
tcpdump -ni any icmp          # IPv4 ICMP
tcpdump -ni any proto 50      # ESP
tcpdump -ni any udp port 500 or udp port 4500  # IKE/NAT-T

先确认规则是否在生效、是否有命中

1) 列出 nft 规则

# 全部规则
nft list ruleset

# 只看你截图里的“dnsmasq”那张表
nft list table inet dnsmasq

# 带 handle 和计数器(建议看这个)
nft -a list chain inet dnsmasq prerouting

如果规则里没有 counter,可以临时加一个(或用 LuCI 加),便于看命中数是否在增长:

nft add rule inet dnsmasq prerouting udp dport 53 counter redirect to :53
# ↑ 只是示例,实际以你的规则为准

实时追踪一条 DNS 包是否命中

nft monitor trace

另一个终端执行 nslookup,然后观察 trace 是否显示命中 dnsmasq/prerouting 的 redirect 规则

3) 看 WAN 口是否还有 53 流量(最终验证)

tcpdump -ni <你的WAN口> 'port 53'
# 比如 pppoe-wan/eth0/eth1 等

能看到去 8.8.8.8 的 53 包 → 劫持没有命中。

完全看不到 53 → 劫持成功(即使你在 LAN 口仍能看到目的为 8.8.8.8 的“原始”包)。

4):

A. 追踪路由器自身 → 127.0.0.1:11302 的流量

# 1) 先开一个终端:
nft monitor trace

# 2) 在另一个终端,把打标规则插到 inet fw4 的 output 链最前面(确保能被命中)
nft insert rule inet fw4 output oifname "lo" udp dport {53,11301,11302} meta nftrace set 1
nft insert rule inet fw4 output oifname "lo" tcp dport {53,11301,11302} meta nftrace set 1
# 如有 IPv6 也会走 lo,这两条已覆盖,无需额外加 ip/ip6 条件

# 3) 再做一次 nslookup(指向 127.0.0.1:11302)
nslookup www.google.com 127.0.0.1#11302
# 此时 monitor 窗口应当开始滚动,显示命中的表/链/规则及 verdict

清理(用 handle 删除你刚插入的规则):

nft -a list chain inet fw4 output | grep nftrace
nft delete rule inet fw4 output handle <handle号>

B. 追踪“LAN 客户端的 DNS 被 NAT 重定向到 11302”的路径

(这才会经过你关心的 PREROUTING/DNAT 规则)

在路由器上打标 prerouting + 来自 LAN 的 53 端口,然后从 LAN 电脑 发起查询(别指向 127.0.0.1,而是随便写 8.8.8.8:53 或默认 DNS):

# 1) 监控窗口
nft monitor trace

# 2) 打标(把 br-lan 改成你的 LAN 接口名)
nft insert rule inet fw4 prerouting iifname "br-lan" udp dport 53 meta nftrace set 1
nft insert rule inet fw4 prerouting iifname "br-lan" tcp dport 53 meta nftrace set 1

# 3) 在 LAN 电脑上执行:
nslookup www.google.com 8.8.8.8
# 现在 monitor 会显示:进入 inet/fw4 的 prerouting → 命中 DNAT/redirect → 继续到本机 11302 的轨迹

清理同上,用 handle 删除。

nft -a list chain inet fw4 prerouting | grep nftrace
nft delete rule inet fw4 prerouting handle <handle号>

5): 两种链的对比

三条典型路径(帮助你定位问题)

  1. LAN 客户端 → 路由器本机 DNS (53)
    (ingress br-lan) → PREROUTING → (路由决策) → INPUT

想劫持它:在 PREROUTINGREDIRECT/DNAT → 11301/11302

  1. LAN 客户端 → 互联网(转发)
    (ingress br-lan) → PREROUTING → FORWARD → POSTROUTING → (egress wan)

常在 PREROUTING 打 mark/TProxy,POSTROUTING 做 SNAT/MASQUERADE

  1. 路由器本机进程 → 上游(如 dnsmasq → 1.1.1.1:53)
    (本机进程) → OUTPUT → POSTROUTING → (egress wan)

想“拦/排除”本机发出的 DNS,在 OUTPUT 上做;PREROUTING 是拦不到的。

6): 禁掉/旁路 非 TCP/UDP 对公网(ICMP/ESP/AH/GRE/NTP 等

方式一:用 LuCI(图形界面)加“流量规则”

目标:仅限制某台买家设备(举例 192.168.111.50)从 LAN → WAN 的非 TCP/UDP;另外单独拦截 NTP(UDP/123),避免侧向校时泄露。

  1. 打开:网络 → 防火墙 → 流量规则 → 添加
    • 名称:Block non-TCP/UDP to WAN (buyer)
    • 家族:IPv4/IPv6(任意)
    • 协议:自定义,填:icmp ah esp gre
    • 源区域:lan
    • 源IP:192.168.111.50(或你买家设备的 IP / 子网)
    • 目标区域:wan
    • 动作:丢弃(DROP)拒绝(REJECT)
    • 保存并应用
  2. 再加一条IPv6 的 ICMPv6(因为上面“icmp”不涵盖 v6 的 ICMPv6)
    • 名称:Block ICMPv6 to WAN (buyer)
    • 家族:仅 IPv6
    • 协议:icmp(在 IPv6 家族下就是 ICMPv6)
    • 其它同上 → 丢弃
  3. 可选:拦截 NTP(若你不希望该设备对公网校时)
    • 名称:Block NTP (buyer)
    • 家族:IPv4/IPv6(任意)
    • 协议:udp
    • 目标端口:123
    • 源区域:lan,源IP:192.168.111.50,目标区域:wan
    • 动作:拒绝(REJECT 更直观,应用会立即得到失败)

说明:这些规则只影响 LAN→WAN 的转发,不影响你在路由器本机上 ping/管理,也不影响 LAN 内互访。


方式二:命令行(UCI 一把梭)

把下面整段贴进 SSH 里(把 IP 改成你的买家设备 IP;如用整段 VLAN/子网,可把 src_ip 改成 192.168.111.0/24):

# 1) 阻断 IPv4/IPv6 的非 TCP/UDP 协议到 WAN(icmp/ah/esp/gre)
uci add firewall rule
uci set firewall.@rule[-1].name='Block-non-TCP_UDP-to-WAN'
uci set firewall.@rule[-1].src='lan'
uci set firewall.@rule[-1].src_ip='192.168.111.50'
uci set firewall.@rule[-1].dest='wan'
uci set firewall.@rule[-1].proto='icmp ah esp gre'
uci set firewall.@rule[-1].target='DROP'
uci set firewall.@rule[-1].family='any'

# 2) 补一条 ICMPv6(icmp 在 family:any 下未必涵盖 v6)
uci add firewall rule
uci set firewall.@rule[-1].name='Block-ICMPv6-to-WAN'
uci set firewall.@rule[-1].src='lan'
uci set firewall.@rule[-1].src_ip='192.168.111.50'
uci set firewall.@rule[-1].dest='wan'
uci set firewall.@rule[-1].proto='icmp'
uci set firewall.@rule[-1].family='ipv6'
uci set firewall.@rule[-1].target='DROP'

# 3) 可选:拦截 NTP(UDP/123)
uci add firewall rule
uci set firewall.@rule[-1].name='Block-NTP-to-WAN'
uci set firewall.@rule[-1].src='lan'
uci set firewall.@rule[-1].src_ip='192.168.111.50'
uci set firewall.@rule[-1].dest='wan'
uci set firewall.@rule[-1].proto='udp'
uci set firewall.@rule[-1].dest_port='123'
uci set firewall.@rule[-1].target='REJECT'
uci set firewall.@rule[-1].family='any'

uci commit firewall
/etc/init.d/firewall restart

R4S 重新写 TF 卡镜像

1, 先用lsblk 命令, 查看存储卡的启动盘情况

NAME SIZE MOUNTPOINTS
loop0 1.7G /overlay
mmcblk1 29.7G
├─mmcblk1p1 32M /mnt/mmcblk1p1
└─mmcblk1p2 2G /rom

2, 不用电脑 TF 读卡器,直接写TF盘,如果是img.gz文件

scp immortalwrt-24.10.2-rockchip-armv8-friendlyarm_nanopi-r4s-ext4-sysupgrade.img.gz [email protected]:/tmp/


gunzip -c /tmp/immortalwrt-rockchip-armv8-friendlyarm_nanopi-r4s-ext4.img.gz | dd of=/dev/mmcblk1 bs=4M conv=fsync
sync
reboot

3,  如果你拿到的是 sysupgrade.bin 而不是 img.gz,可以只写 rootfs 分区:

dd if=/tmp/immortalwrt-rockchip-armv8-friendlyarm_nanopi-r4s-squashfs-sysupgrade.bin of=/dev/mmcblk1p2 bs=4M conv=fsync
sync
reboot

测评环境设置

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>

R4S + 小米 AP VLAN 多 SSID

1, 在 R4S 侧:为连接到小米路由器的那根网线口(比如 eth1)创建多个 VLAN 接口:

eth1.10 → VLAN10 英国节点
eth1.20 → VLAN20 美国节点
eth1.30 → VLAN30 德国节点

每个 VLAN 接口走 Passwall 对应节点。

2, 在小米路由器侧:

无线 AP1 绑定 VLAN10
无线 AP2 绑定 VLAN20
无线 AP3 绑定 VLAN30

这样物理网线只有一根,但 VLAN Tag 把流量隔离出来

3, R4S openwrt上的配置文件

假设你的小米路由器那根网线接在 R4S 的 eth1 上,你可以在 /etc/config/network 添加:

config device
option name 'eth1.10'
option type '8021q'
option ifname 'eth1'
option vid '10'
config interface 'vlan10'
option device 'eth1.10'
option proto 'static'
option ipaddr '192.168.10.1'
option netmask '255.255.255.0'
config device
option name 'eth1.20'
option type '8021q'
option ifname 'eth1'
option vid '20'
config interface 'vlan20'
option device 'eth1.20'
option proto 'static'
option ipaddr '192.168.20.1'
option netmask '255.255.255.0'
config device
option name 'eth1.30'
option type '8021q'
option ifname 'eth1'
option vid '30'
config interface 'vlan30'
option device 'eth1.30'
option proto 'static'
option ipaddr '192.168.30.1'
option netmask '255.255.255.0'

这样会在 eth1 上打 VLAN 10、20、30 三个 Tag,分别对应英国 / 美国 / 德国节点。

配置 /etc/config/dhcp

config dhcp 'vlan10'
option interface 'vlan10'
option start '100'
option limit '150'
option leasetime '12h'
config dhcp 'vlan20'
option interface 'vlan20'
option start '100'
option limit '150'
option leasetime '12h'
config dhcp 'vlan30'
option interface 'vlan30'
option start '100'
option limit '150'
option leasetime '12h'
配置 /etc/config/firewall
config zone
option name 'lan'
option input 'ACCEPT'
option output 'ACCEPT'
option forward 'ACCEPT'
list network 'vlan10'
list network 'vlan20'
list network 'vlan30'

4, 小米openwrt中的配置

典型端口名:eth0/eth1,桥 br-lan,用 bridge-vlans 管理。
假设你用 LAN1 口接 R4S,这个 LAN1 要作为 trunk(tagged 10/20/30)。

a): /etc/config/network

### 把 lan 口做成桥,并在桥里定义 VLAN
config device
option name 'br-lan'
option type 'bridge'
list ports 'lan1'
list ports 'lan2'
list ports 'lan3'
list ports 'lan4'
# 注:如果你只有 2 个 LAN,就保留实际存在的端口
### 定义 bridge-vlans:把 LAN1 设为 trunk(tagged),其他 LAN 可不承载这些 VLAN(或留空)
config bridge-vlan
option device 'br-lan'
option vlan '10'
list ports 'lan1:t'     # trunk:往R4S的这根口
# 如需在本机插线测试 untagged 出 VLAN10,可加 'lan2:u*'
config bridge-vlan
option device 'br-lan'
option vlan '20'
list ports 'lan1:t'
config bridge-vlan
option device 'br-lan'
option vlan '30'
list ports 'lan1:t'
### 给 AP(无线)侧各建一个不带 IP 的接口(桥到对应 VLAN)
config interface 'ap1_vlan10'
option device 'br-lan.10'
option proto 'none'        # Unmanaged,不分配IP
config interface 'ap2_vlan20'
option device 'br-lan.20'
option proto 'none'
config interface 'ap3_vlan30'
option device 'br-lan.30'
option proto 'none'

说明:

  • br-lan.10/20/30 是桥上的 VLAN 子接口
  • ap*_vlan* 接口用 proto none(Unmanaged),只做二层桥接,不跑 IP。
  • LAN1 是接 R4S 的干道口(tagged 10/20/30)。你也可以换成 WAN 口,但需要把 WAN 并入 br-lan,不建议新手这么做。

b): /etc/config/wireless

config wifi-device 'radio0'
option type 'mac80211'
option path 'pci/.../wifi0'   # 系统自动生成的就行
option band '5g'
option htmode 'HE80'
option channel 'auto'
option country 'US'           # 按需修改法规域
### AP1 → 绑到 VLAN10
config wifi-iface
option device 'radio0'
option mode 'ap'
option ssid 'AP1-UK'
option network 'ap1_vlan10'
option encryption 'psk2'
option key 'yourpassword1'
option isolate '1'            # 客户端隔离可选
### AP2 → 绑到 VLAN20
config wifi-iface
option device 'radio0'
option mode 'ap'
option ssid 'AP2-US'
option network 'ap2_vlan20'
option encryption 'psk2'
option key 'yourpassword2'
option isolate '1'
### AP3 → 绑到 VLAN30
config wifi-iface
option device 'radio0'
option mode 'ap'
option ssid 'AP3-DE'
option network 'ap3_vlan30'
option encryption 'psk2'
option key 'yourpassword3'
option isolate '1'

c): /etc/config/dhcp(关闭本机 DHCP)

config dhcp 'lan'
option interface 'lan'
option ignore '1'      # 不在AP上发DHCP
# 可把其它段都忽略
config dhcp 'ap1_vlan10'
option interface 'ap1_vlan10'
option ignore '1'
config dhcp 'ap2_vlan20'
option interface 'ap2_vlan20'
option ignore '1'
config dhcp 'ap3_vlan30'
option interface 'ap3_vlan30'
option ignore '1'

d): /etc/config/firewall

# 作为纯AP,最简单是把防火墙功能整体关掉,或全部接口并入lan,仅作二层桥
config defaults
option syn_flood '1'
option input 'ACCEPT'
option output 'ACCEPT'
option forward 'ACCEPT'
# 清理 wan/masquerade/NAT 等(或直接停用 firewall 服务)

5, 与 R4S 的对接(一定要对应一致)

你之前在 R4S 上已经创建了:
eth1.10(英国)、eth1.20(美国)、eth1.30(德国),并在 Passwall 里按接口分流。

小米这边 trunk 口(lan1:t) 就要接到 R4S 的 eth1

VLAN ID 必须一一对应

  • 小米 AP1 → VLAN 10 ↔ R4S eth1.10
  • 小米 AP2 → VLAN 20 ↔ R4S eth1.20
  • 小米 AP3 → VLAN 30 ↔ R4S eth1.30

6, 应用与排错

应用配置:

/etc/init.d/network restart
wifi reload
# 或重启整机

常见排错:

  • 连接不上某个 SSID → 检查该 SSID 绑定的 network 是否是对应的 br-lan.XX/eth0.XX
  • 终端拿不到 IP → 确认 DHCP 在 R4S 或你指定的地方开启(本机 AP 侧应关闭)。
  • VLAN 不通 → 核对干道口两端是否都为 tagged 同一 VLAN ID
  • 只能上默认出口 → 看 R4S 的 Passwall 是否已按 接口/Zone 绑定节点,并允许该 VLAN 接口通过。

VMware 安装 macOs

1, 亚马逊买家号信用卡头查询

https://binlist.net/

2, iphone 手机虚拟定位

Windows + VMware 安装 macOS + Xcode + 连接 iPhone 虚拟定位操作

Windows

VMware Player 17.5.0(解锁)

macOS Ventura / Monterey 镜像

安装 Xcode(离线包)

连接 iPhone → 启用开发者模式

Xcode 中模拟位置(虚拟定位)

macOS 系统版本对比

下载地址:

https://heipg.cn/macos/install-macos-monterey-12-7-1-21g920-iso.html

安装器界面停在“请选择您要安装 macOS 的磁盘”,但下方没有任何磁盘可选,且“继续”按钮是灰色的。

✅ 原因分析:

通常是以下原因之一导致:

  1. 虚拟磁盘未格式化(最常见)
  2. 创建虚拟机时未添加或未挂载磁盘
  3. 磁盘格式不是 APFS 或 macOS 扩展(Journaled)
  4. 虚拟机 BIOS 设置为 UEFI,但没有识别磁盘

🛠️ 解决步骤:

✅ 步骤 1:打开“磁盘工具”格式化虚拟磁盘

  1. 在当前界面点击左上角「返回」
  2. 回到 macOS 实用工具界面(你会看到“磁盘工具”、“安装 macOS”、“终端”等)
  3. 选择 “磁盘工具”,点击继续
  4. 在左侧找到你的虚拟硬盘(通常叫 “Apple SSD”、“VMware Virtual…” 等)
  5. 点击顶部【抹掉】,设置如下:
    • 名称:macOS
    • 格式:APFS(推荐)或 Mac OS 扩展(日志式)
    • 方案:GUID 分区图(必选)
  6. 点击【抹掉】开始格式化(⚠️ 注意:不是“MS-DOS”格式)

完成后关闭磁盘工具窗口,返回安装器,再次尝试安装。

一步步优化 VMware 中的 macOS

✅ 1. 启用 VT-x / EPT 虚拟化(关键)

必须在 BIOS 中开启 Intel VT-x(虚拟化技术)+ EPT 扩展页表

启动电脑 → 进入 BIOS(多为 F2 / Del)→
找到 Virtualization Technology 或 VT-d → Enabled

并确认未启用 Hyper-V,执行:

bash复制编辑bcdedit /set hypervisorlaunchtype off

✅ 教你彻底关闭 Hyper-V + 虚拟化平台(适用于 Win11)

以下是实战验证最彻底的 3 步关闭方法:


✅ 第一步:命令行禁用 Hypervisor

以管理员身份打开 PowerShell 或 CMD,输入:

bash复制编辑bcdedit /set hypervisorlaunchtype off

然后重启。


✅ 第二步:卸载相关虚拟化功能

  1. 打开「控制面板」→ 程序 → 启用或关闭 Windows 功能
  2. 取消勾选下列所有项目(非常关键):
    • Hyper-V
    • 虚拟机平台(Virtual Machine Platform)
    • Windows 虚拟化平台(Windows Hypervisor Platform)
    • Windows Subsystem for Linux(WSL)(如你不需要)

✅ 取消后点击【确定】,重启系统。


✅ 第三步(关键):关闭核心隔离内存完整性

  1. 设置 → 隐私与安全性 → Windows 安全中心
  2. 打开「设备安全性」→ 点「核心隔离详细信息」
  3. 关闭 内存完整性(Memory Integrity)
  4. 重启系统

这是 Win11 下强制启用 Hyper-V 的重要开关之一。


🧪 检查是否关闭成功

你可以运行命令:

bash复制编辑systeminfo | find "Hyper-V"

若结果中 没有任何以 “Hyper-V” 开头的行,说明你已经彻底关闭了 Hyper-V。

如何判断 Hyper-V 是否真正开启?

在 Win11 下,有两种更准确的检测方式:

1️⃣ 用 msinfo32

  1. Win + R → 输入 msinfo32 → 回车
  2. 在右侧找到 “Hyper-V – 已检测到虚拟机监控程序”
    • 如果显示 “否” → Hyper-V 已关闭
    • 如果显示 “是” → Hyper-V 还在运行

2️⃣ 用 systeminfo 的另一个结果

运行:

powershell复制编辑systeminfo

如果在最底部看到:

less复制编辑Hyper-V Requirements: A hypervisor has been detected. Features required for Hyper-V will not be displayed.

这就说明 Hyper-V 还在运行(即使你关闭了功能菜单里的勾选)。

3, 用GeoPort 虚拟定位

https://zoom.earth/       卫星定位

4, BSSID 修改为国外 MAC

https://maclookup.app/          MAC 制造商
美国住宅  Comcast/Arris/Xfinity     
BSSID 对应美国常见 ISP 路由器厂商(Arris、Netgear、Comcast)

dnsmasq 多实例配置

dnsmasq 被阻塞

Recv-Q 显示 181536,大量 UDP 请求已到达内核但未被 dnsmasq 读取,极大异常

多实例监听配置错误(多个实例监听相同地址端口)

查看所有 dnsmasq 进程:

ps -ef | grep dnsmasq

确保每个 dnsmasq 实例 监听互不冲突的接口/IP/端口