我遇到了一个奇怪的问题,我似乎无法找到导致这种情况发生的原因。当应用程序首先启动时,应用程序中的SSL套接字工作正常,但是在某个时间之后或者在一些加载之后,握手过程开始出现问题。当通过openssl命令测试时,它有时会在写入客户端问候后停留几秒钟,然后返回没有证书可用错误,或者有时会出现此错误
CONNECTED(00000003)
SSL_connect:before/connect initialization
SSL_connect:unknown state
以下是如何创建SSLSocket并初始化密钥库的代码。
课程开始
public synchronized void start(CamdMessageListener listener, CaProfile profile) throws IOException, SocketException {
this.profile = profile;
if (srv == null) {
try {
createServerSocket();
} catch (IOException e) {
}
}
if (acceptThread == null && null != srv) {
if (useSsl) {
acceptThread = new AcceptSSLThread(listener, this);
}
else {
acceptThread = new AcceptThread(listener, this);
}
}
portNumbers.put(new Integer(port), this);
acceptThread.start();
alive = true;
}
创建服务器套接字
public void createServerSocket() throws IOException {
synchronized (this) {
if (this.useSsl) {
ListenPort.logger.info("(ListenPort " + this.port + ") creating SSL server Socket , using Ssl : On");
try {
final SSLContext sslContext = SSLContext.getInstance("TLSv1.2");
ListenPort.logger.info("ListenPort " + this.port + ") Default keymanagerFactory algorithm: '" + KeyManagerFactory.getDefaultAlgorithm() + "'.");
//final KeyManagerList keyManagers = new KeyManagerList();
//final TrustManagerList trustManagers = new TrustManagerList();
final ArrayList<KeyManager> keyManagers = new ArrayList<KeyManager>();
final ArrayList<TrustManager> trustManagers = new ArrayList<TrustManager>();
this.keystores.forEach((k, v) -> {
try {
ListenPort.logger.info("(ListenPort " + this.port + ") ssl On : keystore ='" + k + "'");
final KeyStore ks = KeyStore.getInstance("JKS");
final KeyStore ks2 = KeyStore.getInstance("JKS");
final FileInputStream fis = new FileInputStream(k);
ListenPort.logger.info("(ListenPort " + this.port + ") Retrieving ssl ids from keystore '" + k + "' = passwd '" + v + "'");
ks2.load(fis, v.toCharArray());
ListenPort.logger.info("(ListenPort " + this.port + ") keystore '" + k + "' Loaded.");
final KeyManagerFactory kmf = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
final TrustManagerFactory tmf = TrustManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
ListenPort.logger.info("(ListenPort " + this.port + ") initializing Keymanager '" + k + "'.");
kmf.init(ks2, v.toCharArray());
final KeyManager[] km = kmf.getKeyManagers();
if (km.length > 0) {
ListenPort.logger.finest("(ListenPort " + this.port + ") Reading " + km.length + " key(s)");
for (int i = 0; i < km.length; ++i) {
ListenPort.logger.finest("(ListenPort " + this.port + ") Reading key " + km[i]);
keyManagers.add(km[i]);
}
}
ListenPort.logger.info("(ListenPort " + this.port + ") initializing trustmanager '" + k + "'.");
tmf.init(ks2);
final TrustManager[] tm = tmf.getTrustManagers();
if (tm.length > 0) {
ListenPort.logger.finest("(ListenPort " + this.port + ") Reading " + km.length + " trust(s)");
for (int j = 0; j < tm.length; ++j) {
ListenPort.logger.finest("(ListenPort " + this.port + ") Reading trust " + tm[j]);
trustManagers.add(tm[j]);
}
}
ListenPort.logger.info("(ListenPort " + this.port + ") Retrieving ssl On : from keystore '" + k + "' ok");
}
catch (UnrecoverableKeyException e7) {
ListenPort.logger.info("(ListenPort " + this.port + ") ssl On : keystore ='" + k + "' unrecoverable Key");
}
catch (KeyStoreException e8) {
ListenPort.logger.info("(ListenPort " + this.port + ") ssl On : keystore ='" + k + "' Bad Keystore");
}
catch (NoSuchAlgorithmException e9) {
ListenPort.logger.info("(ListenPort " + this.port + ") ssl On : keystore ='" + k + "' No such Algorithm");
}
catch (CertificateException e10) {
ListenPort.logger.info("(ListenPort " + this.port + ") ssl On : keystore ='" + k + "' Bad Certificate");
}
catch (IOException e11) {
ListenPort.logger.severe("(ListenPort " + this.port + ") ssl On : keystore ='" + k + "' IOExcept");
}
return;
});
try {
KeyManager[] km2 = new KeyManager[0];
TrustManager[] tp = new TrustManager[0];
km2 = keyManagers.toArray(km2);
tp = trustManagers.toArray(tp);
ListenPort.logger.finest("(ListenPort " + this.port + ") Init SSL Context : " + km2.length + " key , " + tp.length + " trusts");
sslContext.init(km2, tp, null);
SSLServerSocket sslsrv;
if (this.bindAddr == null) {
ListenPort.logger.finest("(ListenPort " + this.port + ") No specific Binding Address");
sslsrv = (SSLServerSocket)sslContext.getServerSocketFactory().createServerSocket(this.port);
}
else {
ListenPort.logger.finest("(ListenPort " + this.port + ") Binding Address" + this.bindAddr.getHostAddress());
sslsrv = (SSLServerSocket)sslContext.getServerSocketFactory().createServerSocket(this.port, 0, this.bindAddr);
}
ListenPort.logger.finest("(ListenPort " + this.port + ") Enabling protocols");
String[] protocols = sslsrv.getSupportedProtocols();
for (int l = 0; l < protocols.length; ++l) {
ListenPort.logger.finest("(ListenPort " + this.port + ") " + protocols[l]);
}
sslsrv.setEnabledProtocols(protocols);
String[] suites = sslsrv.getSupportedCipherSuites();
ListenPort.logger.finest("(ListenPort " + this.port + ") Supported cipher suites are:");
for (int m = 0; m < suites.length; ++m) {
ListenPort.logger.finest("(ListenPort " + this.port + ") " + suites[m]);
}
sslsrv.setEnabledCipherSuites(suites);
suites = sslsrv.getEnabledCipherSuites();
ListenPort.logger.finest("(ListenPort " + this.port + ") Supported cipher suites are:");
for (int m = 0; m < suites.length; ++m) {
ListenPort.logger.finest("(ListenPort " + this.port + ") " + suites[m]);
}
ListenPort.logger.finest("(ListenPort " + this.port + ") Support protocols are:");
protocols = sslsrv.getSupportedProtocols();
for (int m = 0; m < protocols.length; ++m) {
ListenPort.logger.finest("(ListenPort " + this.port + ") " + protocols[m]);
}
this.srv = sslsrv;
}
catch (NullPointerException e) {
ListenPort.logger.warning("ListenPort " + this.port + ") Erreur Creating server socket : " + e.getMessage());
}
catch (IOException e2) {
ListenPort.logger.warning("ListenPort " + this.port + ") Erreur Creating server socket" + e2.getMessage());
}
ListenPort.logger.info("(ListenPort " + this.port + ") ssl On server created");
}
catch (NoSuchAlgorithmException e3) {
if (null != this.srv) {
this.srv.close();
}
this.srv = null;
System.err.println(" open ssl listenning port : no such algorithm");
ListenPort.logger.severe("ListenPort " + this.port + ") open ssl listenning port : no such algorithm disabling ssl : " + e3.getMessage());
}
catch (KeyManagementException e4) {
if (null != this.srv) {
this.srv.close();
}
this.srv = null;
ListenPort.logger.severe("(ListenPort " + this.port + ") creating SSL server Socket :key management problem " + e4.getMessage());
}
catch (Exception e5) {
if (null != this.srv) {
this.srv.close();
}
this.srv = null;
ListenPort.logger.info("(ListenPort " + this.port + ") creating SSL server Socket :key management problem " + e5.getMessage());
}
ListenPort.logger.info("(ListenPort " + this.port + ") creating server Socket , using Ssl : On");
}
else {
srv = new ServerSocket();
try {
if (this.bindAddr == null) {
srv.bind(new InetSocketAddress(this.port));
}
else {
srv.bind(new InetSocketAddress(this.bindAddr, this.port));
}
}
catch (BindException e6) {
}
}
}
}
AcceptSSLThread
public void run()
{
while (this.listenPort.isAlive()) {
try
{
SSLSocket s = (SSLSocket)this.listenPort.getServerSocket().accept();
SSLSession sess = s.getSession();
this.logger.info("Peer host is " + sess.getPeerHost());
this.logger.info("Cipher is " + sess.getCipherSuite());
this.logger.info("Protocol is " + sess.getProtocol());
this.logger.info("ID is " + sess.getId());
this.logger.info("Session created in " + sess.getCreationTime());
this.logger.info("Session accessed in " + sess.getLastAccessedTime());
String ip = s.getInetAddress().getHostAddress();
int maxThreads = ProxyConfig.getInstance().getMaxThreads();
if (Thread.activeCount() > maxThreads) {
try {
Thread.sleep(1000L);
} catch (InterruptedException localInterruptedException) {}
this.logger.severe("Max-threads exceeded (" + maxThreads + "), closing incoming connection: " + CustomFormatter.formatAddress(ip));
s.close();
}
else if ((!this.listenPort.isAllowed(ip)) || (this.listenPort.isDenied(ip))) {
this.logger.fine("Rejected connection: " + CustomFormatter.formatAddress(ip) + " not allowed.");
com.bowman.cardserv.session.SessionManager.getInstance().fireUserLoginFailed("?@" + ip, this.listenPort + "/", ip, "rejected by [" + this.listenPort + "] ip deny list.");
s.close();
} else {
this.logger.fine("Accepted connection: " + CustomFormatter.formatAddress(ip));
ProxySession ps;
try
{
ps = createSession(s, this.listenPort, this.listener);
} catch (UnknownHostException e) {
this.logger.fine("Unknown Host Excpeption: " + CustomFormatter.formatAddress(ip) + " : " + e.getMessage() + "' cause: " + e.getCause().getMessage());
ps = null;
} catch (IOException e) {
this.logger.fine("IOExcpeption: " + CustomFormatter.formatAddress(ip) + " : " + e.getMessage() + "' cause: " + e.getCause().getMessage());
ps = null;
}
catch (Exception e) {
this.logger.fine("Exception : " + CustomFormatter.formatAddress(ip) + " : " + e.getMessage() + "' cause: " + e.getCause().getMessage());
ps = null;
}
if (ps == null) {
try { s.close();
}
catch (Exception localException1) {}
}
}
} catch (java.net.SocketException e) {
this.logger.throwing("Server socket closed: " + this.listenPort + " (" + e.getMessage() + ")", e);
this.listenPort.destroy();
} catch (IOException e) {
this.logger.severe("Exception accepting socket connection for [" + this.listenPort + "], aborting...", e);
this.listenPort.destroy();
} catch (Throwable t) {
this.logger.severe("Error in accept loop: " + t, t);
return;
}
}
}
问题有时会发生在几分钟之后,有时几个小时之后,也许用户负载与问题有关。但是当启动应用程序时它工作正常,并且如果配置文件发生更改,则有一个用于刷新套接字的系统,因此如果我更改配置文件并再次执行SSL代码,则它会再次开始工作并再次停止一段时间后。这真让我疯狂。
此处还有代码部分,如果配置更新,则刷新密钥库。
public void configUpdated(ProxyXmlConfig xml) throws ConfigException {
int port = xml.getPortValue("listen-port");
if (portNumbers.containsKey(new Integer(port))) {
ListenPort lp = (ListenPort)portNumbers.get(new Integer(port));
if (lp != this) {
throw new ConfigException(xml.getFullName(), "listen-port", "Listen-port '" + port + "' already in use by [" + lp + "]");
}
}
ProxyXmlConfig sslXml = null;
try {
sslXml = xml.getSubConfig("ssl");
}
catch (ConfigException e) {
ListenPort.logger.info("(ListenPort " + port + ") " + e.getMessage());
}
catch (Exception e2) {
ListenPort.logger.info("(ListenPort " + port + ") " + e2.getMessage());
}
if (sslXml != null && "true".equalsIgnoreCase(sslXml.getStringValue("enabled"))) {
Iterator iter = sslXml.getMultipleSubConfigs("keystore");
this.keystores.clear();
if (iter != null) {
while (iter.hasNext()) {
ProxyXmlConfig keystore = (ProxyXmlConfig) iter.next();
if (keystore.getName() != null && keystore.getName().length() > 0) {
String passwd = keystore.getStringValue("password");
String store = keystore.getContents();
if (new File(store).exists()) {
this.keystores.put(store, passwd);
ListenPort.logger.finest("(ListenPort " + port + ") loading from config file :'" + store + "' passwd '" + passwd + "'");
}
else {
ListenPort.logger.warning("(ListenPort " + port + ") +Keystore file " + keystore.getName() + "unreachable - ignoring ");
}
}
}
}
this.useSsl = true;
}
setPort(port);
String bindIp = null; bindAddr = null;
try {
bindIp = xml.getStringValue("bind-ip");
} catch (ConfigException ex) {}
if(bindIp != null) try {
bindAddr = InetAddress.getByName(bindIp);
} catch (UnknownHostException e3) {
ListenPort.logger.throwing("ListenPort " + port + ") Bind IP Exception '" + e3.getMessage() + "' for bindin " + bindIp, new ConfigException(xml.getFullName(), "bind-ip", "Invalid listen-port bind-ip: " + bindIp));
} catch (Exception e4) {
ListenPort.logger.throwing("ListenPort " + port + ") Bind IP Exception '" + e4.getMessage() + "' for bindin " + bindIp, new ConfigException(xml.getFullName(), "bind-ip", "Invalid listen-port bind-ip: " + bindIp));
}
properties.clear();
Iterator iter2 = xml.getMultipleSubConfigs(null);
if (iter2 != null) {
ProxyXmlConfig e5;
while (iter2.hasNext()) {
e5 = (ProxyXmlConfig)iter2.next();
if (e5.getName() != null && e5.getName().length() > 0) {
this.properties.put(e5.getName(), xml);
}
}
try {
e5 = (ProxyXmlConfig)properties.remove("allow-list");
if (e5 == null) throw new ConfigException("");
String allow = e5.getStringValue("allow-list");
allowList = new HashSet(Arrays.asList(allow.split(" ")));
} catch (ConfigException ce) {
allowList = new HashSet();
}
try {
e5 = (ProxyXmlConfig)properties.remove("deny-list");
if (e5 == null) throw new ConfigException("");
String deny = e5.getStringValue("deny-list");
denyList = new HashSet(Arrays.asList(deny.split(" ")));
} catch (ConfigException ce) {
denyList = new HashSet();
}
}
}
非常感谢任何帮助,谢谢。