跳到主内容
快讯直播
AI智模界
教程

审计编码智能体出网流量:防静默上传 Git 历史

适用场景

本方案适合在本机或内网服务器上运行编码智能体、代码补全工具、自动化脚本的开发者与运维人员。核心目标是:当智能体在后台读取仓库、调用远端模型或遥测接口时,能看清它到底把哪些数据发到了哪里,并在发现异常上传时直接阻断。以“ZCode 式静默上传 Git 历史”为切口,用出口代理、进程日志、权限隔离三件套,搭一套可复用的外传审计配置。

环境与前置条件

  • 操作系统:主流 Linux 发行版,内核支持 nftables 与 auditd。Windows/macOS 可参考思路,但命令需按平台调整。
  • 运行时:Python 3,用于运行 mitmproxy;pipx 或虚拟环境均可。具体版本要求以 mitmproxy 官方文档当前版本为准。
  • 权限:需要 root 或 sudo,用于创建专用用户、写 nftables 规则、配置 auditd。
  • 磁盘:代理日志与审计日志会持续增长,建议预留数 GB,并配置轮转。
  • 内存:代理常驻内存通常在几百 MB 以内,以实际运行和官方说明为准。
  • 网络:智能体只允许访问出口代理端口,代理再按白名单访问外部模型服务域名。

分步骤部署

1. 安装基础组件

安装 nftables、auditd、Python 工具链。包名以发行版仓库为准。

```bash

sudo apt update

sudo apt install -y nftables auditd python3 python3-pip pipx

pipx install mitmproxy

```

确认命令可用:

```bash

which mitmdump

sudo systemctl status auditd

sudo nft --version

```

mitmdump 能输出版本信息、auditd 处于 active、nft 能正常执行,即视为成功。

2. 创建专用用户与目录

不要让智能体以你的日常账号运行,也不要让代理以 root 运行。创建两个系统用户:zagent 跑智能体,proxyuser 跑代理。

```bash

sudo useradd --system --create-home --shell /bin/bash zagent

sudo useradd --system --create-home --shell /usr/sbin/nologin proxyuser

sudo mkdir -p /srv/agent-work /etc/mitmproxy /var/log/agent-egress

sudo chown root:root /srv/agent-work

sudo chmod 755 /srv/agent-work

sudo chown proxyuser:proxyuser /var/log/agent-egress

sudo chmod 750 /var/log/agent-egress

```

3. 准备最小仓库视图

静默上传的前提通常是智能体能读到完整 .git 历史。给它一个浅克隆,并去掉写权限,能显著缩小暴露面。

```bash

sudo mkdir -p /srv/agent-work/project

sudo chown zagent:zagent /srv/agent-work/project

sudo -u zagent git clone --depth 1 --single-branch https://example.com/your/repo.git /srv/agent-work/project

sudo chown -R root:root /srv/agent-work/project

sudo chmod -R go-w /srv/agent-work/project

sudo mkdir -p /srv/agent-work/workspace

sudo chown zagent:zagent /srv/agent-work/workspace

```

这样智能体只能读项目文件,临时输出写到 workspace,没有完整历史可传。

4. 配置出口代理与白名单

创建审计 addon。把 api.example-model.com 换成实际使用的模型服务域名,白名单只放必须访问的域名。

```bash

sudo tee /etc/mitmproxy/egress_audit.py >/dev/null <<'PY'

import json

import time

from mitmproxy import http

ALLOW = {

"api.example-model.com",

"registry.npmjs.org",

"pypi.org",

}

LOG = "/var/log/agent-egress/access.jsonl"

def _allowed(host: str) -> bool:

return any(host == d or host.endswith("." + d) for d in ALLOW)

def _write(record: dict) -> None:

with open(LOG, "a", encoding="utf-8") as f:

f.write(json.dumps(record, ensure_ascii=False) + "\n")

def http_connect(flow: http.HTTPFlow) -> None:

host = flow.request.host

_write({"ts": time.time(), "type": "connect", "host": host})

if not _allowed(host):

flow.response = http.Response.make(403, b"blocked by egress audit\n")

def request(flow: http.HTTPFlow) -> None:

host = flow.request.pretty_host

body = flow.request.raw_content or b""

_write({

"ts": time.time(),

"type": "request",

"method": flow.request.method,

"host": host,

"path": flow.request.path,

"body_size": len(body),

})

if not _allowed(host):

flow.response = http.Response.make(403, b"blocked by egress audit\n")

PY

```

启动代理服务。ExecStart 里的 mitmdump 路径用 which mitmdump 的结果替换。

```bash

sudo tee /etc/systemd/system/agent-egress-proxy.service >/dev/null <<'EOF'

[Unit]

Description=Agent egress audit proxy

After=network.target

[Service]

User=proxyuser

Group=proxyuser

ExecStart=/home/proxyuser/.local/bin/mitmdump -s /etc/mitmproxy/egress_audit.py --listen-host 127.0.0.1 --listen-port 8080

Restart=on-failure

RestartSec=3

[Install]

WantedBy=multi-user.target

EOF

sudo systemctl daemon-reload

sudo systemctl enable --now agent-egress-proxy

```

5. 用 nftables 限制智能体出网

只允许 zagent 访问本机代理端口,其余出站流量丢弃。这样即使智能体不认代理,也发不出去。

