0

I need to access some https soap services through a http proxy tunnel. So I am using org.apache.http.impl.client.ProxyClient to connect to the target host through proxy tunnel. Which returns me a socket connected to the target host through the proxy server. The returned socket is connected properly to the target system. Now I need to invoke soap services hosted in the target system. But I am clueless how can I access those https services through socket. Below is my sample program. Sample url for service that needs to be invoked https://XX.XX.XX.XX:44330/sampleService/1.0

public static void proxyTunnelDemo(String url,String soapRequestBody) throws IOException, HttpException {
    ProxyClient proxyClient = new ProxyClient();
    HttpHost target = new HttpHost("XX.XX.XX.XX", 44330);
    HttpHost proxy = new HttpHost("YY.YY.YY.YY", 9293);
    UsernamePasswordCredentials credentials = new UsernamePasswordCredentials("********", "********");
    Socket socket = proxyClient.tunnel(proxy, target, credentials);

    // Need to access Web service through socket .
    // request method GET 
    // PORT  = 44330
    // url = https://XX.XX.XX.XX:44330/sampleService/1
    //soapRequestBody =  soap message needs to be sent.
String SOAP_CREDENTIALS = "*********";
SSLSocketFactory factory =  (SSLSocketFactory)SSLSocketFactory.getDefault();
    SSLSocket sslSocket = (SSLSocket)factory.createSocket(socket, target.getHostName(), target.getPort(), true);
    sslSocket.startHandshake();

try {


        //Send header
        BufferedWriter wr = new BufferedWriter(new OutputStreamWriter(sslSocket.getOutputStream(), StandardCharsets.UTF_8));
        String authorization  =  new BASE64Encoder().encode(SOAP_CREDENTIALS.getBytes());
        // You can use "UTF8" for compatibility with the Microsoft virtual machine.

        wr.write("GET / HTTP/1.1\r\n");
        wr.write("Host: "+target.getHostName()+"\r\n");
        wr.write("Content-Length:"+ soapRequestBody.length() + "\r\n");
        wr.write("Content-Type: text/html\"\r\n");
        wr.write("SOAPAction:"+url+"\r\n");
        wr.write("Authorization: Basic "+authorization+"\r\n");
        wr.write("\r\n ");           //Send data
        wr.write(soapRequestBody);
        wr.flush();

        BufferedReader in = new BufferedReader(
                new InputStreamReader(sslSocket.getInputStream(), StandardCharsets.UTF_8));
        String line = null;
        while ((line = in.readLine()) != null) {
            System.out.println(line);
        }

    } finally {
        socket.close();
        sslSocket.close();
    }
}

With the above code getting error response below
HTTP/1.1 400 Error X-Backside-Transport: FAIL FAIL Content-Type: text/xml Connection: close

Angshuman
  • 225
  • 3
  • 17

1 Answers1

0

You have already established connection with XX.XX.XX.XX on port 44330. Next you need to pass this socket to an SSLSocket like this

SSLSocketFactory factory =  (SSLSocketFactory)SSLSocketFactory.getDefault();
 SSLSocket sslSocket = (SSLSocket)factory.createSocket(socket, host, port, true);

Then you can do a SSL handshake with the webserver

socket.startHandShake();

And then use printwriter to read/write from the socket

https://docs.oracle.com/javase/tutorial/networking/sockets/readingWriting.html

Full Example here :

https://docs.oracle.com/javase/7/docs/technotes/guides/security/jsse/samples/sockets/client/SSLSocketClientWithTunneling.java

Monish Sen
  • 1,773
  • 3
  • 20
  • 32
  • edited according to your answer. But getting error response. Please check the updated post. – Angshuman May 10 '17 at 12:15
  • @Angshuman it looks like you are able to talk to the webservice, which if I may say, seems to be IBM Datapower Soap API. You are getting a serverside response code 400. If i were to make a guess, your soap request is bad. But that is not relevant to this thread. If your original question is solved, please accept the answer or if it is partially solved, upvote it – Monish Sen May 11 '17 at 11:07