Java SSL javax.net.ssl.SSLException: Received fatal alert: internal_error - java

I finally managed to get SSL working between clients and my server... Atleast when running it directly from Netbeans.
Client network init code:
private Network(final String hostname, final int port) {
try {
URL resource = getClass().getResource("/truststore/TCGtruststore.jks");
if (resource == null) {
Controller.getInstance().write(MessageType.DEBUG, "Could not load trust store.");
throw new IllegalStateException("network.Network: Could not load trust store.");
}
else {
Controller.getInstance().write(MessageType.LOG, "Loaded trust store.");
}
System.setProperty("javax.net.ssl.trustStore", resource.getPath());
System.setProperty("javax.net.ssl.trustStorePassword", "tcgadmin");
Socket baseSocket = new Socket();
baseSocket.connect(new InetSocketAddress(hostname, port), Config.TIMEOUT);
SSLSocketFactory socketFactory = (SSLSocketFactory)SSLSocketFactory.getDefault();
clientSocket = (SSLSocket)socketFactory.createSocket(baseSocket, hostname, port, true);
clientSocket.startHandshake();
out = new PrintWriter(clientSocket.getOutputStream(), true);
in = new BufferedReader(new InputStreamReader(clientSocket.getInputStream()));
connected = true;
} catch (IOException ex) {
connected = false;
}
waitForServer = new HashMap<>();
}
Server network init code:
public Server(final int port) {
this.port = port;
try {
URL resource = getClass().getResource("/keystore/TCGkeystore.jks");
if (resource == null) {
throw new IllegalStateException("server.Server: Could not load key store.");
}
System.setProperty("javax.net.ssl.keyStore", resource.getPath());
System.setProperty("javax.net.ssl.keyStorePassword", "tcgadmin");
//serverSocket = new ServerSocket(port);
serverSocket = (SSLServerSocket)SSLServerSocketFactory.getDefault().createServerSocket(port);
} catch (IOException ex) {
Logger.getLogger(Server.class.getName()).log(Level.SEVERE, null, ex);
}
}
However when I clean and build it, and run it outside Netbeans, it breaks.
Surprisingly enough the client still behaves fine though, it is the server that starts acting strange with this message:
mei 20, 2013 4:36:16 PM server.ServerConnectionReceiver run
SEVERE: null
javax.net.ssl.SSLException: Received fatal alert: internal_error
at sun.security.ssl.Alerts.getSSLException(Alerts.java:208)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1977)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1093)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1328)
at sun.security.ssl.SSLSocketImpl.readDataRecord(SSLSocketImpl.java:882)
at sun.security.ssl.AppInputStream.read(AppInputStream.java:102)
at sun.nio.cs.StreamDecoder.readBytes(StreamDecoder.java:283)
at sun.nio.cs.StreamDecoder.implRead(StreamDecoder.java:325)
at sun.nio.cs.StreamDecoder.read(StreamDecoder.java:177)
at java.io.InputStreamReader.read(InputStreamReader.java:184)
at java.io.BufferedReader.fill(BufferedReader.java:154)
at java.io.BufferedReader.readLine(BufferedReader.java:317)
at java.io.BufferedReader.readLine(BufferedReader.java:382)
at server.ServerConnectionReceiver.run(ServerConnectionReceiver.java:45)
at java.lang.Thread.run(Thread.java:722)
Command line code from client:
[16:36:15] [Log] Loaded trust store.
[16:36:16] [Log] Could not establish a connection with the server.
Does anyone have any clue on what went wrong?
When server runs from within netbeans and client aswell, everything is fine.
When server runs from within netbeans and client via commandline, the server gives an exception.
When I try to run the server from commandline, it gives an error. (I was about to test if it would work with both from commandline, but I unfortunately cannot just test that)
Regards.

Related

Why does SSL not work inside a build jar?

