敬请指正

才疏学浅,若有不对之处烦请指正

前言

公司电脑预装了 360 终端安全管理系统,其中的 DLP(数据防泄漏)模块会监控 Windows 进程的外发行为。而访问公司内网需要安装 aTrust(零信任安全接入网关,功能类似 VPN),结果就是想往 GitHub 拉或推个代码,直接弹窗”禁止外发”。

奇怪的是,360 一直都在,之前没装 aTrust 的时候 git pull/push 完全正常。装了 aTrust 之后才开始拦截,而且卸载 aTrust 后问题依旧。研究了一下发现:360 的 DLP 策略是由公司后台统一下发的,aTrust 连接公司网络时会触发策略同步,把最新的 DLP 拦截规则推送到本机的 360 上。一旦规则落地,就跟 aTrust 本身没关系了——360 独立执行拦截,卸载 aTrust 不会清除已下发的策略。

最恶心的是,这个 DLP 模块有内核级自我保护:管理员权限杀不掉进程、卸载需要密码、禁用启动项后重启照样跑。常规手段根本搞不定。

最终方案

重装系统 + Docker 内启动 aTrust。重装后不再安装本机 aTrust 客户端,不加域(防止域策略自动推送 360 DLP 规则)。公司内网访问全部通过 Docker 容器内的 aTrust 代理解决——容器内的 DLP 只能监控容器内部,管不到宿主机。GitHub 推送走宿主机直连,互不干扰。

参考链接

1. 环境

环境信息
  • 操作系统:Windows 10 专业版 (Build 19045)
  • 公司 VPN:深信服 aTrust(零信任安全接入网关)
  • 终端管控:360 终端安全管理系统(公司系统预装,重装系统后仍存在)
  • 拦截对象:Windows 上的 git.exe 进程的所有外发操作
  • 影响范围:所有往外部仓库(GitHub、GitLab 等非公司地址)的 push 操作

2. 排查过程

2.1 第一反应:走代理绕过?

既然 DLP 拦的是网络外发,那让 git 走加密代理出去,DLP 是不是就识别不到目标了?

1
2
git config --global http.https://github.com.proxy socks5://127.0.0.1:7890
git config --global https.https://github.com.proxy socks5://127.0.0.1:7890

结果:照样拦截。太天真了😅

排除

DLP 不是通过监控网络目标来判断的,而是进程级监控——直接盯着 git.exe 这个进程,不管你流量走哪条路、加不加密,只要是 git.exe 发起的外发操作,一律拦截。

2.2 第二反应:杀掉 DLP 进程?

既然你监控我,那我把你干掉你了不就行了?

1
2
3
tasklist | findstr /i "sangfor aTrust"
# aTrustAgent.exe 5628 Services 0 23,012 K
# aTrustAgent.exe 14168 Console 1 90,728 K

尝试管理员权限强杀:

1
2
taskkill /F /IM aTrustAgent.exe
# 错误: 无法终止进程 "aTrustAgent.exe",其 PID 为 5628。原因: 拒绝访问。
排除

连管理员都杀不掉,有内核级自我保护。好好好,这么玩是吧🙃

2.3 第三反应:卸载 aTrust?

杀不掉那我卸载总行了吧?

控制面板卸载 → 弹出”请输入卸载密码”。什么密码?装的时候也没设密码啊!需要联系管理员获取——算了算了。

用 Geek Uninstaller 强删文件 → 重启后进程照样跑。

排除

360 终端安全管理系统注册了内核驱动,删文件不影响已加载的驱动,重启后自动恢复。真没招了

2.4 关键发现:WSL 里的 git 不受监控

换个思路——既然 Windows 上的 git.exe 被进程级监控,那 WSL 里的 Linux 版 git 呢?毕竟那是 Linux 进程,360 你管得着吗?

1
wsl -d Ubuntu -- bash -c "cd /mnt/d/MyCode/JuneBlog && git push"

结果:推送成功!360 没有拦截! 🎉

确认

360 DLP 只监控 Windows 进程,WSL 内部的 Linux 进程不在其监控范围内。

这验证了一个关键假设:只要操作不在 Windows 宿主机的进程空间里执行,DLP 就管不到。Docker 容器同理—。

3. 方案设计

3.1 核心思路

3.2 流量路径

操作 路径
git push GitHub 宿主机 git → Clash → 外网(DLP 管不到)
git pull git.company.com 宿主机 git → Clash → 容器 aTrust 代理 → 公司内网
浏览器访问公司内网 浏览器 → Clash → 容器 aTrust 代理 → 公司内网
浏览器访问外网 浏览器 → Clash → 正常代理规则

4. 实施步骤

4.1 前置条件

  • Docker Desktop 已安装并运行
  • Clash Verge 已安装,规则模式,允许局域网连接(Allow LAN)开启,端口 7890

4.2 启动 aTrust 容器

1
2
3
4
5
6
7
8
9
10
11
docker run --rm -d --device /dev/net/tun --cap-add NET_ADMIN ^
-e PASSWORD=123456 -e URLWIN=1 ^
-v ecdata:/root ^
-p 127.0.0.1:5901:5901 ^
-p 127.0.0.1:1080:1080 ^
-p 127.0.0.1:8888:8888 ^
-e HTTP_PROXY=http://host.docker.internal:7890 ^
-e HTTPS_PROXY=http://host.docker.internal:7890 ^
-e ALL_PROXY=socks5://host.docker.internal:7890 ^
--sysctl net.ipv4.conf.default.route_localnet=1 ^
hagb/docker-atrust

参数说明:

参数 作用
-d 后台运行
--device /dev/net/tun VPN 隧道需要 TUN 设备
--cap-add NET_ADMIN 网络管理权限
-v ecdata:/root 持久化 aTrust 登录数据
-p 127.0.0.1:1080:1080 暴露 socks5 代理
-p 127.0.0.1:5901:5901 VNC 端口(登录用)
HTTP_PROXY 让容器通过宿主机 Clash 出网
host.docker.internal Docker Desktop 中容器访问宿主机的特殊域名

4.3 VNC 登录 aTrust

  1. RealVNC Viewer 连接 127.0.0.1:5901,密码 123456
  2. 在 VNC 界面中登录 aTrust(公司 VPN 账号密码)
  3. 看到 “Online Connected” 后关闭 VNC,容器后台继续运行

4.4 配置 Clash 全局扩展脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
function main(config) {
// 1. DNS 配置:公司域名走公司内网 DNS
if (!config.dns) config.dns = {};
if (!config.dns['nameserver-policy']) config.dns['nameserver-policy'] = {};
config.dns['nameserver-policy']['+.company.com'] = '10.0.0.1';
config.dns['nameserver-policy']['domain-keyword:company'] = '10.0.0.1';

// 2. 初始化
if (!config.rules) config.rules = [];
if (!config.proxies) config.proxies = [];

// 3. aTrust 代理节点(Docker 容器暴露的 socks5)
const atrust = { name: "aTrust", type: "socks5", server: "127.0.0.1", port: 1080 };
if (!config.proxies.some(p => p.name === "aTrust")) {
config.proxies.unshift(atrust);
}

// 4. 路由规则(后 unshift 的排在前面,优先级更高)
config.rules.unshift("DOMAIN-KEYWORD,other-direct-domain,DIRECT");
config.rules.unshift("IP-CIDR,172.18.0.0/16,DIRECT");

// 公司域名走容器 aTrust 代理
config.rules.unshift("DOMAIN-KEYWORD,company,aTrust");

// VPN 服务器地址必须直连(防回环:容器自己连 VPN 服务器用)
config.rules.unshift("DOMAIN,atrust.company.com,DIRECT");

return config;
}
防回环说明

atrust.company.com(VPN 服务器地址)必须走 DIRECT。如果它也走 aTrust 代理,就会形成死循环:容器要连 VPN 服务器 → 流量被 Clash 转到容器自己的代理 → 代理还没建立 → 永远连不上。

4.5 配置 Git 代理

1
2
3
4
# 公司仓库走容器 aTrust 代理
git config --global http.https://git.company.com/.proxy socks5://127.0.0.1:1080

# GitHub 不配代理,直连

5. 踩坑记录

5.1 360 DLP 杀不掉也卸不掉(最终只能重装系统)

试了所有能想到的办法,全部失败:

  • taskkill /F → 拒绝访问(内核级保护)
  • 卸载 → 需要密码(我又不是管理员)
  • Geek Uninstaller 强删文件 → 重启后进程照样跑
  • 禁用启动项 → 无效,服务级自启
  • 安全模式下删除 → 内核驱动已加载,文件被锁定
  • 注册表清理 → 驱动注册项有 ACL 保护,改不了
结论

所有常规手段均无效,最终只能重装系统。 360 终端安全管理系统的内核驱动有完整的自我保护链:进程保护 + 文件保护 + 注册表保护 + 服务自恢复。除非拿到管理员下发的卸载密码,否则在 Windows 运行状态下无法移除。有亿点流氓啊😭

解决方案

重装系统,不装 aTrust 客户端,不加域。 重装后公司内网访问通过 Docker 容器里的 aTrust 代理解决。如果公司通过域策略自动推送这些软件,就不加域。

5.2 Docker Desktop 安装报 “Server service” 未启用

安装 Docker Desktop 4.72.0 时弹窗:Installation failed. One prerequisite is not fulfilled. Docker Desktop requires the Server service to be enabled.

解决方案

