meow_netmgrd 期2:观测层(PID→实体归因+连接普查)+DNS 代理+事件日志+连接/DNS IPC 与 CLI
NETMGR_DESIGN.md 期2范围落地(全在 patch_v2/meow_netmgrd/ + meow_ipc.h 追加):
- 连接普查(§4):每 2s 解析 /proc/net/{tcp,udp}(IPv4) → socket inode→pid(由 inode 集驱动扫
/proc/<pid>/fd,不逐 pid 盲扫)→ 三实体归因 app:<pkg>(amsd status)/svc:<svc>(svcd 落盘状态
/tmp/meow_svcd.status,socket 查询兜底)/proc:<comm>(无则 proc:unknown)。连接表静态 ≤512:
entity/五元组/状态/寿命;远端 IP 由 DNS 缓存反查域名。
- DNS 代理(§5):监听 127.0.0.1:53 UDP;启动备份 resolv.conf 写双行(127.0.0.1+原上游,崩溃零断流);
透传转发+缓存(TTL 尊重;≤256 条);按源端口(port→entity)归因;域名规则 per-entity+global allow/deny
(deny→NXDOMAIN+日志);atexit/SIGTERM/SIGHUP 恢复;5s 自检被第三方改回即重写;HibyOS 绝不启用/绝不改 resolv。
DNS wire(deny NXDOMAIN / forward→A+cache / NXDOMAIN id 回显) 宿主+qemu 实测 PASS。
- 事件日志(§8):新连接/关闭/dns deny/接口状态变化;同 entity 同 dst 1 分钟去重(首条+计数)。
- IPC meow_ipc.h 追加 0x00E8 CONNS_REQ/RESULT、0x00EC DNS_CTL/RESULT(纯追加不改既有行;
0x00EA 策略(期3)/0x00EE 事件推送(预留) 保留)。
- CLI meow_net 补 apps / conns [entity] / top(2s 刷新) / dns status|stats|flush。
- 内存:静态表禁 malloc,mipsel bss 228KB → RSS≈374KB,≤600KB 目标 / ≤1MB 预算。
宿主编译 -Wall -Wextra 0 warning;test_netmgrd.sh 48/48(宿主+qemu)、test_netmgrd_p2 全过(宿主+qemu)、
netmgrd_authtest 全过;真机(M6.0/0.8.0)只读实测 apps/conns/dns status 正确
(svc:meowpanel/svc:mdnsd/proc:dropbear 真实三实体归因),resolv.conf 测后核验原值未触碰。
This commit is contained in:
1 parent
239345bfd2
commit
52edf0c9e4
8 files changed
+1400
-8
No files matched your search
@@ -37,6 +37,19 @@ EOF
|
||||
printf 'nameserver 223.5.5.5\nnameserver 10.78.193.1\n' > "$T/resolv"
|
||||
echo meow > "$T/boot_mode"
|
||||
|
||||
# ---- 期2 观测层打桩:/proc/net/{tcp,udp}(IPv4 LE hex)+ 域名规则 conf + amsd/svcd 缺省 ----
|
||||
cat > "$T/tcp" <<'EOF'
|
||||
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
|
||||
0: 32C14E0A:5137 0905CD8C:01BB 01 00000000:00000000 00:00000000 00000000 1000 0 12345 1 0 0 10 0
|
||||
1: 32C14E0A:4F32 32C34E0A:01BB 01 00000000:00000000 00:00000000 00000000 1000 0 12346 1 0 0 10 0
|
||||
2: 32C14E0A:0A00 00000000:0000 07 00000000:00000000 00:00000000 00000000 1000 0 67890 1 0 0 10 0
|
||||
EOF
|
||||
cat > "$T/udp" <<'EOF'
|
||||
sl local_address rem_address st tx_queue rx_queue tr tm->when retrnsmt uid timeout inode
|
||||
0: 0100007F:D301 0100007F:0035 07 00000000:00000000 00:00000000 00000000 0 0 99999 1 0 0 10 0
|
||||
EOF
|
||||
printf 'app:dev.player.ncm domain=-ads.example.com\nproc:dropbear domain=+x\n' > "$T/policy"
|
||||
|
||||
# 桩后端命令(popen stubbing)
|
||||
cat > "$T/wpa_cli" <<'EOF'
|
||||
#!/bin/sh
|
||||
@@ -75,10 +88,13 @@ EOF
|
||||
for f in wpa_cli hciconfig bluetoothctl ip; do chmod +x "$T/$f"; done
|
||||
|
||||
mkdir -p "$T/logs" "$T/pid"
|
||||
# 期2:DNS 禁用(宿主无 root 不绑 53),观测层经 MEOW_TCP/UDP 打桩;amsd/svcd 缺省(实体归因走 proc:comm→unknown)。
|
||||
ENVS="MEOW_NET_DIR=$NET MEOW_NETDEV=$T/netdev MEOW_NET_ROUTE=$T/route MEOW_RESOLV=$T/resolv
|
||||
MEOW_RFKILL_DIR=$RF MEOW_BT_DIR=$BT MEOW_BOOT_MODE=$T/boot_mode MEOW_BOOTTS_CACHE=$T/bootts
|
||||
MEOW_IP=$T/ip MEOW_WPA_CLI=$T/wpa_cli MEOW_HCICONFIG=$T/hciconfig MEOW_BLUETOOTHCTL=$T/bluetoothctl
|
||||
MEOW_NET_SOCK=$T/net.sock MEOW_NET_POLL_SEC=1 MEOW_LOG_DIR=$T/logs"
|
||||
MEOW_NET_SOCK=$T/net.sock MEOW_NET_POLL_SEC=1 MEOW_LOG_DIR=$T/logs
|
||||
MEOW_TCP=$T/tcp MEOW_UDP=$T/udp MEOW_NET_POLICY=$T/policy
|
||||
MEOW_AMS_SOCK=$T/no_ams MEOW_SVCD_SOCK=$T/no_svcd MEOW_DNS_DISABLE=1"
|
||||
ln -sf "$(readlink -f "$BIN")" "$T/meow_net" # argv[0] 双形态 → CLI
|
||||
|
||||
# ---- T0: 守护起 ----
|
||||
@@ -159,6 +175,95 @@ ck T9a "usage: meow_net" "$OUT"
|
||||
OUT=$(env $ENVS $Q "$T/meow_net" bogus 2>&1); RC=$?
|
||||
ck T9b "usage: meow_net" "$OUT"
|
||||
|
||||
# ---- 重启 daemon A(T8 已停)供期2 观测/连接表/日志测试 ----
|
||||
env $ENVS $Q "$BIN" --sock "$T/net.sock" >"$T/daemon2.log" 2>&1 &
|
||||
DPID=$!
|
||||
for i in $(seq 1 30); do [ -S "$T/net.sock" ] && break; sleep 0.2; done
|
||||
[ -S "$T/net.sock" ] || { echo "FAIL T10-pre: daemon 未重启"; cat "$T/daemon2.log"; exit 1; }
|
||||
|
||||
# ---- T10: 期2 conns(读级;观测层经 MEOW_TCP/UDP 桩 + amsd/svcd 缺省 → proc:unknown 归因)----
|
||||
sleep 1 # 等守护普查一拍
|
||||
OUT=$(env $ENVS $Q "$T/meow_net" conns 2>&1)
|
||||
ck T10a "proc:unknown" "$OUT"
|
||||
ck T10b "10.78.193.50:20791" "$OUT"
|
||||
ck T10b2 "140.205.5.9:443" "$OUT"
|
||||
ck T10c "ESTAB" "$OUT"
|
||||
ck T10d "UDP" "$OUT"
|
||||
ck T10e "connection" "$OUT"
|
||||
# ---- T11: apps(实体聚合)----
|
||||
OUT=$(env $ENVS $Q "$T/meow_net" apps 2>&1)
|
||||
ck T11a "entity" "$OUT"
|
||||
ck T11b "proc:unknown" "$OUT"
|
||||
# ---- T12: dns status/stats(DNS 禁用 → 显示 disabled)----
|
||||
OUT=$(env $ENVS $Q "$T/meow_net" dns status 2>&1)
|
||||
ck T12a "proxy disabled" "$OUT"
|
||||
OUT=$(env $ENVS $Q "$T/meow_net" dns stats 2>&1)
|
||||
ck T12b "proxy disabled" "$OUT"
|
||||
# ---- T13: dns flush(写级;宿主 CLI=CALL_OTHER → 拒)----
|
||||
OUT=$(env $ENVS $Q "$T/meow_net" dns flush 2>&1)
|
||||
ck T13a "permission denied" "$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
|
||||
EOF
|
||||
printf 'nameserver %s\n' "$HOSTIP" > "$T/resolv_dns"
|
||||
cat > "$T/dns_test.py" <<'PYEOF'
|
||||
import socket, struct, threading, sys, os
|
||||
UP_IP = os.environ.get("T_UP_IP", "0.0.0.0")
|
||||
up = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
up.bind((UP_IP, 5311)) # 0.0.0.0 通配,绑到宿主自身 IP
|
||||
up.settimeout(6)
|
||||
def serve():
|
||||
try:
|
||||
while True:
|
||||
d,a = up.recvfrom(1536)
|
||||
off=12
|
||||
while d[off]!=0: off += 1+d[off]
|
||||
off += 1+4
|
||||
qsec = d[12:off]
|
||||
resp = d[:2] + b'\x81\x80' + b'\x00\x01\x00\x01\x00\x00\x00\x00' + qsec
|
||||
resp += b'\xc0\x0c' + b'\x00\x01\x00\x01' + struct.pack('>I',60) + b'\x00\x04' + socket.inet_aton('11.22.33.44')
|
||||
up.sendto(resp, a)
|
||||
except Exception:
|
||||
pass
|
||||
threading.Thread(target=serve, daemon=True).start()
|
||||
def query(name):
|
||||
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'
|
||||
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))
|
||||
except Exception as e:
|
||||
sys.stdout.write("ERR=%s\n" % e)
|
||||
PYEOF
|
||||
# 追加式覆写(env 左→右,后者胜出):DNS 启用、换独立 socket/resolv/policy、上游端口。
|
||||
DNSENV="$ENVS MEOW_DNS_DISABLE=0 MEOW_NET_SOCK=$T/dns.sock MEOW_RESOLV=$T/resolv_dns
|
||||
MEOW_NET_POLICY=$T/policy_dns MEOW_DNS_PORT=5300 MEOW_DNS_UPSTREAM_PORT=5311"
|
||||
ln -sf "$(readlink -f "$BIN")" "$T/dns_netmgrd"
|
||||
env $DNSENV $Q "$BIN" --sock "$T/dns.sock" >"$T/dnsd.log" 2>&1 &
|
||||
D2PID=$!
|
||||
for i in $(seq 1 30); do [ -S "$T/dns.sock" ] && break; sleep 0.2; done
|
||||
sleep 1
|
||||
OUT=$(env $DNSENV $Q "$T/meow_net" dns status 2>&1)
|
||||
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"
|
||||
OUT=$(env $DNSENV $Q "$T/meow_net" dns stats 2>&1)
|
||||
ck T14d "q=2" "$OUT"
|
||||
ck T14e "deny=1" "$OUT"
|
||||
kill $D2PID 2>/dev/null; wait $D2PID 2>/dev/null
|
||||
# 恢复守护 A 的 MEOW_RESOLV(其未被 DNS 触碰,此处确认)
|
||||
grep -q "nameserver 223.5.5.5" "$T/resolv" && { PASS=$((PASS+1)); echo "PASS T14f daemonA resolv untouched"; } || { FAIL=$((FAIL+1)); echo "FAIL T14f daemonA resolv touched"; }
|
||||
|
||||
echo "=============================="
|
||||
echo "PASS=$PASS FAIL=$FAIL"
|
||||
[ $FAIL -eq 0 ]
|
||||
Reference in new issue
Block a user