```bash

sudo nft add table inet agent_egress

sudo nft add chain inet agent_egress output '{ type filter hook output priority 0; policy accept; }'

sudo nft add rule inet agent_egress output meta skuid zagent ip daddr 127.0.0.1 tcp dport 8080 accept

sudo nft add rule inet agent_egress output meta skuid zagent ip6 daddr ::1 tcp dport 8080 accept

sudo nft add rule inet agent_egress output meta skuid zagent drop

```

持久化规则。若本机已有 nftables 配置,请合并,不要直接覆盖。

```bash

sudo sh -c 'nft list ruleset > /etc/nftables.conf'

sudo systemctl enable --now nftables

```

6. 配置 auditd 进程与文件读取日志

记录 zagent 执行过的命令,以及它对 .git 目录的读取行为。

```bash

AGENT_UID=$(id -u zagent)

sudo tee /etc/audit/rules.d/agent.rules >/dev/null <<EOF

-a always,exit -F arch=b64 -S execve -F uid=$AGENT_UID -k agent_exec

-w /srv/agent-work/project/.git -p r -k agent_git_read

EOF

sudo augenrules --load

sudo systemctl enable --now auditd

```

7. 以专用用户启动智能体

在子 shell 中显式设置代理环境变量,再启动智能体。启动命令按实际工具替换。

```bash

sudo -u zagent -H bash -lc '

export HTTP_PROXY=http://127.0.0.1:8080

export HTTPS_PROXY=http://127.0.0.1:8080

export NO_PROXY=127.0.0.1,localhost

cd /srv/agent-work/workspace

此处替换为实际编码智能体的启动命令

'

```

验证部署是否成功

1. 代理是否在监听:

```bash

ss -lntp | grep 8080

sudo systemctl status agent-egress-proxy

```

预期看到 127.0.0.1:8080 处于 LISTEN,服务 active。

2. 放行域名测试:

```bash

sudo -u zagent env HTTPS_PROXY=http://127.0.0.1:8080 \

curl -sS -o /dev/null -w "%{http_code}\n" https://api.example-model.com

```

预期返回 200、401、403 等 HTTP 状态码,而不是连接失败。若返回 blocked by egress audit,说明该域名不在白名单。

3. 阻断测试:

```bash

sudo -u zagent env HTTPS_PROXY=http://127.0.0.1:8080 \

curl -sS https://example.net

```

预期返回 blocked by egress audit

4. 直连测试:

```bash

sudo -u zagent curl -sS --max-time 5 https://example.net

```

预期连接超时或被拒绝,因为 nftables 只允许该用户访问代理端口。

5. 查看代理日志:

```bash

tail -n 5 /var/log/agent-egress/access.jsonl

```

预期看到 JSON 行,包含 hostmethodbody_size 等字段。

6. 查看审计日志:

```bash

sudo ausearch -k agent_exec -ts recent | tail -n 20

sudo ausearch -k agent_git_read -ts recent | tail -n 20

```

预期看到 zagent 执行的命令,以及读取 .git 的记录。

常见报错与解决

1. 报错:curl: (7) Failed to connect to 127.0.0.1 port 8080: Connection refused

原因:代理没有启动,或监听地址/端口不一致。

解决:

```bash

sudo systemctl restart agent-egress-proxy

ss -lntp | grep 8080

```

2. 报错:curl: (60) SSL certificate problem: unable to get local issuer certificate

原因:mitmproxy 要解密 HTTPS,但客户端不信任它的 CA。

解决:把 mitmproxy 的 CA 证书加入对应运行时的信任库。不同语言环境变量不同,例如 CURL_CA_BUNDLENODE_EXTRA_CA_CERTSREQUESTS_CA_BUNDLE。具体路径与导入方式以 mitmproxy 官方文档当前版本为准。

3. 报错:Error: Could not process rule: Operation not permitted

原因:nftables 规则需要 root,或内核模块未加载。

解决:

```bash

sudo nft list ruleset

sudo modprobe nf_tables

```

4. 报错:ausearch: no matches 或审计规则为空

原因:auditd 未运行,规则未加载,或 uid 写错。

解决:

```bash

sudo systemctl enable --now auditd

sudo auditctl -l

AGENT_UID=$(id -u zagent)

sudo auditctl -a always,exit -F arch=b64 -S execve -F uid=$AGENT_UID -k agent_exec

```

5. 报错:Permission denied 读取 /srv/agent-work/project/.git

原因:权限隔离生效,zagent 对完整 .git 没有写权限或没有读权限。

解决:若确实需要读取,使用 ACL 单独授权;更推荐保持只读,把需要修改的内容放到 workspace

后续维护

  • 日志轮转:为 /var/log/agent-egress/*.jsonl 和 auditd 日志配置 logrotate,避免磁盘写满。
  • 白名单更新:编辑 /etc/mitmproxy/egress_audit.py 后重启 agent-egress-proxy,不要把未知域名直接放行。
  • 定期审计:每周查看 ausearch -k agent_exec -ts this-week 和代理 JSONL,重点关注大 body_size、异常域名、非工作时段请求。
  • 升级:mitmproxy、nftables、auditd 的升级方式以官方文档当前版本为准;升级前备份配置。
  • 备份:备份 /etc/mitmproxy//etc/nftables.conf/etc/audit/rules.d//var/log/agent-egress/
  • 监控:把代理做成 systemd 常驻服务并开启 Restart=on-failure,同时监控进程存活、端口监听和日志磁盘占用。

AI 生成本文由 AI 基于公开信息自动生成,仅供参考。