繁体   English   中英

Java SSL套接字无法从客户端连接

[英]Java SSL socket cannot connect from client

我正在尝试在我正在写的服务器和一个我不太了解的设备之间建立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套接字。

我所做的是(根据此答案

将我的证书和密钥转换为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 Integration作为最终目标是使尝试启动的应用程序在接收到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代码不同的地方吗? 或我可以使用的其他任何方向。

谢谢!

原来问题出在我的机顶盒防火墙中。 python在防火墙中有异常(我的假设是那些异常是在安装过程中插入的,但对此不太确定),而java没有这些异常,因此java进程无法将该套接字“暴露”给外界

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM