3、OPC UA安全策略配置:安全策略选择、消息签名与加密、用户认证模式
好,咱们进入第三章。说实话,安全策略配置这块,是很多OPC UA项目里最容易出问题的地方。我见过不少项目,安全策略配得乱七八糟,要么是根本连不上,要么是裸奔上阵。今天咱们就把这事儿掰扯清楚。
3.1 安全策略选择:Basic256Sha256 为什么是首选?
OPC UA 规范里定义了好几种安全策略,但实际项目中常用的就那么几个。我列个表,你一看就明白。
| 安全策略 | 对称加密算法 | 签名算法 | 密钥长度 | 推荐场景 |
|---|---|---|---|---|
| None | 无 | 无 | N/A | 仅测试环境 |
| Basic128Rsa15 | AES-128 | RSA-SHA1 | 128位 | 遗留系统兼容 |
| Basic256 | AES-256 | RSA-SHA1 | 256位 | 已不推荐 |
| Basic256Sha256 | AES-256 | RSA-SHA256 | 256位 | 生产环境首选 |
| Aes128Sha256RsaOaep | AES-128 | RSA-SHA256 | 128位 | 新项目可选 |
| Aes256Sha256RsaPss | AES-256 | RSA-PSS | 256位 | 最高安全要求 |
我个人习惯,只要不是跟十年前的旧设备对接,一律选 Basic256Sha256。为什么?
- 算法够硬:AES-256 加密,RSA-SHA256 签名,目前没有已知的有效攻击。
- 兼容性好:几乎所有现代 OPC UA SDK 都支持,不像 Aes256Sha256RsaPss 那样挑版本。
- 性能可接受:在工业控制器上,256位对称加密的开销完全扛得住。
3.2 消息签名与加密:到底签什么?加密什么?
很多初学者搞不清楚签名和加密的区别。说白了,签名是防篡改,加密是防偷看。OPC UA 里这两件事是分开配置的。
OPC UA 的消息安全模式有三种:
- Sign:只签名,不加密。消息内容是明文的,但能检测是否被篡改。
- SignAndEncrypt:先签名,再加密。既防篡改又防偷看。
- None:裸奔,啥也不做。
你想想看,在工业现场,控制指令要是被人篡改了,后果有多严重?所以我的建议是:
- 数据采集场景(读变量、读历史数据):可以用 Sign,性能开销小一些。
- 控制指令场景(写变量、调用方法):必须用 SignAndEncrypt。
- 配置变更场景(修改服务器参数):同样必须用 SignAndEncrypt。
核心原则:能加密就加密,能签名就签名。别为了省那点CPU占用,把整个产线暴露在风险里。
3.3 用户认证模式:匿名?用户名?证书?
OPC UA 的用户认证,说白了就是「你是谁」的问题。常见的有三种模式:
| 认证模式 | 安全等级 | 适用场景 | 管理成本 |
|---|---|---|---|
| Anonymous | 低 | 只读数据展示、内部调试 | 无 |
| UserName/Password | 中 | 操作员站、HMI | 低 |
| X.509 Certificate | 高 | 服务器间通信、关键控制 | 高 |
嗯,这里要注意一点:匿名不等于不安全。如果你把匿名用户限制为只读权限,配合 SignAndEncrypt 的消息安全模式,其实也能达到不错的安全水平。但如果你让匿名用户能写变量,那就是在给自己挖坑。
用户名密码模式,我建议配合 HTTPS 或 TLS 传输层加密一起用,否则密码在网络上就是明文传输的。我记得有个客户,他们的 OPC UA 服务器跑在办公网里,用的就是用户名密码模式,但没有启用传输层加密。结果 IT 部门做渗透测试时,直接抓包拿到了管理员密码。
证书认证是最安全的,但管理起来也最麻烦。你需要:
- 搭建 CA(证书颁发机构)
- 为每个客户端和服务器签发证书
- 管理证书吊销列表(CRL)
- 定期轮换证书
3.4 安全策略配置实战:代码示例
下面给一个 C# 的配置示例,用的是 OPC Foundation 的官方 SDK。这段代码我实际项目里改过很多次,基本能直接复用。
// 创建客户端配置
var clientConfig = new ApplicationConfiguration
{
ApplicationName = "MyOPCUAClient",
ApplicationType = ApplicationType.Client,
SecurityConfiguration = new SecurityConfiguration
{
// 安全策略:Basic256Sha256
SelectedSecurityPolicies = new List<string>
{
SecurityPolicies.Basic256Sha256
},
// 消息安全模式:签名+加密
SelectedMessageSecurityModes = new List<MessageSecurityMode>
{
MessageSecurityMode.SignAndEncrypt
},
// 用户认证:用户名密码
UserIdentityTokenPolicies = new List<UserTokenPolicy>
{
new UserTokenPolicy(UserTokenType.UserName)
},
// 证书验证选项(生产环境要严格)
CertificateValidator = new CertificateValidator
{
CertificateValidationOptions = CertificateValidationOptions.SuppressCertificateExpired |
CertificateValidationOptions.SuppressCertificateChainNotComplete
}
}
};
// 创建会话
var session = await Session.Create(
clientConfig,
new ConfiguredEndpoint(null, new Uri("opc.tcp://192.168.1.100:4840")),
new UserIdentity(new UserNameIdentityToken("admin", "P@ssw0rd")),
true);
3.5 安全策略组合决策树
为了让你更直观地理解怎么选,我画了一张决策图。你可以把它贴在工位上,每次配置新设备时对照着看。
这张图的核心逻辑很简单:先看通信类型,再选安全策略,最后定用户认证。别跳步骤,也别为了省事选低安全等级。
3.6 常见配置错误与排查
最后,我总结几个我踩过的坑,你遇到了可以直接对照排查:
- 客户端和服务器安全策略不匹配:两边必须选同一个策略,否则握手失败。检查 Server 端支持的策略列表,客户端只选其中一个。
- 证书信任链没建立:客户端证书没导入服务器的信任列表,反过来也一样。检查两边的 CertificateStore。
- 用户认证凭据错误:用户名密码不对,或者证书私钥没权限访问。这个最基础,但也最容易忽略。
- 消息安全模式不一致:客户端设了 SignAndEncrypt,服务器只支持 Sign。协商失败时会报 Bad_SecurityModeRejected。