Windows 的 LanmanServer 服务被禁用了(可能是精简系统时关掉的)。在管理员 PowerShell 中执行:

1
2
3
# 注意:PowerShell 里 sc 是 Set-Content 的别名,必须用 sc.exe
sc.exe config LanmanServer start= auto
net start LanmanServer

启用后重新运行安装程序即可通过。

5.3 Docker Desktop 启动报 “WSL needs updating”

Docker Desktop 安装成功后首次启动,提示 WSL 版本过旧。

解决方案
1
wsl --update

如果网络拉不下来:

1
wsl --update --web-download

更新完在 Docker Desktop 界面点 Try Again,等左下角变成 “Engine running” 即可。

5.4 Clash Verge 局域网连接未开启

容器启动后连不上宿主机 Clash,host.docker.internal:7890 拒绝连接。

解决方案

确认 Clash Verge 的局域网连接(Allow LAN)已开启,否则容器通过 host.docker.internal 访问不到 Clash。

5.5 WSL 里 git push 报代理连接失败

Windows git 配置了 proxy=socks5://127.0.0.1:7890,WSL 里的 git 继承了这个配置,但 WSL 内部 127.0.0.1 指向的是 WSL 自己,不是 Windows 宿主机。

解决方案

推送时临时清除代理:

1
git -c http.proxy="" -c https.proxy="" push

或者配置 WSL 的 git 代理指向宿主机 IP(通过 /etc/resolv.conf 中的 nameserver 地址)。

5.6 git clone 公司仓库报 SSL_ERROR_SYSCALL

容器代理正常(curl -x socks5://127.0.0.1:1080 能访问公司 GitLab),但 git clone 报错:

1
2
unable to access 'https://git.company.com/xxx/xxx.git/':
OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to git.company.com:443

原因:流量经过容器 aTrust VPN 代理后,公司网关可能对 HTTPS 做了 SSL inspection(证书替换),git 的 OpenSSL 不信任被替换的证书,SSL 握手失败。

解决方案

针对公司仓库关闭 SSL 验证(不影响 GitHub 等其他仓库):

1
git config --global http.https://git.company.com/.sslVerify false

6. 备用方案:WSL 里操作 git

如果重装系统后 360 又被推送回来(域策略自动部署),Windows 的 git.exe 往非公司地址推送还是会被拦(公司仓库的操作不受影响,DLP 只拦外发)。这时候用 WSL 里的 git 来推 GitHub,360 管不到 Linux 进程:

1
2
3
4
5
6
7
8
9
# 安装 Ubuntu
wsl --install -d Ubuntu
wsl --set-default Ubuntu

# 配置凭据(复用 Windows 的 Git Credential Manager)
wsl -d Ubuntu -- bash -c "git config --global credential.helper '/mnt/c/Program\ Files/Git/mingw64/bin/git-credential-manager.exe'"

# 安全目录(WSL 访问 Windows 文件系统会触发 ownership 检查)
wsl -d Ubuntu -- bash -c "git config --global --add safe.directory '*'"

日常使用:

1
2
# 推送 GitHub(WSL 里的 git 不受 DLP 监控)
cd /mnt/d/MyCode/JuneBlog && git push
提示

这个方案只需要在推/拉外部仓库时手动切到 WSL 操作,公司仓库的日常开发继续用 Windows 的 git 和 IDE 即可,不受影响。

7. 总结

根因链

1
2
3
4
5
6
7
8
9
公司部署 aTrust + 360 终端安全管理系统
↓ 360 DLP 模块进程级监控 Windows 上的 git.exe
↓ 任何往非公司地址的 git 操作被拦截
↓ DLP 有内核级保护,杀不掉、卸不掉
↓ 最终重装系统,不装 aTrust、不加域
↓ 公司内网访问:将 aTrust 隔离到 Docker 容器
↓ 容器暴露 socks5 代理,Clash 按域名分流
↓ 宿主机 git push GitHub 直连,不经过任何 DLP
↓ 公司仓库通过 Clash → 容器代理 → VPN 隧道访问

经验教训

  1. 企业 DLP 是进程级监控,不是网络级。走代理、改 DNS、加密隧道都绕不过,只有让操作发生在 DLP 监控范围之外(容器/WSL)才行。
  2. Docker 容器是天然的隔离沙箱。不仅隔离了文件系统和网络,也隔离了终端管控软件的监控范围。
  3. Clash 分流 + 容器代理是一个通用模式。任何需要”部分流量走 VPN、部分流量不走”的场景都可以用这个架构。
  4. 防回环是关键。VPN 服务器地址必须走 DIRECT,否则容器永远连不上 VPN。
一句话总结

管不了 DLP,就把 VPN 关进笼子里🐳——容器内连公司网,容器外自由呼吸。