I have a small project in which i want to use TLS 1.3.
As main example i used this respo: https://github.com/williamswhy/SSLSocket
This is my server:
Server() {
SSLServerSocket serverSocket = null;
SSLSocket socket = null;
try {
SSLServerSocketFactory sslServerSocketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
serverSocket = (SSLServerSocket) sslServerSocketFactory.createServerSocket(3122);
MariaDB mariaDB = new MariaDB();
new Thread(mariaDB).start();
while (true) {
socket = (SSLSocket) serverSocket.accept();
new Thread(new ClientConnection(socket,mariaDB)).start();
}
} catch (IOException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
//System.setProperty("javax.net.debug", "all");
System.setProperty("javax.net.ssl.keyStore", "sslserverkeys");
System.setProperty("javax.net.ssl.keyStorePassword", "password");
new Server();
}
My Client uses the following class:
try {
System.setProperty("javax.net.ssl.trustStore", "sslclienttrust");
System.setProperty("javax.net.ssl.trustStorePassword", "password");
//DO NOT CHANGE THIS
SSLContext sslContext = SSLContext.getInstance("TLSv1.3");
sslContext.init(null, null, new SecureRandom());
SSLSocketFactory socketFactory = sslContext.getSocketFactory();
socket = (SSLSocket) socketFactory.createSocket("localhost", 3122);
System.out.println("Successfully initialized connection");
try {
this.out = new ObjectOutputStream(this.socket.getOutputStream());
System.out.println("Successfully opened ObjectOutputStream");
} catch (IOException var4) {
var4.printStackTrace();
try {
this.out.close();
} catch (IOException var3) {
var3.printStackTrace();
}
}
} catch (NoSuchAlgorithmException | KeyManagementException | IOException e) {
e.printStackTrace();
}
I have a sslclienttrust file in the root folder of my client and sslserverkeys in the root folder of my server. I'm coding in IntelliJ Ultimate with Maven and the connection works like a charm in it.
But when i build a .jar (using maven-shade-plugin) I get an exception.
The Server throws the following exception:
javax.net.ssl.SSLException: readHandshakeRecord
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1392)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:441)
at java.base/sun.security.ssl.SSLSocketImpl.ensureNegotiated(SSLSocketImpl.java:889)
at java.base/sun.security.ssl.SSLSocketImpl$AppOutputStream.write(SSLSocketImpl.java:1251)
at java.base/java.io.ObjectOutputStream$BlockDataOutputStream.drain(ObjectOutputStream.java:1893)
at java.base/java.io.ObjectOutputStream$BlockDataOutputStream.setBlockDataMode(ObjectOutputStream.java:1802)
at java.base/java.io.ObjectOutputStream.<init>(ObjectOutputStream.java:252)
at ClientConnection.<init>(ClientConnection.java:21)
at Server.<init>(Server.java:20)
at Server.main(Server.java:36)
Suppressed: java.net.SocketException: An established connection was aborted by the software in your host machine
at java.base/sun.nio.ch.NioSocketImpl.implWrite(NioSocketImpl.java:420)
at java.base/sun.nio.ch.NioSocketImpl.write(NioSocketImpl.java:440)
at java.base/sun.nio.ch.NioSocketImpl$2.write(NioSocketImpl.java:826)
at java.base/java.net.Socket$SocketOutputStream.write(Socket.java:1052)
at java.base/sun.security.ssl.SSLSocketOutputRecord.encodeAlert(SSLSocketOutputRecord.java:82)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:356)
at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:268)
at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:451)
... 8 more
Caused by: java.net.SocketException: An established connection was aborted by the software in your host machine
at java.base/sun.nio.ch.NioSocketImpl.implWrite(NioSocketImpl.java:420)
at java.base/sun.nio.ch.NioSocketImpl.write(NioSocketImpl.java:440)
at java.base/sun.nio.ch.NioSocketImpl$2.write(NioSocketImpl.java:826)
at java.base/java.net.Socket$SocketOutputStream.write(Socket.java:1052)
at java.base/sun.security.ssl.SSLSocketOutputRecord.flush(SSLSocketOutputRecord.java:268)
at java.base/sun.security.ssl.HandshakeOutStream.flush(HandshakeOutStream.java:89)
at java.base/sun.security.ssl.Finished$T13FinishedProducer.onProduceFinished(Finished.java:783)
at java.base/sun.security.ssl.Finished$T13FinishedProducer.produce(Finished.java:671)
at java.base/sun.security.ssl.SSLHandshake.produce(SSLHandshake.java:440)
at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.goServerHello(ClientHello.java:1252)
at java.base/sun.security.ssl.ClientHello$T13ClientHelloConsumer.consume(ClientHello.java:1188)
at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.onClientHello(ClientHello.java:851)
at java.base/sun.security.ssl.ClientHello$ClientHelloConsumer.consume(ClientHello.java:812)
at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:445)
at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:423)
at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:182)
at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:171)
at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1475)
at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1381)
... 9 more
The client throws the following:
the last modified time is: Mon Sep 28 00:44:21 CEST 2020
javax.net.ssl|DEBUG|15|Thread-4|2020-09-29 24:55:10.430 CEST|TrustStoreManager.java:334|Reload the trust store
javax.net.ssl|DEBUG|15|Thread-4|2020-09-29 24:55:10.468 CEST|TrustManagerFactoryImpl.java:70|SunX509: skip default keystore (
"throwable" : {
java.io.IOException: Keystore was tampered with, or password was incorrect
at java.base/sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:794)
at java.base/sun.security.util.KeyStoreDelegator.engineLoad(KeyStoreDelegator.java:241)
at java.base/java.security.KeyStore.load(KeyStore.java:1472)
at java.base/sun.security.ssl.TrustStoreManager$TrustAnchorManager.loadKeyStore(TrustStoreManager.java:390)
at java.base/sun.security.ssl.TrustStoreManager$TrustAnchorManager.getTrustedCerts(TrustStoreManager.java:336)
at java.base/sun.security.ssl.TrustStoreManager.getTrustedCerts(TrustStoreManager.java:56)
at java.base/sun.security.ssl.TrustManagerFactoryImpl.engineInit(TrustManagerFactoryImpl.java:49)
at java.base/javax.net.ssl.TrustManagerFactory.init(TrustManagerFactory.java:281)
at java.base/sun.security.ssl.SSLContextImpl.engineInit(SSLContextImpl.java:94)
at java.base/javax.net.ssl.SSLContext.init(SSLContext.java:313)
at connection.ServerConnection.connectToServer(ServerConnection.java:204)
at connection.ServerConnection.run(ServerConnection.java:42)
at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.security.UnrecoverableKeyException: Password verification failed
at java.base/sun.security.provider.JavaKeyStore.engineLoad(JavaKeyStore.java:792)
... 12 more}
At first i thought this has something to do with wrong pathing, so i tried a couple of ways mentioned on sof. But the error, that the password is incorrect or the keystore is tampered confuses me. The password cannot be wrong, because it is working in the IDE.
Why does the SSL work in my IDE, but not inside the .jar
I saw some threads about SSL not working at all, but not like this.
System property javax.net.ssl.trustStore requires that you pass a file in, and that file must.. exist.
entries in jars are file-like, but not files, so you cannot use a truststore file packed inside a jar file. That kinda explodes the point of a jar in the first place, and is why this isn't 'working' - you're running the jar from someplace where the working dir isn't proper. In general passing a relative entry (something that doesn't start with / or C:\ or whatnot) to javax.net.ssl.trustStore is never going to work in the hands of end users and requires careful scripting by the ops team if you try to deploy that on your own servers.
To load a trust store from any random source, such as 'a resource 'file' that is in the same place my class files live; look in the jar file if you have to', check this tutorial.

