2017-08-27 125 views
0

我试图建立一个我正在写的服务器和一个我不太了解的设备之间的SSL连接,除了它可能嵌入公共事件键(正如你将在下面看到的,我有私钥)。Java SSL套接字无法从客户端连接

我所知道的是,我有一个可以工作的服务器的python代码,并且该设备可以连接并发送和接收消息。

随着python代码,我还收到了一个证书(PEM格式)和我在套接字初始化期间提供的私钥。在Python代码如下:

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
print 'Socket created' 

#Bind socket to local host and port 
try: 
sock.bind((HOST, 34567)) 
except socket.error as msg: 
    print 'Bind failed. Error Code : ' + str(msg[0]) + ' Message ' + msg[1] 
    sys.exit() 
print 'Socket bind complete' 
sslSocket = ssl.wrap_socket(sock , server_side=True, certfile="device.crt", keyfile="device.key", ssl_version=ssl.PROTOCOL_TLSv1_2) 

#Start listening on socket 
sslSocket.listen(10) 
print 'Socket now listening' 

#wait to accept a connection - blocking call 
print 'wait to accept a connection' 

conn, addr = sslSocket.accept() 
print 'Connected with ' + addr[0] + ':' + str(addr[1]) 

#start new thread takes 1st argument as a function name to be run, second is 
the tuple of arguments to the function. 
start_new_thread(receiveThread ,(conn,)) 
time.sleep(1) 
start_new_thread(clientThread ,(conn,)) 

while 1: 
time.sleep(1) 
if exitNow: 
    print 'Exit' 
    break 

sock.close() 

print 'exiting' 
sys.exit() 

我有插座零经验,但据我了解在Java中的插座我必须初始化和设置一个密钥库和信任,以创建一个SSL套接字。

我做什么(根据this SO answer

转换我的证书和密钥导入PKCS12证明书

openssl pkcs12 -export -in device.crt -inkey device.key -certfile device.crt -name "someName" -out device.p12 

创建密钥库并导入新生成的证书到它 -

keytool -importkeystore -deststorepass 123456 -destkeypass 123456 -destkeystore keystore.jks -srckeystore device.p12 -srcstoretype PKCS12 -srcstorepass 1234 -alias someName 

再次复制该密钥库并将其称为信任库(不确定这是否正确)。 然后,我使用生成的密钥仓库用以下代码初始化套接字:(请注意,我使用Spring集成,因为我的最终目标是尝试启动应用程序,它会在REST API上接收调用后在套接字上发送消息) :

@EnableIntegration 
@IntegrationComponentScan 
@Configuration 
public class SocketConfiguration implements 
ApplicationListener<TcpConnectionEvent> { 

private final org.slf4j.Logger log = LoggerFactory.getLogger(getClass()); 

@Bean 
public AbstractServerConnectionFactory AbstractServerConnectionFactory() { 
    TcpNetServerConnectionFactory tcpNetServerConnectionFactory = new TcpNetServerConnectionFactory(34567); 
    DefaultTcpNetSSLSocketFactorySupport tcpNetSSLSocketFactory = tcpSocketFactorySupport(); 
    tcpNetServerConnectionFactory.setTcpSocketFactorySupport(tcpNetSSLSocketFactory); 
    return tcpNetServerConnectionFactory; 
} 
@Bean 
public DefaultTcpNetSSLSocketFactorySupport tcpSocketFactorySupport() { 
    TcpSSLContextSupport sslContextSupport = new DefaultTcpSSLContextSupport("keystore.jks", 
      "trustStore.jks", "123456", "123456"); 
    DefaultTcpNetSSLSocketFactorySupport tcpSocketFactorySupport = 
      new DefaultTcpNetSSLSocketFactorySupport(sslContextSupport); 
    return tcpSocketFactorySupport; 
} 

@Bean 
public TcpInboundGateway TcpInboundGateway(AbstractServerConnectionFactory connectionFactory) { 
    TcpInboundGateway inGate = new TcpInboundGateway(); 
    inGate.setConnectionFactory(connectionFactory); 
    inGate.setRequestChannel(getMessageChannel()); 
    return inGate; 
} 

@Bean 
public MessageChannel getMessageChannel() { 
    return new DirectChannel(); 
} 

@MessageEndpoint 
public class Echo { 

    @Transformer(inputChannel = "getMessageChannel") 
    public String convert(byte[] bytes) throws Exception { 
     return new String(bytes); 
    } 

} 

private static ConcurrentHashMap<String, TcpConnection> tcpConnections = new ConcurrentHashMap<>(); 

@Override 
public void onApplicationEvent(TcpConnectionEvent tcpEvent) { 
    TcpConnection source = (TcpConnection) tcpEvent.getSource(); 
    if (tcpEvent instanceof TcpConnectionOpenEvent) { 

     log.info("Socket Opened " + source.getConnectionId()); 
     tcpConnections.put(tcpEvent.getConnectionId(), source); 

     if (!authorizeIncomingConnection(source.getSocketInfo())) { 
      log.warn("Socket Rejected " + source.getConnectionId()); 
      source.close(); 
     } 

    } else if (tcpEvent instanceof TcpConnectionCloseEvent) { 
     log.info("Socket Closed " + source.getConnectionId()); 
     tcpConnections.remove(source.getConnectionId()); 
    } 
} 

private boolean authorizeIncomingConnection(SocketInfo socketInfo) { 
    //Authorization Logic , Like Ip,Mac Address WhiteList or anyThing else ! 
    return (System.currentTimeMillis()/1000) % 2 == 0; 
} 

我觉得插座创建成功,因为我的Windows机器上运行netstat显示的端口40003采取的是一个Java进程(这是不是当我终止进程)。

现在唯一的问题是设备仍然不能连接到我的套接字。 不幸的是,这是一个封闭的设备,我有零信息,无法调试它,了解发生了什么以及为什么无法连接(也没有从中获取任何日志)。 我的唯一参考是 - 当我在运行java代码的同一台机器上运行附加的Python代码(显然不在一起)时,同一个设备能够连接到套接字。

请问我可以指点我的java代码与Python代码不同吗?或我可以使用的任何其他方向。

谢谢!

回答

0

原来问题出在我的防火墙上。 python在防火墙中有异常(我的假设是这些异常是在安装过程中插入的,但不太确定),而java没有这些异常,因此java进程无法将此套接字“公开”到外部世界

相关问题