安全
概述
OpenPLC 运行时 v4 实施了多层安全防护,以抵御常见漏洞,并确保在工业环境中的安全运行。
TLS/HTTPS
自签名证书
运行时在首次启动时会自动生成自签名的 TLS 证书:
证书文件:
webserver/certOPENPLC.pem-- 证书webserver/keyOPENPLC.pem-- 私钥
证书详情:
- 密钥长度:2048 位 RSA
- 有效期:365 天
- 主题:CN=localhost
- 主题备用名称:localhost、127.0.0.1 以及检测到的 IP 地址
实现代码: webserver/credentials.py
证书生成
证书生成过程包含多项安全校验:
- 主机名校验:防止在主机名字段中进行命令注入
- IP 地址校验:确保 IP 格式有效
- 路径校验:防止证书文件路径中的目录遍历攻击
- 自动续期:检查证书有效性,过期后自动重新生成
关键函数:
python
CertGen.generate_self_signed_cert(cert_file, key_file)
CertGen.is_certificate_valid(cert_file)
使用自定义证书
如需使用自定义证书(例如来自 Let's Encrypt 的证书):
- 用您的证书替换
webserver/certOPENPLC.pem - 用您的私钥替换
webserver/keyOPENPLC.pem - 确保证书包含所有必要的主机名/IP
- 重启运行时
证书链:
若使用证书链,请将证书串联在一起:
bash
cat your_cert.pem intermediate.pem root.pem > certOPENPLC.pem
身份认证
JWT 令牌
运行时使用 JSON Web 令牌(JWT)进行身份认证:
令牌存储:
- 密钥保存在
/var/run/runtime/.env中 - 256 位十六进制密钥(64 字符)
- 首次启动时自动生成
令牌用途:
- WebSocket 调试接口需要 JWT 认证
- 令牌通过 REST API 登录端点获取
- 可通过重新生成密钥来吊销所有令牌
环境变量:
JWT_SECRET_KEY=<64-character-hex-string>
密码安全
用户密码经过多层保护:
- 哈希:使用安全算法对密码进行哈希
- 盐值:每个用户拥有唯一的盐
- 胡椒 :全局 256 位胡椒,保存在
.env文件中 - 数据库 :存储于
/var/run/runtime/restapi.db
环境变量:
PEPPER=<64-character-hex-string>
配置管理
.env 文件在首次启动时自动生成,采用安全默认值:
路径: /var/run/runtime/.env
内容:
SQLALCHEMY_DATABASE_URI=sqlite:////var/run/runtime/restapi.db
JWT_SECRET_KEY=<自动生成>
PEPPER=<自动生成>
权限:
- 文件创建时带有受限权限
- 仅运行时用户可访问
- 不应提交至版本控制系统
实现代码: webserver/config.py
文件上传安全
ZIP 文件校验
上传的 ZIP 文件在解压前会经过全面的安全检查:
路径遍历防护
检查项:
- 无绝对路径(以
/开头) - 无父目录引用(
..) - 无盘符(
:字符) - 解压路径经验证始终位于目标目录内
示例拦截路径:
/etc/passwd
../../../etc/passwd
C:\Windows\System32
大小限制
限制:
- 单个文件最大:10 MB
- 解压后总大小最大:50 MB
- 在解压前即强制执行
目的: 防止资源耗尽和磁盘空间攻击
ZIP 炸弹检测
检查项: 压缩比必须 ≤ 1000:1
示例:
- 压缩后:1 KB
- 解压后:1 MB(比率 1000:1)-- 允许
- 解压后:2 MB(比率 2000:1)-- 拦截
目的: 防止解压炸弹耗尽磁盘空间或内存
扩展名白名单
拦截的扩展名:
.exe-- Windows 可执行文件.dll-- 动态链接库.sh-- Shell 脚本.bat-- 批处理文件.js-- JavaScript 文件.vbs-- VBScript 文件.scr-- 屏幕保护程序(常被用作恶意软件)
目的: 防止执行恶意代码
macOS 元数据移除
移除项:
__MACOSX/目录.DS_Store文件
目的: 清除可能包含敏感信息的多余元数据
实现代码: webserver/plcapp_management.py
安全解压
解压过程还包含额外安全措施:
- 根目录剥离:自动移除单个顶层根文件夹
- 路径规范化:将所有路径转换为绝对路径并验证合法性
- 目录创建:安全地创建必要的子目录
- 原子操作:解压过程要么全部成功,要么全部回滚
进程安全
特权要求
运行时的某些操作需要提升权限:
- 实时调度:设置 SCHED_FIFO 优先级
- 套接字创建 :在
/run/runtime/中创建 Unix 域套接字 - 端口绑定:绑定至 8443 端口(特权端口)
建议: 使用 sudo 运行,或授予特定能力(capabilities):
bash
sudo setcap cap_sys_nice,cap_net_bind_service=+ep build/plc_main
进程隔离
独立进程:
- Web 服务器作为 Python 进程运行
- PLC 运行时作为独立的 C/C++ 进程运行
- 仅通过 Unix 域套接字通信
优势:
- 一个进程崩溃不会影响另一个进程
- 可实现不同级别的权限
- 内存隔离
信号处理
运行时能够优雅地处理信号:
- SIGINT:优雅关闭,清理资源
- SIGTERM:优雅关闭
- SIGSEGV:捕获并记录日志(如可能)
实现代码: core/src/plc_app/plc_main.c
网络安全
端口暴露
默认端口:
- 8443 (HTTPS) -- OpenPLC 编辑器通信的 REST API
建议:
- 使用防火墙限制访问
- 仅暴露给可信网络
- 远程访问可考虑使用 VPN
Docker 端口映射:
bash
docker run -p 127.0.0.1:8443:8443 ... # 仅本地回环
docker run -p 8443:8443 ... # 所有接口
Unix 域套接字
套接字位置:
/run/runtime/plc_runtime.socket-- 命令套接字/run/runtime/log_runtime.socket-- 日志套接字
安全性:
- 仅本地系统可访问
- 文件系统权限控制访问
- 不暴露至网络
权限:
- 创建时带有受限权限
- 仅运行时用户可连接
数据安全
数据库
路径: /var/run/runtime/restapi.db
内容:
- 用户账户
- 哈希密码
- 会话数据
保护措施:
- 文件系统权限
- SQLite 加密(如配置)
- 建议定期备份
日志
敏感信息:
- 日志可能包含变量值
- IP 地址及连接信息
- 带有文件路径的错误信息
建议:
- 定期轮转日志
- 限制日志文件访问权限
- 共享前对日志进行脱敏处理
编译后程序
路径: build/libplc_*.so
内容:
- 编译后的 PLC 逻辑
- 变量定义
- 自定义功能块
保护措施:
- 文件系统权限
- 不通过网络传输
- 带时间戳以进行版本控制
Docker 安全
容器隔离
优势:
- 与宿主机进程隔离
- 网络隔离(除非显式暴露)
- 文件系统隔离
注意事项:
- 实时调度可能需要特权模式
- 挂载卷会暴露宿主机目录
- 端口暴露会创建网络访问入口
卷安全
持久化卷:
bash
docker run -v openplc-runtime-data:/var/run/runtime ...
内容:
- 含机密的
.env文件 - 含用户账户的数据库
- 编译后的程序
建议:
- 使用命名卷(而非绑定挂载)
- 定期备份卷
- 限制卷的访问权限
镜像安全
官方镜像: ghcr.io/autonomy-logic/openplc-runtime:latest
安全特性:
- 基于 Debian bookworm-slim(最小攻击面)
- 通过 CI/CD 定期更新
- 多架构支持
- 签名镜像(GitHub 容器仓库)
验证方法:
bash
docker pull ghcr.io/autonomy-logic/openplc-runtime:latest
docker inspect ghcr.io/autonomy-logic/openplc-runtime:latest
安全最佳实践
部署
- 仅使用 HTTPS:切勿禁用 TLS
- 强密码:强制密码复杂度
- 定期更新:保持运行时及依赖项为最新
- 防火墙规则:限制网络访问
- 监控:监控日志以发现可疑活动
开发
- 代码审查:合并前审查所有变更
- 静态分析:使用 linter 和安全扫描工具
- 依赖项扫描:检查是否存在漏洞依赖
- 输入校验:验证所有用户输入
- 错误处理:错误信息中不暴露敏感信息
运维
- 定期备份 :备份
/var/run/runtime/目录 - 轮换密钥:定期重新生成 JWT 密钥和胡椒
- 审计日志:检查日志中的安全事件
- 更新证书:在证书过期前续期
- 最小权限原则:以所需的最低权限运行
漏洞报告
若发现安全漏洞:
- 请勿 公开提交 issue
- 私下联系维护者
- 提供详细的重现步骤
- 留出补丁开发时间
- 协调披露时间
安全局限性
已知限制
- 自签名证书:默认证书为自签名(OpenPLC 编辑器可自动处理)
- 无速率限制:API 端点未限制请求频率
- 无账户锁定:未提供暴力破解防护
- 无审计追踪:安全事件日志记录有限
- 无静态加密:数据库和文件未加密
未来改进
计划中的安全增强功能:
- API 端点速率限制
- 失败尝试后的账户锁定
- 全面的审计日志
- 数据库静态加密
- 证书管理界面
- 双因素认证
- 基于角色的访问控制
合规性考虑
工业标准
运行时专为工业自动化设计,但未声称符合特定标准(如 IEC 62443)。各组织应:
- 进行安全评估
- 根据需要实施额外控制措施
- 遵循行业特定指南
- 记录安全配置
数据保护
对于有数据保护要求的环境(GDPR 等):
- 最小化数据收集
- 实施数据保留策略
- 提供数据导出功能
- 记录数据流
- 实施访问控制