How to handle/surpress Java ElasticSearch ConnectTransportException

I am currently setting up a small project using elastic search in Java, and I am trying to figure out how to gracefully handle the 'ConnectTransportException' when my ElasticSearchCluster is down.
private TransportClient buildClient() {
TransportClient client = null;
try {
client = new PreBuiltTransportClient(Settings.EMPTY)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), 9300));
} catch(UnknownHostException ex) {
logger.error("Unknown host {}: {}", "localhost", ex.getMessage());
}
return client;
}
This code works fine. When my ElasticSearch cluster isn't running I want to be able to know if the client was not able to connect to it and log an appropriate message and then handle it appropriately.
Currently when the client can't connect to the cluster I get this error:
org.elasticsearch.transport.ConnectTransportException: [][127.0.0.1:9300] connect_timeout[30s]
at org.elasticsearch.transport.netty4.Netty4Transport.connectToChannels(Netty4Transport.java:370) ~[transport-netty4-client-5.3.0.jar:5.3.0]
at org.elasticsearch.transport.TcpTransport.openConnection(TcpTransport.java:495) ~[elasticsearch-5.3.0.jar:5.3.0]
at org.elasticsearch.transport.TcpTransport.connectToNode(TcpTransport.java:460) ~[elasticsearch-5.3.0.jar:5.3.0]
at org.elasticsearch.transport.TransportService.connectToNode(TransportService.java:314) ~[elasticsearch-5.3.0.jar:5.3.0]
at org.elasticsearch.client.transport.TransportClientNodesService$SimpleNodeSampler.doSample(TransportClientNodesService.java:408) [elasticsearch-5.3.0.jar:5.3.0]
at org.elasticsearch.client.transport.TransportClientNodesService$NodeSampler.sample(TransportClientNodesService.java:354) [elasticsearch-5.3.0.jar:5.3.0]
at org.elasticsearch.client.transport.TransportClientNodesService.addTransportAddresses(TransportClientNodesService.java:195) [elasticsearch-5.3.0.jar:5.3.0]
at org.elasticsearch.client.transport.TransportClient.addTransportAddress(TransportClient.java:322) [elasticsearch-5.3.0.jar:5.3.0]
at elk.aggregator.ElasticClient.buildClient(ElasticClient.java:72) [classes/:?]
at elk.aggregator.ElasticClient.<init>(ElasticClient.java:62) [classes/:?]
at elk.aggregator.ElasticClient.getInstance(ElasticClient.java:55) [classes/:?]
at elk.aggregator.App.main(App.java:9) [classes/:?]
Caused by: io.netty.channel.AbstractChannel$AnnotatedConnectException: Connection refused: localhost/127.0.0.1:9300
at sun.nio.ch.SocketChannelImpl.checkConnect(Native Method) ~[?:1.8.0_111]
at sun.nio.ch.SocketChannelImpl.finishConnect(SocketChannelImpl.java:717) ~[?:1.8.0_111]
at io.netty.channel.socket.nio.NioSocketChannel.doFinishConnect(NioSocketChannel.java:346) ~[netty-transport-4.1.7.Final.jar:4.1.7.Final]
at io.netty.channel.nio.AbstractNioChannel$AbstractNioUnsafe.finishConnect(AbstractNioChannel.java:340) ~[netty-transport-4.1.7.Final.jar:4.1.7.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:630) ~[netty-transport-4.1.7.Final.jar:4.1.7.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeysPlain(NioEventLoop.java:527) ~[netty-transport-4.1.7.Final.jar:4.1.7.Final]
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:481) ~[netty-transport-4.1.7.Final.jar:4.1.7.Final]
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:441) ~[netty-transport-4.1.7.Final.jar:4.1.7.Final]
at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:858) ~[netty-common-4.1.7.Final.jar:4.1.7.Final]
at java.lang.Thread.run(Thread.java:745) ~[?:1.8.0_111]
I want to be able to handle this gracefully by catching the error, but simply adding another catch block catching ConnectTransportException does not work.
Any idea how to do this?
You can seperate the code and handling for getting host and creating transport client then it will be more clear about the exception as below:
private boolean checkHostAvailability(String host, int port){
bool success = true;
try {
(new Socket(host, port)).close();
} catch (UnknownHostException e) {
success = false;
logger.error("Unknown host {}: {}", host, e.getMessage());
} catch (IOException e) {
success = false;
logger.error("Service not running host {}: {}, {}", host, port, e.getMessage());
}
retrun success;
}
private TransportClient buildClient() {
String host = "localhost";
int port = 9300;
if(checkHostAvailability(host,port){
TransportClient client = null;
try {
client = new PreBuiltTransportClient(Settings.EMPTY)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("localhost"), port));
} catch(Exception ex) {
}
return client;
}
}

