How to connect a SSL socket through a HTTP proxy?
Combine MacDaddy's answer and Viktor Mukhachev's comment, use SSLSocket
over a Socket
over a Proxy
.
Code:
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Socket;
import java.nio.charset.StandardCharsets;
public class SSLThroughProxy {
public static void main(String[] args) throws IOException {
final String REQUEST = "GET / HTTP/1.1\r\n" +
"Host: github.com\r\n" +
"Connection: close\r\n" +
"\r\n";
Proxy proxy = new Proxy(Proxy.Type.HTTP, new InetSocketAddress("your-proxy-host", 8080));
Socket socket = new Socket(proxy);
InetSocketAddress address = new InetSocketAddress("github.com", 443);
socket.connect(address);
SSLSocketFactory sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(socket, address.getHostName(), address.getPort(), true);
sslSocket.startHandshake();
sslSocket.getOutputStream().write(REQUEST.getBytes());
InputStream inputStream = sslSocket.getInputStream();
byte[] bytes = inputStream.readAllBytes();
System.out.println(new String(bytes, StandardCharsets.UTF_8));
sslSocket.close();
}
}
You have to use javax.net lib . you can archive to your target using javax.net.ssl.*.
I think you can get solution using oracle docs. Here is the link for that.
SSLSocketClientWithTunneling
I don't have time to test/write a targetted solution now, however Upgrading socket to SSLSocket with STARTTLS: recv failed seems to cover the basic problem.
In your case, you need to connect to the proxy, issue a proxy connect, then upgrade the connection - essentially you CONNECT takes the place of the STARTTLS in the referenced question, and the check for " 670 " is not needed.
java.net.Proxy
, or the https.proxyHost/proxyPort
properties, only support HTTP proxying via HttpURLConnection,
not via a Socket.
To make that work for an SSLSocket
of your own, all you need to to is create a plaintext socket, issue an HTTP CONNECT
command on it, check the response for 200, and then wrap it in an SSLSocket.
EDIT When sending the CONNECT command, you must not close the socket, of course; and when reading its reply you must not use a BufferedReader,
otherwise you will lose data; either read the line by hand or use DataInputStream.readLine(),
despite its deprecation. You also need to follow RFC 2616 entirely.