在流程工业和电力、水务等关键基础设施中,SCADA系统传统上运行在独立、隔离的控制网络上。随着边缘计算和敏捷运维的推进,不少企业开始把SCADA上位机、实时数据库、协议网关等组件迁移到容器平台。容器化带来了快速部署和资源利用率提升,但也把原本封闭的OT环境暴露在镜像仓库、容器运行时和编排API等新的攻击面上。攻击者不需要直接接触PLC或RTU,只要攻破一个镜像构建环节或利用编排接口的配置缺陷,就可能干扰数据采集甚至下发错误控制指令。

因此,容器化SCADA的加固不能照搬传统IT容器的做法,必须围绕实时性、可用性和控制安全三个维度重新设计纵深防御。
一、容器化SCADA面临的主要威胁模型
SCADA容器化之后,安全边界从控制网络扩展到了容器供应链。镜像仓库可能成为攻击入口。很多团队为了方便,直接使用公共基础镜像或者内部仓库中未经过扫描的历史镜像。攻击者可以通过镜像投毒的方式植入后门,例如在一个看似正常的Modbus网关镜像里加入定时反弹shell的脚本。一旦该镜像被部署到SCADA节点,攻击者就能在OT网络内部建立持久化据点。
运行时威胁同样严重。容器与宿主机共享内核,容器逃逸漏洞、错误的能力授予、挂载宿主机敏感目录等配置失误都可能让攻击者突破隔离。SCADA系统对延迟极为敏感,拒绝服务攻击或资源耗尽会直接导致数据刷新中断,影响操作员对现场状态的判断。编排层如果暴露在办公网络或互联网,未授权访问Kubernetes API等同于拿到整个集群的控制权,攻击者可以删除关键Pod、窃取Secret或创建恶意工作负载。
此外,SCADA协议本身在设计之初缺乏认证和加密,例如Modbus TCP、DNP3和IEC 60870-5-104通常以明文传输。容器网络如果缺少分段,攻击者从IT侧横向移动后可以直接嗅探或篡改控制报文。
二、镜像与供应链安全加固
加固的第一步是收紧镜像构建流程。基础镜像应选择发行版维护的精简版本,而不是携带大量工具和库的通用镜像。对于SCADA组件,建议使用多阶段构建,在构建阶段安装编译器或依赖,在运行阶段只复制最终二进制文件和必要配置。这样可以显著减小攻击面,也降低漏洞扫描的噪音。
下面是一个针对Modbus协议网关的多阶段Dockerfile示例:
# 构建阶段 FROM golang:1.22 AS builder WORKDIR /src COPY . . RUN CGO_ENABLED=0 go build -o modbus-gateway ./cmd/gateway # 运行阶段 FROM alpine:3.20 RUN apk add --no-cache ca-certificates && addgroup -S scada && adduser -S -G scada scada COPY --from=builder /src/modbus-gateway /usr/local/bin/modbus-gateway USER scada ENTRYPOINT ["/usr/local/bin/modbus-gateway"]
注意上面示例中的&&在真实Dockerfile里是连续命令连接符,这里为了在HTML中正确显示进行了转义。镜像构建完成后,应在CI流水线中运行漏洞扫描工具,例如Trivy或Grype,只允许通过扫描且无高危漏洞的镜像进入生产仓库。同时使用Sigstore的cosign对镜像进行签名,部署时通过准入控制器验证签名,防止供应链中被替换。
私有镜像仓库需要启用认证和基于角色的访问控制,禁止匿名拉取。推送镜像时使用单独的CI服务账号,开发人员和SCADA工程师不直接持有生产仓库写权限。定期清理旧镜像,避免漏洞累积。
三、运行时与主机层防护
运行时防护的目标是限制容器行为,确保即使单个组件被攻破,攻击者也难以逃逸或影响宿主机。所有SCADA容器应默认使用非root用户运行,并设置只读根文件系统,只有必要的临时目录挂载为可写。Docker运行命令可以加上--read-only和--tmpfs /tmp:rw,noexec,nosuid,size=64m参数。Kubernetes中则在Pod的securityContext里声明:
apiVersion: v1
kind: Pod
metadata:
name: scada-hmi
spec:
securityContext:
runAsNonRoot: true
runAsUser: 10001
fsGroup: 10001
seccompProfile:
type: RuntimeDefault
containers:
- name: hmi
image: registry.internal/scada-hmi:1.4.2
securityContext:
readOnlyRootFilesystem: true
allowPrivilegeEscalation: false
capabilities:
drop:
- ALL
volumeMounts:
- name: tmp
mountPath: /tmp
volumes:
- name: tmp
emptyDir:
medium: Memory
sizeLimit: 64Mi
上面的seccompProfile使用运行时默认的seccomp规则,可以拦截大部分高危系统调用。如果宿主机使用AppArmor或SELinux,应当为SCADA容器编写专门的策略文件,只允许网络、文件和少量进程控制相关的操作。内核能力方面,必须删除全部默认能力后再按需添加,例如NET_BIND_SERVICE用于绑定特权端口,但绝不能授予SYS_ADMIN、NET_ADMIN或CAP_SYS_PTRACE。特权容器在SCADA环境中应被完全禁止。
主机层还需要加固容器引擎和编排组件。Docker守护进程不应监听TCP端口,除非通过TLS双向认证。Kubernetes的API Server应启用RBAC、NodeRestriction和PodSecurity准入控制器。PodSecurityPolicy在较新版本中已被Pod Security Admission替代,但作用相同:阻止hostPID、hostNetwork、privileged等高风险字段。对于仍运行旧版本的集群,可以通过OPA Gatekeeper或Kyverno编写约束策略。
资源限制同样重要。应为每个SCADA容器设置CPU和内存的request与limit,防止单个组件因内存泄漏或异常流量拖垮整个节点。实时性要求高的采集服务可以使用cpuManagerPolicy=static和CPU独占保证调度延迟。
四、网络隔离与访问控制
容器网络不能沿袭传统OT网络的扁平结构。应根据SCADA功能划分不同的网络段:现场采集层、实时数据库层、HMI发布层和运维管理层。Kubernetes的NetworkPolicy可以在Pod之间实现白名单式访问。例如只允许HMI Pod访问实时数据库的1433端口,不允许其他任何Pod主动连接该数据库:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: db-access
spec:
podSelector:
matchLabels:
app: realtime-db
policyTypes:
- Ingress
ingress:
- from:
- podSelector:
matchLabels:
app: scada-hmi
ports:
- protocol: TCP
port: 1433
对于Modbus、DNP3等工业协议,网络策略只能限制IP和端口,无法理解协议内容。建议在关键路径上部署支持工业协议深度检测的防火墙或IDS,识别异常的功能码、寄存器地址和写入频率。容器化的协议网关还应禁用所有非必要的管理端口,例如SSH和Web控制台,只暴露协议服务本身。
访问控制要覆盖两个层面:人对系统的访问和容器对资源的访问。Kubernetes RBAC应遵循最小权限,SCADA工程师只允许登录和查看Pod状态,不允许创建或删除资源。审计日志必须记录所有对API的操作,尤其是创建exec会话、修改ConfigMap或Secret的请求。可以与企业的Active Directory或LDAP集成,使用OIDC进行身份认证,避免使用静态token。
五、审计、合规与持续监控
安全加固不是一次性的配置工作,需要持续验证。部署完成后,应建立容器运行时的行为基线。Falco可以监控异常的系统调用和容器行为,例如一个数据库容器突然执行了shell、一个HMI容器尝试挂载宿主机目录。规则可以对接SIEM,将告警推送到安全运营中心。以下是一个简单的Falco规则思路,检测容器内执行sh的行为:
- rule: Unexpected shell in SCADA container desc: Detect shell spawned in a SCADA workload condition: spawned_process and container.image.repository startswith "scada" and proc.name = "sh" output: "Shell spawned in SCADA container (user=%user.name command=%proc.cmdline)" priority: WARNING tags: [scada, runtime]
实际部署时可以将Falco规则放宽或收紧,避免因为正常的健康检查产生大量误报。日志方面,所有容器和编排组件的日志应集中收集,并设置保留周期。对于SCADA操作事件,例如工程师修改了某个控制参数,需要同时记录容器审计日志和应用层日志,形成完整证据链。
合规层面可以参考IEC 62443系列标准。IEC 62443-3-3定义了区域和管道模型,容器化SCADA可以映射为多个区域,例如控制中心区域、边缘采集区域和远程维护区域,每个区域之间通过受控管道通信。加固措施需要定期接受评估,包括镜像扫描报告、运行时策略合规率、RBAC权限复核和渗透测试结果。自动化可以借助OpenSCAP、kube-bench等工具,将基线检查集成到定期任务中,确保配置漂移被及时发现。
最后,团队需要建立针对容器化SCADA的应急响应流程。当检测到容器逃逸或供应链投毒时,应能快速隔离受影响节点、回滚镜像版本,并通过带外管理通道恢复现场控制。容器化虽然增加了复杂度,但只要在镜像、运行时、网络和审计四个层面持续投入,就能在享受敏捷交付的同时维持工业控制系统应有的安全等级。