meow_netmgrd 期4:SDK 自愿通道 + wifi forget + RSSI signal_poll + AAAA 过滤 + iptables 评估

NETMGR_DESIGN.md §7/§13 期4 落地(只动 patch_v2/meow_netmgrd/ + patch_v2/sdk/ 追加式):
1. SDK 自愿通道(§6.3/§4):meow_ui.h 新增 meow_net_policy_check(host)(0=放行 1=block;
   netmgrd 不在/超时→0 乐观放行)+ meow_net_report(rx,tx)(自愿上报,§4 字节级记账自报通道)。
   meow_ipc.h 追加 0xEE MSG_NET_SDK(op=CHECK/REPORT)/ 0xEF RESULT。netmgrd 侧:CHECK 以
   app_id→实体 app:<pkg> 评估 policy_net_blocked||dns_query_domain_denied;REPORT 记入 per-实体
   g_ent_bytes(status JSON 新增 entity_bytes)。SDK 实现 meow_net_ipc.c(一次 connect+send+read,
   降级不崩);meow_ui.a 重编。
2. wifi forget <id>:wpa_cli remove_network+save_config(MeowOS;HibyOS 只读门控),CLI+IPC 接通
   (286 launcher 录入 UI 缺口)。
3. RSSI:wifi_status 在 status 无 signal= 时回退 wpa_cli signal_poll(真机 rssi=-38,修面板 rssi=null 缺口)。
4. DNS AAAA 过滤:global dns.filter_aaaa=0|1(默认 0 透传;纯 IPv4 设备可置 1 让 AAAA 查询回空答案回落 A)。
5. 静态 iptables 评估(devdocs/plan/NETMGR_IPTABLES_EVAL.md,本机不入库):iptables-legacy 1.8.9 交叉
   编译成功(~578KB,含 owner/cgroup/REDIRECT 等全部 extension),但内核实测 matches 仅
   quota/icmp/udp/tcp、targets 仅 NFQUEUE/NFLOG/ERROR、无 nat 表、全部进程 UID 0 → **per-app 管控
   与 REDIRECT 透明代理判不可行**(与 NETWORK_HW_FACTS 一致);正路为 per-app UID 框架改造(单独立项)。

验证:宿主 test_netmgrd.sh 70/70 + qemu 70/70;test_netmgrd_p2/p3/p5 宿主全过 + 交叉 0 warning;
netmgrd_authtest 全过;sdk meow_net_ipc 交叉 0 warning。真机(固件 netmgrd 共存,独立 socket+DNS off):
wifi status rssi=-38(signal_poll)、wifi forget 0(DISABLED 安全移除,id1 CURRENT 保留、wifi 未断)、
SDK policy check(CHECK_GOOD=0/CHECK_BLOCK=1/REPORT ok)、policy show 正常;resolv.conf 未触碰、
固件 meow_netmgrd(pid) running 未动;测试产物全清。

新 md5:meow_netmgrd 20243ea1a800b29badefebb395603aaf;meow_ui.a be24214e24faadba63577f3a98c2c9d1
(主会话更 fw_content.conf / 热更设备 / 记录新 meow_ui.a)。
This commit is contained in:
MeowOS committed 2026-09-02 16:19:40 +08:00
1 parent 4e0e7441fd
commit 8a43f17653
17 files changed
+563 -16

No files matched your search

