4、应用隔离实战:容器化隔离(Docker/K8s)、应用白名单机制、API网关与流量管控

应用层的横向扩散,说白了就是攻击者拿到一台机器后,通过进程、端口、API 调用去摸隔壁的服务。我见过太多案例——内网被打穿,不是因为防火墙没配好,而是应用之间太「信任」彼此了。今天咱们就聊聊怎么在应用层把路堵死。

4.1 容器化隔离:Docker 与 K8s 的实战姿势

容器不是虚拟机,它共享内核。这意味着一旦内核被突破,隔壁容器就是裸奔的。我个人的习惯是:把容器当进程管,别当机器管。

4.1.1 Docker 层面的微隔离

很多团队上来就 docker run,默认 bridge 网络,所有容器都能互相 ping 通。这其实很危险。我在项目中遇到过,一个 Web 容器被 getshell,攻击者直接 curl 了同宿主机的 Redis 容器——就因为没做网络隔离。

正确的做法是:

  • 自定义网络:每个业务组一个独立的 bridge 网络
  • --link 已废弃:别再用它,改用 network 间的连通性控制
  • iptables 兜底:Docker 的网络规则本质是 iptables,你可以手动加 DROP 规则

实战命令示例:

# 创建两个隔离网络
docker network create --driver bridge net-frontend
docker network create --driver bridge net-backend

# 只让前端容器能访问后端
docker run --network net-frontend --name web-app -d nginx
docker run --network net-backend --name redis-cache -d redis

# 手动建立单向通道
docker network connect net-backend web-app

这样 web-app 能访问 redis-cache,但 redis-cache 无法主动连 web-app。攻击者就算拿下 Web 容器,想反向打 Redis 也得先过网络层。

4.1.2 K8s 环境下的网络策略

K8s 默认所有 Pod 都能通信——这设计初衷是好的,但安全场景下就是灾难。我记得有一次红蓝对抗,蓝队部署了微服务,结果攻击者从一个日志收集 Pod 横向扫遍了整个集群,就是因为没配 NetworkPolicy。

NetworkPolicy 是 K8s 原生的微隔离手段。它的核心逻辑是:没显式允许,就是拒绝。

我的建议: 新集群第一件事就是部署一个默认拒绝所有入站流量的 NetworkPolicy,然后再按需开放。

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-ingress
spec:
  podSelector: {}
  policyTypes:
  - Ingress
---
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-frontend-to-backend
spec:
  podSelector:
    matchLabels:
      app: backend
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: frontend
    ports:
    - protocol: TCP
      port: 8080

这段 YAML 的意思是:所有 Pod 默认拒绝入站,只有打了 app=frontend 标签的 Pod 才能访问 backend 的 8080 端口。嗯,这里要注意——NetworkPolicy 依赖 CNI 插件支持,Calico、Cilium 都行,Flannel 默认不支持。

4.2 应用白名单机制

容器隔离解决的是网络层面的横向,但进程层面的横向呢?攻击者进了容器,能不能执行 wget、curl、bash?这就是白名单要管的事。

4.2.1 可执行文件白名单

我见过最典型的场景:攻击者通过 RCE 上传了一个小工具,然后 chmod +x 跑起来。如果容器里只有 busybox,那他能用的命令就有限。但很多基础镜像装了 python、perl、curl——这些全是横向扩散的利器。

怎么做?

  • Distroless 镜像:Google 出的,里面只有应用和运行时,没有 shell、没有包管理器
  • AppArmor / SELinux:强制限制进程能执行的文件路径
  • Seccomp:限制系统调用,比如禁用 execve、fork 等

避坑指南: 我曾经在客户现场用 AppArmor 限制了一个 Java 容器,结果 JVM 启动时调用了 mprotect 被拦截,直接崩溃。所以白名单一定要先在 staging 环境跑一轮,别直接上生产。

4.2.2 文件系统只读挂载

攻击者想写文件?把根文件系统挂成只读就行。Docker 支持 --read-only 参数,K8s 里可以用 securityContext 设置 readOnlyRootFilesystem: true。

# Docker 启动只读容器
docker run --read-only --tmpfs /tmp --tmpfs /var/run nginx:alpine

这样容器只能写 /tmp 和 /var/run,其他目录全是只读。攻击者就算拿到 shell,想写个 cron 脚本或者 drop 个二进制文件?没门。

4.3 API 网关与流量管控

容器隔离和白名单管的是「能不能连」和「能不能执行」,但 API 层面的横向扩散还得靠网关。你想想看,攻击者如果已经拿到了一个微服务的 JWT Token,他能不能用这个 Token 去调别的微服务?

4.3.1 网关作为唯一入口

我个人的习惯是:所有外部请求必须经过 API 网关,内部服务之间也尽量走网关。这样流量管控点就集中了。

管控维度 说明 常用工具
身份认证 校验 JWT、OAuth2 Token Kong、APISIX
速率限制 防止暴力破解和 DDoS Nginx + lua
路由隔离 不同路径转发到不同后端 Envoy、Traefik
协议校验 只允许 JSON/Protobuf,拒绝二进制 payload 自定义插件

4.3.2 服务网格的流量管控

如果微服务规模大了,API 网关管南北流量还行,东西流量(服务间调用)就力不从心了。这时候我推荐上服务网格,比如 Istio 或 Linkerd。

服务网格的核心是 Sidecar 代理。每个 Pod 旁边跑一个 Envoy,所有进出流量都经过它。你能做的事就多了:

  • mTLS 强制加密:服务间通信自动加密,防止中间人
  • 访问控制:基于 ServiceAccount 的 RBAC,不是你的服务就别想调
  • 熔断与重试:防止一个服务故障后雪崩到其他服务

Istio 访问控制示例:

apiVersion: security.istio.io/v1beta1
kind: AuthorizationPolicy
metadata:
  name: backend-policy
  namespace: default
spec:
  selector:
    matchLabels:
      app: backend
  rules:
  - from:
    - source:
        principals: ["cluster.local/ns/default/sa/frontend-sa"]
    to:
    - operation:
        methods: ["GET"]
        paths: ["/api/v1/data"]

这段策略只允许 frontend-sa 这个 ServiceAccount 发起的 GET 请求访问 /api/v1/data,其他的一律拒绝。攻击者就算偷到了 Token,只要 ServiceAccount 不对,照样 403。

4.4 本章核心逻辑图

下面这张图把应用隔离的三个层次串起来了。你可以看到,从容器网络、到进程白名单、再到 API 管控,每一层都在阻断攻击者的横向路径。

应用隔离三层防御体系 第一层:容器网络隔离 Docker 自定义网络 / K8s NetworkPolicy 阻断 Pod/容器间的非授权通信 默认拒绝 + 按需开放 第二层:应用白名单 Distroless 镜像 / AppArmor / Seccomp 限制可执行文件、系统调用、文件写入 只读根文件系统 + 临时目录白名单 第三层:API 网关与流量管控 Kong / APISIX / Istio 服务网格 mTLS 加密 / 基于 ServiceAccount 的 RBAC / 熔断 南北流量 + 东西流量统一管控 横向扩散路径逐层收窄

这三层不是选一个就行,而是层层递进。容器网络隔离挡住网络扫描,白名单挡住恶意进程,API 管控挡住越权调用。攻击者想横向扩散,得连过三关——说实话,能全过的我还没见过几个。

个人经验: 如果你团队资源有限,优先做第一层和第三层。白名单的维护成本比较高,适合对安全要求极高的场景。我一般建议客户先上 NetworkPolicy + API 网关,跑顺了再加白名单。