How can I use a SSLSocket with a socks5 proxy? I use a normal socket with proxy as underlying.
This code does not work:
public void debugIP(Proxy proxy) throws IOException, NoSuchAlgorithmException, KeyManagementException {
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, null, null);
Socket underlying = new Socket(proxy);
InetSocketAddress proxyAddress = (InetSocketAddress) proxy.address();
underlying.connect(new InetSocketAddress("checkip.amazonaws.com", 80));
SSLSocket socket = (SSLSocket) sslContext.getSocketFactory().createSocket(
underlying,
proxyAddress.getHostName(),
proxyAddress.getPort(),
true);
printInputStream(socket.getInputStream());
}
private void printInputStream(InputStream inputStream) throws IOException {
BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
}
This code is throwing exceptions:
Exception in thread "main" javax.net.ssl.SSLException: Unrecognized SSL message, plaintext connection?
Without SSL the code works.
You are talking SSL to a plaintext port.
Just as the error message says.
Either fix the port or don't use SSL.
Related
I am currently working on a university little project in which we should make an android application which can communicate with a java SSL Socket. I am kinda new on the SSL connections, I red about keystores and stuff but I didn't really get it.
This is the Android side:
SSLSocketFactory socketFactory;
SSLSocket socket;
socketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
try {
socket = (SSLSocket) socketFactory.createSocket("192.168.1.131", 7070);
System.out.println("Connected!");
} catch (IOException e) {
e.printStackTrace();
}
This is the java server one:
SSLServerSocketFactory socketFactory = (SSLServerSocketFactory) SSLServerSocketFactory.getDefault();
SSLServerSocket serverSocket = (SSLServerSocket) socketFactory.createServerSocket(7070);
serverSocket.setEnabledProtocols(new String[] {"TLSv1.3"});
while (true) {
// wait for client connection and check login information
try {
System.err.println("Waiting for connection...");
SSLSocket socket = (SSLSocket) serverSocket.accept();
System.out.println("Connessione Accettata");
// open BufferedReader for reading data from client
BufferedReader input = new BufferedReader(new InputStreamReader(socket.getInputStream()));
// open PrintWriter for writing data to client
System.out.println(input);
//PrintWriter output = new PrintWriter(new OutputStreamWriter(socket.getOutputStream()));
//output.close();
input.close();
socket.close();
} // end try
// handle exception communicating with client
catch (IOException ioException) {
ioException.printStackTrace();
}
}
Obviously the sockets don't even connect each other, what should I implement to make it work?
I am writing a test class for a networking module which establishes a SSL connection used for sending messages. The Junit 4 test class sets up a client side keystore and truststore along with a server side keystore. These variables are used in setting up client side and server side SSLContexts from which I get SSLServerSocket and SSLSocket necessary for setting up a connection through their respective factories.
The SSLServerSocket successfully accepts the connection of my SSLSocket on localhost at the same port. However when I call the SSLSocket.getInputStream() method on the server side socket it hangs whereas calling the SSLSocket.getOutputStream() mehtod on the client side is successful. I am aware that this stage is responsible for initiating the SSL handshake but through my search I have found little on what could be causing a single side to hand. Someone elses post on a separate site mentioned that is could be a reverse dns lookup hanging how would I prevent this? I also tried explicitly starting the handshake in the first of the two Callable threads which hung in a similar fashion. This is my test class:
public class ReceiverClientThreadTest {
// ADD REG AND A SINGLE NETWORK
// ESTABLISH A TLS CONNECTION BETWEEN TWO POINTS WITH
private final static String KEY_MANAGER = "SunX509";
private final static String TLS_VERSION = "TLSv1.2";
private final static String RNG_ALGORITHM = "DEFAULT";
private final static String RNG_PROVIDER = "BC";
private static final String PROVIDER = "BC";
private static final String KEYSTORE_TYPE = "PKCS12";
private static KeyStore keyStore1, keyStore2, trustStore2;
private SSLSocket serverSocket;
private SSLSocket clientSocket;
#BeforeClass
public static void setUp() throws SQLException, GeneralSecurityException, OperatorCreationException, IOException {
String name1 = "localhost", name2 = "client";
KeyPair kp1 = SecurityUtilities.generateKeyPair();
KeyPair kp2 = SecurityUtilities.generateKeyPair();
X509Certificate cert1 = SecurityUtilities.makeV1Certificate(kp1.getPrivate(), kp1.getPublic(), name1);
X509Certificate cert2 = SecurityUtilities.makeV1Certificate(kp2.getPrivate(), kp2.getPublic(), name2);
keyStore1 = KeyStore.getInstance(KEYSTORE_TYPE, PROVIDER);
keyStore2 = KeyStore.getInstance(KEYSTORE_TYPE, PROVIDER);
trustStore2 = KeyStore.getInstance(KEYSTORE_TYPE, PROVIDER);
keyStore1.load(null, null);
keyStore1.setKeyEntry(name1, kp1.getPrivate(), "relaypass".toCharArray(), new X509Certificate[]{cert1});
// keyStore2.load(null, null);
// keyStore2.setKeyEntry(name2, kp2.getPrivate(), null, new X509Certificate[]{cert2});
trustStore2.load(null, null);
trustStore2.setCertificateEntry(name2, cert1);
// secureSocketManager = new SecureSocketManager(keyStore1, password);
}
#Before
public void init() throws IOException, GeneralSecurityException, InterruptedException, ExecutionException {
SSLServerSocket sslServerSocket = getSSLServerSocket();
SSLSocketFactory sslSocketFactory = getSSLSocketFactory();
ExecutorService pool = Executors.newFixedThreadPool(2);
Callable<SSLSocket> c1 = () -> {
return (SSLSocket) sslServerSocket.accept();
};
Callable<SSLSocket> c2 = () -> {
return (SSLSocket) sslSocketFactory.createSocket("localhost", 2048);
};
Future<SSLSocket> server = pool.submit(c1);
Thread.sleep(1000);
Future<SSLSocket> client = pool.submit(c2);
Thread.sleep(1000);
serverSocket = server.get();
clientSocket = client.get();
}
#After
public void tearDown(){
serverSocket = null;
clientSocket = null;
}
#org.junit.Test
public void endSession(){
Thread test = new Thread(new ReceiverClientThread(serverSocket));
test.start();
try (ObjectOutputStream output = new ObjectOutputStream(new BufferedOutputStream(clientSocket.getOutputStream()))) {
System.out.println("here");
}catch (IOException e){
fail();
}
}
private SSLServerSocket getSSLServerSocket() throws GeneralSecurityException, IOException {
char[] entryPassword = "relaypass".toCharArray();
// COULD ADD PROVIDER IN THESE FOR CONSISTENCY
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("PKIX", "BCJSSE");
keyManagerFactory.init(keyStore1, entryPassword);
// specify TLS version e.g. TLSv1.3
SSLContext sslContext = SSLContext.getInstance(TLS_VERSION, "BCJSSE");
sslContext.init(keyManagerFactory.getKeyManagers(),null, null);
SSLServerSocketFactory fact = sslContext.getServerSocketFactory();
return (SSLServerSocket) fact.createServerSocket(2048 );
}
private SSLSocketFactory getSSLSocketFactory() throws GeneralSecurityException{
char[] entryPassword = "relaypass".toCharArray();
// COULD ADD PROVIDER IN THESE FOR CONSISTENCY
// KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KEY_MANAGER, "BCJSSE");
// keyManagerFactory.init(keyStore1, entryPassword);
TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("PKIX", "BCJSSE");
trustManagerFactory.init(trustStore2);
// specify TLS version e.g. TLSv1.3
SSLContext sslContext = SSLContext.getInstance(TLS_VERSION, "BCJSSE");
sslContext.init(null,trustManagerFactory.getTrustManagers(), null);
return sslContext.getSocketFactory();
}
This is the class which it is testing and the only relevant line, the one where the code hangs is commented as such:
public class ReceiverClientThread implements Runnable {
private final SSLSocket sslSocket;
public ReceiverClientThread(SSLSocket sslSocket) {
this.sslSocket = sslSocket;
}
public void run() {
try (ObjectInputStream input = new ObjectInputStream(new BufferedInputStream(sslSocket.getInputStream()))) {
System.out.println("here");
} catch (IOException e) {
}
}
}
Thanks
You could set a timeout on your sslSocket, so that if it hangs during stream read, it will only hang for a set period of time and then will throw an exception. This way the thread will not just hang indefinitely.
sslSocket.setSoTimeout(120000); // timeout of 2 min
public static Socket createSsl(Socket socket) throws IOException {
SSLSocketFactory factory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslsocket = (SSLSocket) (factory.createSocket(socket, socket
.getInetAddress().getHostAddress(), socket.getPort(), true));
sslsocket.setUseClientMode(false);
sslsocket.startHandshake();
return sslsocket;
}
the sslsocket always read time out when sslsocket.startHandshake(), so what should I do to solve the problem?
I need to develop a client-server desktop application with SSL sockets in Java. One of the requirements is to encrypt messages.
I'm trying out some internet example codes just to know how to make the encrypted connection. The examples seem to work fine, or at least they do not generate errors, however I have to verify from Wireshark that messages are actually encrypted, but in wireshark I only see TCP packets. I have the certificates and keystores correct, in my opinion.
JavaSSLServer.java
/**
#web http://java-buddy.blogspot.com/
*/
public class JavaSSLServer {
static final int port = 8000;
public static void main(String[] args) {
System.setProperty("javax.net.ssl.keyStore","/home/jose/serverKey.jks");
System.setProperty("javax.net.ssl.keyStorePassword","servpass");
SSLServerSocketFactory sslServerSocketFactory =
(SSLServerSocketFactory)SSLServerSocketFactory.getDefault();
try {
ServerSocket sslServerSocket =
sslServerSocketFactory.createServerSocket(port);
System.out.println("SSL ServerSocket started");
System.out.println(sslServerSocket.toString());
Socket socket = sslServerSocket.accept();
System.out.println("ServerSocket accepted");
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
try (BufferedReader bufferedReader =
new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
String line;
while((line = bufferedReader.readLine()) != null){
System.out.println(line);
out.println(line);
}
}
System.out.println("Closed");
} catch (IOException ex) {
Logger.getLogger(JavaSSLServer.class.getName())
.log(Level.SEVERE, null, ex);
}
}}
JavaSSLClient.java
/**
#web http://java-buddy.blogspot.com/
*/
public class JavaSSLClient {
static final int port = 8000;
public static void main(String[] args) {
System.setProperty("javax.net.ssl.trustStore", "/home/jose/clientTrustedCerts.jks");
System.setProperty("javax.net.ssl.trustStorePassword", "clientpass");
SSLSocketFactory sslSocketFactory =
(SSLSocketFactory)SSLSocketFactory.getDefault();
try {
Socket socket = sslSocketFactory.createSocket("localhost", port);
PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
try (BufferedReader bufferedReader =
new BufferedReader(
new InputStreamReader(socket.getInputStream()))) {
Scanner scanner = new Scanner(System.in);
while(true){
System.out.println("Enter something:");
String inputLine = scanner.nextLine();
if(inputLine.equals("q")){
break;
}
out.println(inputLine);
System.out.println(bufferedReader.readLine());
}
}
} catch (IOException ex) {
Logger.getLogger(JavaSSLClient.class.getName())
.log(Level.SEVERE, null, ex);
}
}
}
I added the System.setProperty (...
In Wireshark:
Other example:
https://github.com/chuidiang/chuidiang-ejemplos-google-code/commit/2843dafc0a942c2dd636f7e2e1f9be6fe0b9e9ec
The results in Wireshark were similar.
I want to establish a connection with SSL sockets that encrypts the messages between the client and server, and that can be verified from Wireshark (that is another requirement).
My questions are:
How do I verify that the message is actually encrypted using wireshark?
Should I see SSL / TLS packets instead of TCP to conclude that they are encrypted?
Can you tell me if some of the example code is wrong or incomplete?
Your client and server are codes are exchanging plain text messages, so if you don't see that plain text in the TCP packets then the messages are likely being encrypted (which they should be, given the code shown).
To verify, you can filter the Wireshark capture on the two IP/Port pairs of the connection, then decode that TCP stream as TLS, and see if that succeeds. If so, it will show the first few packets of the connection (after the TCP 3-way handshake) are an unencrypted TLS handshake (exchanging the certificates and negotiating the encryption values), and the subsequent packets are encrypted TLS packets.
I have a project in which HttpsURLConnection is configed to use a customized TrustManager as following:
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[]{new MyTrustManager()}, null);
HttpsURLConnection.setDefaultSSLSocketFactory(sslContext.getSocketFactory());
There is a REST API client in this project, it uses Jersey client to send HTTP/HTTPS request:
Client client = ClientBuilder.newClient();
However, the HTTPS connection initiated by this Jerset client does not use the defaultSSLSocketFactory I set in HttpsURLConnection and it fails to connect to untrusted HTTPS url.
I need to explicitly set the SslContext on this client to make it work with my TrustManager.
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, new TrustManager[]{new MyTrustManager()}, null);
Client client = ClientBuilder.newBuilder().sslContext(sslContext).build();
Is there any way to solve this issue?
Thanks.
The solution I eventually found is to set the SSLSocketFactory provider property to a customized SSLSocketFactory. Hope this can help others who have similar issues.
Call this in beginning of the program:
Security.setProperty("ssl.SocketFactory.provider", MySSLSocketFactory.class.getCanonicalName());
Here is how MySSLSocketFactory looks like (it also sets connection timeout):
public class MySSLSocketFactory extends SSLSocketFactory {
private SSLContext sslContext = SSLContext.getInstance(Const.Ssl.PROTOCOL_SSL);
public MySSLSocketFactory() throws NoSuchAlgorithmException, KeyManagementException {
this.sslContext.init(
null,
new TrustManager[] { new MyTrustManager(false) },
new SecureRandom());
}
#Override
public Socket createSocket(Socket socket, String host, int port, boolean autoClose)
throws IOException {
socket.connect(new InetSocketAddress(host, port), Const.Ssl.CONNECT_TIMEOUT);
socket.setSoTimeout(Const.Ssl.DATA_TIMEOUT);
return this.sslContext.getSocketFactory().createSocket(socket, host, port, autoClose);
}
#Override
public String[] getDefaultCipherSuites() {
return this.sslContext.getSocketFactory().getDefaultCipherSuites();
}
#Override
public String[] getSupportedCipherSuites() {
return this.sslContext.getSocketFactory().getSupportedCipherSuites();
}
#Override
public Socket createSocket(String host, int port)
throws IOException, UnknownHostException {
return this.createSocket(new Socket(), host, port, true);
}
#Override
public Socket createSocket(InetAddress address, int port)
throws IOException {
return this.createSocket(new Socket(), address.getHostAddress(), port, true);
}
#Override
public Socket createSocket(String host, int port, InetAddress localHost, int localPort)
throws IOException, UnknownHostException {
return this.createSocket(new Socket(), host, port, true);
}
#Override
public Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort)
throws IOException {
return this.createSocket(new Socket(), address.getHostAddress(), port, true);
}