早上八点,咖啡刚泡好,运维小李就收到告警——生产环境一个容器实例正在对外发起异常连接。排查发现,攻击者通过暴露在公网的API端点侵入,利用未打补丁的应用漏洞拿到了shell。更糟的是,这个容器属于一个本该隔离的内部服务。
端点不只是“出口”
很多人以为,只要把容器编排好、镜像扫描过,安全就搞定了。可现实是,再严密的防线,也可能被一个没保护好的端点击穿。端点(Endpoint)不是简单的网络出口,它是容器与外界通信的唯一通道,也是攻击者最常盯上的突破口。
比如,一个电商后台的微服务容器,如果它的管理接口(如 /actuator/health)直接暴露在公网且未鉴权,黑客就能通过它探测系统结构,甚至触发远程代码执行。这就像你家防盗门装了指纹锁,却忘了关厨房窗户。
常见风险藏在细节里
最常见的问题之一是“过度暴露”。开发为了调试方便,在Dockerfile里用了 EXPOSE 8080,又在Kubernetes Service中设为 NodePort,结果整个内网服务成了公网靶子。
apiVersion: v1
kind: Service
metadata:
name: risky-service
spec:
type: NodePort <!-- 默认开放30000-32767端口到所有节点 -->
ports:
- port: 80
targetPort: 8080
selector:
app: backend
另一个问题是TLS配置缺失。很多团队在内部通信时用明文传输,一旦网络被监听,敏感数据如令牌、用户信息就会裸奔。别忘了,容器网络本质上是虚拟的,同一宿主机上的容器通信也可能被同节点的恶意容器嗅探。
从“默认开放”到“默认封锁”
安全策略得反着来想:不是“哪些要放开”,而是“哪些能保留”。Kubernetes NetworkPolicy 就是干这个的。比如,只允许前端容器访问后端API的特定端口:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: api-allow-only-from-web
spec:
podSelector:
matchLabels:
app: api-backend
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: web-frontend
ports:
- protocol: TCP
port: 8000
这样,即使攻击者进入某个非前端容器,也无法直接连到API服务。
运行时防护不能少
静态策略拦得住已知风险,拦不住零日攻击。运行时行为监控得跟上。比如用eBPF技术跟踪容器的系统调用,一旦发现某个容器突然开始读取 /etc/shadow 或执行 shell,立刻告警或阻断。
有些团队还会在容器内部署轻量探针,监控网络连接、文件修改和进程启动。虽然多了点开销,但比起被挖矿或者数据泄露,这点性能代价不值一提。
别让配置成为摆设
再好的工具,配错了也白搭。比如Ingress Controller启用了HTTPS,但没强制重定向HTTP,用户还是可能通过明文访问。或者证书用了自签,客户端不做校验,中间人攻击轻松得手。
还有些人图省事,把所有容器都挂同一个ServiceAccount,权限粒度粗得像筛子。一旦某个低危服务被突破,攻击者就能顺着权限升级,横扫整个集群。
端点安全不是加个防火墙就完事。它得贯穿构建、部署、运行全过程。每次上线前问一句:这个容器到底需要对外暴露什么?谁能访问它?有没有最小权限?这些问题看似琐碎,却是防住大多数攻击的关键。