+53 -5
View File
@@ -252,11 +252,56 @@ ck T16e "permission denied" "$OUT"
OUT=$(env $ENVS $Q "$T/meow_net" policy del app:dev.player.ncm 2>&1)
ck T16f "permission denied" "$OUT"
# ---- T17: SDK 自愿通道 end-to-end(meow_net_policy_check/report 对守护 A)----
SDK_BIN="$T/test_net_ipc"
if [ -n "$Q" ]; then
"$HOME/Project/R3ProII/.tools/zig-mipsel-cc" -Os -Wall -Wextra -I../sdk -I../sdk/include -I../meow_launcherd \
../sdk/test_net_ipc.c ../sdk/meow_net_ipc.c -o "$SDK_BIN" 2>/dev/null
else
cc -Os -Wall -Wextra -I../sdk -I../sdk/include -I../meow_launcherd \
../sdk/test_net_ipc.c ../sdk/meow_net_ipc.c -o "$SDK_BIN" 2>/dev/null
fi
if [ -x "$SDK_BIN" ]; then
OUT=$(env MEOW_LOG_APP=dev.player.ncm MEOW_NET_SOCK="$T/net.sock" $Q "$SDK_BIN" 2>&1)
ck T17a "CHECK_GOOD=0" "$OUT" # music.163.com 放行
ck T17b "CHECK_BLOCK=1" "$OUT" # ads.example.com 被策略 deny → block
ck T17c "REPORT_DONE" "$OUT"
else
FAIL=$((FAIL+1)); echo "FAIL T17 SDK test 构建失败"
fi
# ---- T18: SDK report → status JSON entity_bytes 回读 ----
JOUT2=$(python3 - "$T/net.sock" <<'PYEOF'
import socket,struct,sys,json
s=socket.socket(socket.AF_UNIX,socket.SOCK_STREAM); s.connect(sys.argv[1]); s.settimeout(2)
def recvn(n):
d=b""
while len(d)<n:
c=s.recv(n-len(d))
if not c: return d
d+=c
return d
s.sendall(struct.pack('<IHHII',0x4D4F5701,1,0x00E0,1,0))
H=struct.unpack('<IHHII', recvn(16)); body=recvn(H[4])
code,jlen=struct.unpack('<IH',body[:6]); js=body[8:8+jlen].decode('utf-8','replace')
o=json.loads(js)
eb=o.get("entity_bytes") or []
hit=[e for e in eb if e["entity"]=="app:dev.player.ncm"]
sys.stdout.write("EB_HIT=%d RX=%d TX=%d\n" % (len(hit), hit[0]["rx"] if hit else -1, hit[0]["tx"] if hit else -1))
PYEOF
)
ck T18a "EB_HIT=1" "$JOUT2"
ck T18b "RX=12345" "$JOUT2"
ck T18c "TX=67890" "$JOUT2"
# ---- RSSI 回读:status wifi rssi 应 >=0(signal_poll 桩已给)----
OUT=$(env $ENVS $Q "$T/meow_net" status 2>&1)
ck T18d "rssi=-45" "$OUT"
# ---- T14: DNS 代理 wire 实测(守护 B:高端口 + 桩上游 + 全局 deny;测 deny/forward/cache)----
HOSTIP=$(hostname -I 2>/dev/null | awk '{print $1}')
[ -n "$HOSTIP" ] || HOSTIP="127.0.0.1"
cat > "$T/policy_dns" <<'EOF'
global domain=-ads.example.com
global domain=-ads.example.com dns.filter_aaaa=1
EOF
printf 'nameserver %s\n' "$HOSTIP" > "$T/resolv_dns"
cat > "$T/dns_test.py" <<'PYEOF'
@@ -279,17 +324,18 @@ def serve():
except Exception:
pass
threading.Thread(target=serve, daemon=True).start()
def query(name):
def query(name, qtype=1):
s=socket.socket(socket.AF_INET, socket.SOCK_DGRAM); s.settimeout(3)
hdr=b'\x12\x34'+b'\x01\x00'+b'\x00\x01\x00\x00\x00\x00\x00\x00'
q=b''.join(bytes([len(l)])+l.encode() for l in name.split('.'))+b'\x00'+b'\x00\x01\x00\x01'
q=b''.join(bytes([len(l)])+l.encode() for l in name.split('.'))+b'\x00'+struct.pack('>HH',qtype,1)
s.sendto(hdr+q, ("127.0.0.1", 5300))
r,_=s.recvfrom(1536); rco=r[3]&0xf; an=struct.unpack('>H',r[6:8])[0]
return rco,an
try:
d1,a1 = query("ads.example.com") # deny → NXDOMAIN (rcode 3)
d2,a2 = query("music.163.com") # allow → forward → A 11.22.33.44
sys.stdout.write("DENY_RCODE=%d\nALLOW_AN=%d\n" % (d1, a2))
da,aa = query("music.163.com", 28) # AAAA + dns.filter_aaaa=1 → 空应答(回落 A)
sys.stdout.write("DENY_RCODE=%d\nALLOW_AN=%d\nAAAA_RCODE=%d AAAA_AN=%d\n" % (d1, a2, da, aa))
except Exception as e:
sys.stdout.write("ERR=%s\n" % e)
PYEOF
@@ -306,8 +352,10 @@ ck T14a "enabled=1 upstream=$HOSTIP" "$OUT"
WIRE=$(python3 "$T/dns_test.py" 2>&1)
ck T14b "DENY_RCODE=3" "$WIRE"
ck T14c "ALLOW_AN=1" "$WIRE"
ck T14c2 "AAAA_RCODE=0" "$WIRE" # 期4 AAAA 过滤:rcode 0
ck T14c3 "AAAA_AN=0" "$WIRE" # 且 0 条应答(回落 A)
OUT=$(env $DNSENV $Q "$T/meow_net" dns stats 2>&1)
ck T14d "q=2" "$OUT"
ck T14d "q=3" "$OUT" # deny + allow + AAAA = 3 查询
ck T14e "deny=1" "$OUT"
kill $D2PID 2>/dev/null; wait $D2PID 2>/dev/null
# 恢复守护 A 的 MEOW_RESOLV(其未被 DNS 触碰,此处确认)