IIOP.NET的 SSL插件在与omniORB的 SSL/mTLS连接上失败(TCP连接正常)——证书已导入,OpenSSL成功
在将一个CORBA系统集成时,服务器端使用C++03版本的omniORB 4.3,客户端使用C#的 IIOP.NET。
Server side (omniORB)
- 服务器在正确的服务器证书下以SSL模式运行正常。
- 客户端认证(mTLS)工作正常。
- 我用OpenSSL验证了连通性:
Shellopenssl s_client -connect <host>:<sslPort> -cert client.crt -key client.key -CAfile ca.crt
握手成功并以Verify返回码:0(ok)结束。
因此,服务端的TLS/mTLS已确认正常。
Windows client certificates (already installed)
在运行C#客户端的Windows机器上,我已经导入:
- 包含私钥的客户端证书(PFX)到CurrentUser => Personal (My)。
- 将CA证书导入到受信任的存储区(Trusted Root / 适当的信任存储)。
这与成功的OpenSSL材料相符,因此证书/密钥/CA的设置是正确的。
Client side problem (IIOP.NET / SSLPlugin)
- 在纯TCP模式下,一切工作正常(命名服务、IOR、方法调用)。
- 启用SSL时,客户端会在很早阶段失败(在真正的远程调用之前),无法稳定地消费启用SSL的 IOR/URI。典型故障包括无法创建通道接收器 / 连接目标 / 与SSLPlugin相关的类似问题。
Attempted IIOP.NET SSL channel config
我尝试了常用的SSLPlugin设置,它使用来自Windows存储的证书:
IDictionary props = new Hashtable();
props[IiopChannel.TRANSPORT_FACTORY_KEY] = "Ch.Elca.Iiop.Security.Ssl.SslTransportFactory,SSLPlugin";
props[SslTransportFactory.CLIENT_AUTHENTICATION] = "Ch.Elca.Iiop.Security.Ssl.ClientMutualAuthenticationSuitableFromStore,SSLPlugin";
props[ClientMutualAuthenticationSuitableFromStore.STORE_LOCATION] = "CurrentUser";
var ch = new IiopClientChannel(props);
ChannelServices.RegisterChannel(ch, false);
然后连接:
- 来自命名服务的启用SSL的 IOR:...,以及
- 尝试从IOR提取的主机/端口和对象键构造的corbaloc形式。
在TCP模式下,相同的客户端代码工作稳定;在SSL模式下,IIOP.NET就会出错。
Question
是否有人遇到IIOP.NET的 SSLPlugin与 omniORB的 SSL/mTLS(特别是在启用SSL的 IOR/服务URI方面)不兼容的情况?
这是SSLPlugin的已知限制/错误吗?
是否有特定的设置/变通办法可以让IIOP.NET正确处理omniORB的 SSL IOR?
关于调试SSLPlugin的线索(例如跟踪/详细日志),是否有方法显示为什么在Windows存储中证书正确的情况下仍然失败?
欢迎给出任何建议。
EDIT: 如有人请求提供堆栈跟踪,我在下面提供一个。请注意,在我的实验中,根据配置变化,出现了不同的异常。我无法在现实场景下重新复现并收集所有异常,但所示的栈跟踪代表了失败的情况。进一步调查显示,根本原因似乎在于Org.Mentalis.Security,这是IIOP.NET SslPlugin内部使用的库。该库相当陈旧,不支持现代TLS版本(如TLS 1.2+)或当代密码套件,导致在连接到CORBA后端时SSL/TLS握手失败。作为权宜之计,使用stunnel在我们的场景中不可行,因为客户端应用要处理大量服务URI,难以为每个端点维护隧道。
connect:omg.org.CORBA.TRANSIENT
HResult=0x80131500
Message=CORBA system exception : omg.org.CORBA.TRANSIENT [Unable to connect to target.] , completed: Completed_No minor: 4000
Source=mscorlib
StackTrace:
at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
at omg.org.CORBA.IObject._is_a(String repositoryId)
at Ch.Elca.Iiop.IiopClientFormatterSink.CheckAssignableRemote(Type formal, String url)
at Ch.Elca.Iiop.IiopClientFormatterSink.IsInterfaceCompatible(Ior target, Type neededTargetType, String targetUrl)
at Ch.Elca.Iiop.IiopClientFormatterSink.VerifyInterfaceCompatible(Ior target, IMessage msg)
at Ch.Elca.Iiop.IiopClientFormatterSink.SyncProcessMessage(IMessage msg)
at System.Runtime.Remoting.Proxies.RemotingProxy.CallProcessMessage(IMessageSink ms, IMessage reqMsg, ArrayWithSize proxySinks, Thread currentThread, Context currentContext, Boolean bSkippingContextChain)
at System.Runtime.Remoting.Proxies.RemotingProxy.InternalInvoke(IMethodCallMessage reqMcmMsg, Boolean useDispatchMessage, Int32 callType)
at System.Runtime.Remoting.Proxies.RemotingProxy.Invoke(IMessage reqMsg)
at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type)
EDIT: 有些用户投票关闭了这个问题,认为它缺乏调试细节。不过我认为这个投票不对,因为问题确实包含了相关细节,包括堆栈跟踪。
解决方案
问题与证书、TLS握手、服务器配置或命名服务无关。TCP-IIOP能可靠工作,但启用SSL会导致可重复的失败(例如对SSL IOR、服务URI的处理,以及对 SslPlugin / Org.Mentalis.Security 初始化的不稳定)。
根本原因在于IIOP.NET的 SSL堆栈,它依赖于 Org.Mentalis.Security。该组件过时且对现代TLS版本的支持不足,使其在SSL/mTLS通信中不可靠。此外,IIOP.NET本身也不再积极维护,因此修复起来需要对ORB进行高风险、深层次的修改。
我们也评估了 DotNetOrb,它实际上是正确工作且可行的解决方案(包括SSL支持)。但在我们的环境中不可用,因为它不支持旧版.NET Framework。
对我们而言的实际解决方案是使用本地的C++ CORBA客户端,并通过DLL封装将其暴露给C#。