Eclipse Milo - ClosedChannelException при использовании SecurityPolicy
Я подключаюсь от клиента Eclipse Milo к серверу Eclipse Milo. Все работает нормально, но как только я пытаюсь подключиться к любому SecurityPolicy, кроме "None", я получаю следующую ошибку:
17:28:18.365 [main] DEBUG org.eclipse.milo.opcua.stack.client.ClientChannelManager - connect(), currentState=NotConnected
17:28:18.365 [main] DEBUG org.eclipse.milo.opcua.stack.client.ClientChannelManager - connect() while NotConnected
java.lang.Exception: null
at org.eclipse.milo.opcua.stack.client.ClientChannelManager.connect(ClientChannelManager.java:67) [stack-client-0.2.3.jar:0.2.3]
at org.eclipse.milo.opcua.stack.client.UaTcpStackClient.connect(UaTcpStackClient.java:127) [stack-client-0.2.3.jar:0.2.3]
at org.eclipse.milo.opcua.sdk.client.OpcUaClient.connect(OpcUaClient.java:312) [sdk-client-0.2.3.jar:0.2.3]
at de.dlh.lht.ticc.esa.opcua.client.lib.LhtOpcUaClient.connect(LhtOpcUaClient.java:86) [classes/:?]
at de.dlh.lht.ticc.esa.opcua.client.lib.TestTools.runWithCredentials(TestTools.java:41) [test-classes/:?]
at de.dlh.lht.ticc.esa.opcua.client.lib.ConnectAgainstMiloServerTest.credentialsTest(ConnectAgainstMiloServerTest.java:48) [test-classes/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_101]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_101]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_101]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_101]
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) [junit-4.12.jar:4.12]
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12]
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) [junit-4.12.jar:4.12]
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) [junit-4.12.jar:4.12]
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) [junit-4.12.jar:4.12]
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12]
at org.junit.runner.JUnitCore.run(JUnitCore.java:137) [junit-4.12.jar:4.12]
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) [junit-rt.jar:?]
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) [junit-rt.jar:?]
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) [junit-rt.jar:?]
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) [junit-rt.jar:?]
17:28:18.367 [ua-shared-pool-0] DEBUG org.eclipse.milo.opcua.stack.client.ClientChannelManager - Channel bootstrap failed: null
java.nio.channels.ClosedChannelException: null
de.dlh.lht.ticc.esa.opcua.client.lib.exceptions.ClientExecutionException: java.util.concurrent.ExecutionException: java.nio.channels.ClosedChannelException
at de.dlh.lht.ticc.esa.opcua.client.lib.LhtOpcUaClient.connect(LhtOpcUaClient.java:88)
at de.dlh.lht.ticc.esa.opcua.client.lib.TestTools.runWithCredentials(TestTools.java:41)
at de.dlh.lht.ticc.esa.opcua.client.lib.ConnectAgainstMiloServerTest.credentialsTest(ConnectAgainstMiloServerTest.java:48)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
Caused by: java.util.concurrent.ExecutionException: java.nio.channels.ClosedChannelException
at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357)
at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1895)
at de.dlh.lht.ticc.esa.opcua.client.lib.LhtOpcUaClient.connect(LhtOpcUaClient.java:86)
... 24 more
Caused by: java.nio.channels.ClosedChannelException
Любая идея?
Это происходит, когда я использую сертификат с закрытым ключом, а также с именем пользователя / паролем. Журналы на стороне сервера
DEBUG o.e.m.o.s.s.h.UaTcpServerAsymmetricHandler - Received CloseSecureChannelRequest
так что я думаю, что клиент здесь проблема. Та же проблема возникает и с другими серверами opc-ua.
РЕДАКТИРОВАТЬ: я создал минимальный пример, где происходит ошибка
package de.dlh.lht.ticc.esa.opcua.client.lib;
import org.eclipse.milo.opcua.sdk.client.OpcUaClient;
import org.eclipse.milo.opcua.sdk.client.api.config.OpcUaClientConfig;
import org.eclipse.milo.opcua.sdk.client.api.config.OpcUaClientConfigBuilder;
import org.eclipse.milo.opcua.sdk.client.api.identity.UsernameProvider;
import org.eclipse.milo.opcua.stack.client.UaTcpStackClient;
import org.eclipse.milo.opcua.stack.core.security.SecurityPolicy;
import org.eclipse.milo.opcua.stack.core.types.structured.EndpointDescription;
import org.junit.Test;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.Arrays;
public class SmokeTest {
private static final Logger log = LoggerFactory.getLogger(SmokeTest.class);
private static EndpointDescription getEndpointDescriptions(String endpoint, SecurityPolicy securityPolicy) throws Exception {
EndpointDescription[] endpoints;
try {
endpoints = UaTcpStackClient
.getEndpoints(endpoint)
.get();
} catch (Exception ex) {
log.warn("failed to get endpoints", ex);
log.warn("will try to explicitly discover endpoints");
String discoveryUrl = endpoint + "/discovery";
log.info("Trying explicit discovery URL: {}", discoveryUrl);
endpoints = UaTcpStackClient
.getEndpoints(discoveryUrl)
.get();
}
EndpointDescription endpointDescription = Arrays.stream(endpoints)
.filter(e -> e.getSecurityPolicyUri().equals(securityPolicy.getSecurityPolicyUri()))
.findFirst().orElseThrow(() -> new Exception("no valid endpoint found for '" + endpoint + "'"));
return endpointDescription;
}
@Test
public void runTest() throws Exception {
OpcUaClientConfigBuilder builder = OpcUaClientConfig.builder();
EndpointDescription endpointDescription =
getEndpointDescriptions("opc.tcp://127.0.0.1:12686/example", SecurityPolicy.Basic128Rsa15);
builder
.setEndpoint(endpointDescription);
builder.setIdentityProvider(new UsernameProvider(
"user",
"password1"
));
OpcUaClient client = new OpcUaClient(builder.build());
client.connect().get();
Thread.sleep(1000 * 10);
client.disconnect().get();
}
}
Этот тест выполняется на примере сервера eclipse milo: https://github.com/eclipse/milo/blob/master/milo-examples/server-examples/src/main/java/org/eclipse/milo/examples/server/ExampleServer.java
Еще одно обновление: меня больше всего раздражает следующее поведение
09:19:09.040 [ua-shared-pool-0] DEBUG org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler - Received OpenSecureChannelResponse.
09:19:09.040 [ua-shared-pool-0] DEBUG org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler - SecureChannel id=4, currentTokenId=4, previousTokenId=-1, lifetime=3600000ms, createdAt=DateTime{utcTime=131860523490250000, javaDate=Wed Nov 07 09:19:09 CET 2018}
09:19:09.040 [ua-netty-event-loop-0] DEBUG org.eclipse.milo.opcua.stack.client.handlers.UaTcpClientMessageHandler - 0 message(s) queued before handshake completed; sending now.
09:19:09.040 [ua-shared-pool-1] DEBUG org.eclipse.milo.opcua.stack.client.ClientChannelManager - Channel bootstrap succeeded: localAddress=/127.0.0.1:50437, remoteAddress=/127.0.0.1:12686
09:19:09.134 [ua-shared-pool-0] DEBUG org.eclipse.milo.opcua.stack.client.ClientChannelManager - disconnect(), currentState=Connected
09:19:09.134 [ua-shared-pool-1] DEBUG org.eclipse.milo.opcua.stack.client.ClientChannelManager - Sending CloseSecureChannelRequest...
Кажется, что соединение с клиентом успешно, но затем клиент из вышеупомянутого теста сразу же отключается снова сам, чего он не делает, не используя SecurityPolicy.
Еще страннее, после этого журнал продолжается с:
09:28:12.283 [ua-netty-event-loop-0] DEBUG org.eclipse.milo.opcua.stack.client.ClientChannelManager - channelInactive(), disconnect complete
09:28:12.283 [ua-netty-event-loop-0] DEBUG org.eclipse.milo.opcua.stack.client.ClientChannelManager - disconnect complete, state set to Idle
09:28:12.299 [main] INFO org.eclipse.milo.opcua.sdk.client.OpcUaClient - Eclipse Milo OPC UA Stack version: 0.2.4
09:28:12.299 [main] INFO org.eclipse.milo.opcua.sdk.client.OpcUaClient - Eclipse Milo OPC UA Client SDK version: 0.2.4
09:28:12.315 [main] DEBUG org.eclipse.milo.opcua.sdk.client.OpcUaClient - Added ServiceFaultListener: org.eclipse.milo.opcua.sdk.client.session.SessionFsm$FaultListener@333d4a8c
09:28:12.330 [main] DEBUG org.eclipse.milo.opcua.sdk.client.OpcUaClient - Added SessionActivityListener: org.eclipse.milo.opcua.sdk.client.subscriptions.OpcUaSubscriptionManager$1@71687585
09:28:12.440 [main] DEBUG org.eclipse.milo.opcua.stack.client.ClientChannelManager - connect(), currentState=NotConnected
09:28:12.440 [main] DEBUG org.eclipse.milo.opcua.stack.client.ClientChannelManager - connect() while NotConnected
java.lang.Exception: null
at org.eclipse.milo.opcua.stack.client.ClientChannelManager.connect(ClientChannelManager.java:67) [stack-client-0.2.4.jar:0.2.4]
at org.eclipse.milo.opcua.stack.client.UaTcpStackClient.connect(UaTcpStackClient.java:127) [stack-client-0.2.4.jar:0.2.4]
at org.eclipse.milo.opcua.sdk.client.OpcUaClient.connect(OpcUaClient.java:312) [sdk-client-0.2.4.jar:0.2.4]
at de.dlh.lht.ticc.esa.opcua.client.lib.SmokeManualTest.run(SmokeManualTest.java:95) [test-classes/:?]
at de.dlh.lht.ticc.esa.opcua.client.lib.SmokeManualTest.credentialsTest(SmokeManualTest.java:104) [test-classes/:?]
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0_101]
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[?:1.8.0_101]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[?:1.8.0_101]
at java.lang.reflect.Method.invoke(Method.java:498) ~[?:1.8.0_101]
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50) [junit-4.12.jar:4.12]
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12) [junit-4.12.jar:4.12]
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47) [junit-4.12.jar:4.12]
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17) [junit-4.12.jar:4.12]
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26) [junit-4.12.jar:4.12]
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325) [junit-4.12.jar:4.12]
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78) [junit-4.12.jar:4.12]
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268) [junit-4.12.jar:4.12]
at org.junit.runners.ParentRunner.run(ParentRunner.java:363) [junit-4.12.jar:4.12]
at org.junit.runner.JUnitCore.run(JUnitCore.java:137) [junit-4.12.jar:4.12]
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68) [junit-rt.jar:?]
at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:47) [junit-rt.jar:?]
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242) [junit-rt.jar:?]
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70) [junit-rt.jar:?]
09:28:12.440 [ua-shared-pool-0] DEBUG org.eclipse.milo.opcua.stack.client.ClientChannelManager - Channel bootstrap failed: null
java.nio.channels.ClosedChannelException: null
Таким образом, похоже, что ClientChannelManager пытается подключиться после отключения, которое он сам инициировал.
Еще одна вещь, которую я попробовал, была
builder.setCertificateValidator( new InsecureCertificateValidator());
Предполагается, что самоподписанный сертификат сервера отклонен, но это не помогло. Даже журналы из этого класса не печатаются, поэтому я предполагаю, что средство проверки сертификата не вызывается, и ошибка происходит даже раньше.
Просто для удовольствия, я также добавил
static {
CryptoRestrictions.remove();
Security.addProvider(new BouncyCastleProvider());
}
к моему тесту на дым. все еще не повезло
1 ответ
Конечно, это была довольно простая проблема. Другие ошибки в журнале не имели к этому никакого отношения.
Еще один взгляд на Понимание безопасности OPC-UA с использованием Eclipse Milo очень помог.
Видите ли, вам всегда нужен сертификат приложения при использовании SecurityPolicy, который не является "Нет", так как этот сертификат используется для шифрования и подписи сообщений. Это также несколько специальный сертификат, так как он содержит URI приложения, которое должно соответствовать URI приложения, которое вы настраиваете для своего клиента через builder.setApplicationUri().
При использовании аутентификации через сертификат вы предоставляете второй сертификат (и закрытый ключ), который используется для подтверждения вашей личности на сервере. Это также причина, по которой вы можете проходить аутентификацию с помощью сертификата или имени пользователя / пароля, не шифруя и не подписывая сообщения.