How to connect to an SSL Server in Java that doesn't send a certificate?

I have a situation where an Open SSL server is running without a certificate as follows :
openssl s_server -accept 4443 -nocert
How do I connect to this server using Java? Also, how do I start my server in Java to accept no certificate?
I have attached the code for Client.java and Server.java that I have been using.
Error while running the attached code on the client side:
javax.net.ssl.SSLHandshakeException: Received fatal alert: handshake_failure
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.Alerts.getSSLException(Alerts.java:154)
at sun.security.ssl.SSLSocketImpl.recvAlert(SSLSocketImpl.java:1959)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:1077)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1312)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:702)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:122)
at sun.nio.cs.StreamEncoder.writeBytes(StreamEncoder.java:221)
at sun.nio.cs.StreamEncoder.implFlushBuffer(StreamEncoder.java:291)
at sun.nio.cs.StreamEncoder.implFlush(StreamEncoder.java:295)
at sun.nio.cs.StreamEncoder.flush(StreamEncoder.java:141)
at java.io.OutputStreamWriter.flush(OutputStreamWriter.java:229)
at Client.main(Client.java:27)
Error on the Server Side :
ERROR
140387701290656:error:1408A0C1:SSL routines:SSL3_GET_CLIENT_HELLO:no shared cipher:s3_srvr.c:1358:
shutting down SSL
CONNECTION CLOSED
ACCEPT
Client.java
public class Client {
public static void main(String[] arstring) {
try {
SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket("localhost", 4443);
//sslsocket.setEnabledCipherSuites(sslsocket.getSupportedCipherSuites());
sslsocket.setEnabledCipherSuites(new String[] { "TLS_DH_anon_WITH_AES_128_CBC_SHA" }); //Added upon suggestion from Steffan
boolean test = sslsocket.isConnected();
System.out.println(test);
InputStream inputstream = sslsocket.getInputStream();
InputStreamReader inputstreamreader = new InputStreamReader(inputstream);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
System.out.println("1");
OutputStream outputstream = sslsocket.getOutputStream();
System.out.println("2");
OutputStreamWriter outputstreamwriter = new OutputStreamWriter(outputstream,"UTF-8");
String str = "hello\n";
outputstreamwriter.write(str,0,str.length());
//outputstreamwriter.flush();
BufferedWriter bufferedwriter = new BufferedWriter(outputstreamwriter);
String string = null;
int count = 0;
string = bufferedreader.readLine();
while (true) {
System.out.println(string);
System.out.flush();
System.out.println(++count);
string = bufferedreader.readLine();
if (inputstream.available()==0)
break;
else{
System.out.print("StreamData:");
System.out.println(inputstream.available());
}
}
System.out.println("Out");
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
Server.java
public class Server {
public static void main(String[] arstring) {
try {
SSLServerSocketFactory sslServersocketFactory =
(SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket sslServerSocket =
(SSLServerSocket) sslServersocketFactory.createServerSocket(4443);
SSLSocket sslSocket = (SSLSocket) sslServerSocket.accept();
sslSocket.setEnabledCipherSuites(sslSocket.getSupportedCipherSuites());
if (sslSocket.isConnected())
System.out.println("Connected to a client");
InputStream inputStream = sslSocket.getInputStream();
InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
String command = "";
String response = "";
while ((command = bufferedReader.readLine()) != null) {
System.out.println("Command Recieved: "+command);
if (command.toLowerCase().compareTo("hello")==0)
response = "Bingo !! You got it write!\n";
else
response = "Type Hello to see a response\n";
OutputStream outputStream = sslSocket.getOutputStream();
OutputStreamWriter outputStreamWriter = new OutputStreamWriter(outputStream,"UTF-8");
outputStreamWriter.write(response, 0, response.length());
outputStreamWriter.flush();
}
} catch (Exception exception) {
exception.printStackTrace();
}
}
}
Edit:
I think I need to use the anonymous DH Cipher but it's still not working. May be I am doing it wrong. The code has been edited too.
How to connect to an SSL Server in Java that doesn't send a certificate?
If its not sending a certificate, then its probably using (1) one of the preshared keys cipher suites, like TLS-SRP or TLS-PSK, or (2) its using Anonymous Diffie-Hellman.
The preshared key cipher suites are usually choices because they provide mutual authentication and channel binding.
Anonymous Diffie-Hellman is usually a bad choice because it lacks server authentication.
I have a situation where an Open SSL server is running without a certificate as follows : openssl s_server -accept 4443 -nocert
Well, there you have it.
How do I connect to this server using Java? Also, how do I start my server in Java to accept no certificate?
Use a cipher suite that includes an anonymous exchange, like:
ADH-DES-CBC3-SHA
ADH-AES128-SHA
ADH-AES256-SHA
ADH-CAMELLIA128-SHA
ADH-CAMELLIA256-SHA
ADH-SEED-SHA
ADH-AES128-SHA256
ADH-AES256-SHA256
ADH-AES128-GCM-SHA256
ADH-AES256-GCM-SHA384
You can get the mapping of ADH-AES128-SHA to TLS_DH_anon_WITH_AES_128_CBC_SHA at the openssl ciphers man page.
You might try the command:
openssl s_server -accept 4443 -tls1 -nocert -cipher "HIGH"
By enabling TLS1, you side step any potential issues where one side or the other disables SSLv2 and SSLv3 (which is a good thing), but you only provide SSLv3 (which is a bad thing).
The cipher suite list string "HIGH" includes ADH by default (in production, usually you do "HIGH:!ADH:!RC4:!MD5...").

Why does my SOCKS proxy code throw SocketException: Malformed reply from SOCKS server?

Why does my SOCKS proxy code throw SocketException: Malformed reply from SOCKS server? I've tried to set in URLConnection or other, but this doesn't work. Only thing that worked - chilkat lib, but it's commercial. So, how I, for example, make http request through a ASOCKS proxy? Maybe exist some free lib for that?
For example, that code:
SocketAddress addr = new InetSocketAddress(proxy_ip, proxy_port);
Proxy proxy = new Proxy(Proxy.Type.SOCKS, addr);
Socket socket = new Socket(proxy);
InetSocketAddress dest = new InetSocketAddress("google.com", 80);
try {
socket.connect(dest);
} catch (IOException ex) {
Logger.getLogger(CheckProxy.class.getName()).log(Level.SEVERE, null, ex);
}
Throws exception:
java.net.SocketException: Malformed reply from SOCKS server
at java.net.SocksSocketImpl.readSocksReply(Unknown Source)
at java.net.SocksSocketImpl.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at java.net.Socket.connect(Unknown Source)
at proxychecker.CheckProxy.SocksCheck(CheckProxy.java:86)
Where line 86 is "socket.connect(dest);"
Explanation of this bug: bugs.java.com/view_bug.do?bug_id=6964547
You need to manually change mode in Socket object using this code:
Class clazzSocks = socket.getClass();
Method setSockVersion = null;
Field sockImplField = null;
SocketImpl socksimpl = null;
try {
sockImplField = clazzSocks.getDeclaredField("impl");
sockImplField.setAccessible(true);
socksimpl = (SocketImpl) sockImplField.get(socket);
Class clazzSocksImpl = socksimpl.getClass();
setSockVersion = clazzSocksImpl.getDeclaredMethod("setV4");
setSockVersion.setAccessible(true);
if(null != setSockVersion){
setSockVersion.invoke(socksimpl);
}
sockImplField.set(socket, socksimpl);
} catch (Exception e) {
}
SocketException: Malformed reply from SOCKS server
That indicates that you don't have a SOCKS proxy at all. Possibly it is an HTTP proxy.
And note that you asked the wrong question. Your code was correct, it was your premiss that was wrong.

MySQL jdbc + SSL

I set system properties for a SSL-enabled MySQL client, which worked fine:
System.setProperty("javax.net.ssl.trustStore","truststore");
System.setProperty("javax.net.ssl.trustStorePassword","12345");
String url = "jdbc:mysql://abc.com:3306/test?" +
"user=abc&password=123" +
"&useUnicode=true" +
"&characterEncoding=utf8&useSSL=true"
A couple days ago I found the client couldn't connect to another web site in which a commercially signed SSL certificate is installed. Obviously the overriding keystores didn't work with regular https connections.
Then I decided to build my version of SocketFactory based on StandardSocketFactory.java in MySQL Connector/J source.
I added a method to create Socket objects in public Socket connect(String hostname, int portNumber, Properties props) method.
private Socket createSSLSocket(InetAddress address, int port) {
Socket socket;
try {
InputStream trustStream = new FileInputStream(new File("truststore"));
KeyStore trustStore = KeyStore.getInstance("JKS");
// load the stream to your store
trustStore.load(trustStream, trustPassword);
// initialize a trust manager factory with the trusted store
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance("PKIX", "SunJSSE"); trustFactory.init(trustStore);
// get the trust managers from the factory
TrustManager[] trustManagers = trustFactory.getTrustManagers();
// initialize an ssl context to use these managers and set as default
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustManagers, null);
if(address == null) {
socket = sslContext.getSocketFactory().createSocket();
} else {
socket = sslContext.getSocketFactory().createSocket(address, port);
}
} catch (Exception e) {
System.out.println(e.getLocalizedMessage());
return null;
}
return socket;
}
The url passed to jdbc driver is changed to:
String url = "jdbc:mysql://abc.com:3306/test?" +
"user=abc&password=123" +
"&useUnicode=true" +
"&characterEncoding=utf8&useSSL=true" +
"&socketFactory=" + MySocketFactory.class.getName();
The client did execute my version createSSLSocket() and return a Socket object. However, I got the following Exceptions after continuing the execution:
com.mysql.jdbc.exceptions.jdbc4.CommunicationsException:
Communications link failure
The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server.
javax.net.ssl.SSLException:
Unrecognized SSL message, plaintext connection?
I'm sure the MySQL was up and running, the address and port passed to createSSLSocket() were correct. Could anyone help? The client has to communicate to 2 sites at the same time: an HTTPS web server and a self-signed MySQL server.

Categories