• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 929
  • Last Modified:

java ssl gateway timeout https

Dear experts,

I am trying to connect to a website through a proxy but i get a gateway timeout status 504
I am using this code:
public class SSLSocketClientWithTunneling {

    public static void main(String[] args) throws Exception {
	//new SSLSocketClientWithTunneling().doIt("www.google.com:443/HTTPS", 443);
new SSLSocketClientWithTunneling().doIt("https://necsapi.statnett.no:443/HTTPS", 443);
    }

    String tunnelHost;
    int tunnelPort;

    public void doIt(String host, int port) {
	try {

	    /*
	     * Let's setup the SSLContext first, as there's a lot of
	     * computations to be done.  If the socket were created
	     * before the SSLContext, the server/proxy might timeout
	     * waiting for the client to actually send something.
	     */
	    SSLSocketFactory factory =
		(SSLSocketFactory)SSLSocketFactory.getDefault();

	    /*
	     * Set up a socket to do tunneling through the proxy.
	     * Start it off as a regular socket, then layer SSL
	     * over the top of it.
	     */
       System.setProperty("https.proxyPort","8080");
       System.setProperty("https.proxyHost","myproxy");
       
       tunnelHost = System.getProperty("https.proxyHost");
       tunnelPort = Integer.getInteger("https.proxyPort").intValue();
       
      String keystoreFilename = System.getProperty("java.home")
        + "/lib/security/cacerts".replace('/', File.separatorChar);

    char[] password = "mypassword".toCharArray();
    String alias = "thecertificate";

    FileInputStream fIn = new FileInputStream(keystoreFilename);
    KeyStore keystore = KeyStore.getInstance("JKS");
    keystore.load(fIn, password);
    
	    Socket tunnel = new Socket(tunnelHost, tunnelPort);
	    doTunnelHandshake(tunnel, host, port);

	    /*
	     * Ok, let's overlay the tunnel socket with SSL.
	     */
	    SSLSocket socket =
		(SSLSocket)factory.createSocket(tunnel, host, port, true);

	    /*
	     * register a callback for handshaking completion event
	     */
	    socket.addHandshakeCompletedListener(
		new HandshakeCompletedListener() {
		    public void handshakeCompleted(
			    HandshakeCompletedEvent event) {
			System.out.println("Handshake finished!");
			System.out.println(
			    "\t CipherSuite:" + event.getCipherSuite());
			System.out.println(
			    "\t SessionId " + event.getSession());
			System.out.println(
			    "\t PeerHost " + event.getSession().getPeerHost());
		    }
		}
	    );

	    /*
	     * send http request
	     *
	     * See SSLSocketClient.java for more information about why
	     * there is a forced handshake here when using PrintWriters.
	     */
	    socket.startHandshake();

	    PrintWriter out = new PrintWriter(
				  new BufferedWriter(
				  new OutputStreamWriter(
     				  socket.getOutputStream())));

	    out.println("GET / HTTP/1.0");
	    out.println();
	    out.flush();

	    /*
	     * Make sure there were no surprises
	     */
	    if (out.checkError())
		System.out.println(
		    "SSLSocketClient:  java.io.PrintWriter error");

	    /* read response */
	    BufferedReader in = new BufferedReader(
				    new InputStreamReader(
				    socket.getInputStream()));

	    String inputLine;

	    while ((inputLine = in.readLine()) != null)
		System.out.println(inputLine);

	    in.close();
	    out.close();
	    socket.close();
	    tunnel.close();
	} catch (Exception e) {
	    e.printStackTrace();
	}
    }

    /*
     * Tell our tunnel where we want to CONNECT, and look for the
     * right reply.  Throw IOException if anything goes wrong.
     */
    private void doTunnelHandshake(Socket tunnel, String host, int port)
    throws IOException
    {
	OutputStream out = tunnel.getOutputStream();
	String msg = "CONNECT " + host + ":" + port + " HTTP/1.0\n"
		     + "User-Agent: "
		     + sun.net.www.protocol.http.HttpURLConnection.userAgent
		     + "\r\n\r\n";
	byte b[];
	try {
	    /*
	     * We really do want ASCII7 -- the http protocol doesn't change
	     * with locale.
	     */
	    b = msg.getBytes("ASCII7");
	} catch (UnsupportedEncodingException ignored) {
	    /*
	     * If ASCII7 isn't there, something serious is wrong, but
	     * Paranoia Is Good (tm)
	     */
	    b = msg.getBytes();
	}
	out.write(b);
	out.flush();

	/*
	 * We need to store the reply so we can create a detailed
	 * error message to the user.
	 */
	byte		reply[] = new byte[200];
	int		replyLen = 0;
	int		newlinesSeen = 0;
	boolean		headerDone = false;	/* Done on first newline */

	InputStream	in = tunnel.getInputStream();
	boolean		error = false;

	while (newlinesSeen < 2) {
	    int i = in.read();
	    if (i < 0) {
		throw new IOException("Unexpected EOF from proxy");
	    }
	    if (i == '\n') {
		headerDone = true;
		++newlinesSeen;
	    } else if (i != '\r') {
		newlinesSeen = 0;
		if (!headerDone && replyLen < reply.length) {
		    reply[replyLen++] = (byte) i;
		}
	    }
	}

	/*
	 * Converting the byte array to a string is slightly wasteful
	 * in the case where the connection was successful, but it's
	 * insignificant compared to the network overhead.
	 */
	String replyStr;
	try {
	    replyStr = new String(reply, 0, replyLen, "ASCII7");
	} catch (UnsupportedEncodingException ignored) {
	    replyStr = new String(reply, 0, replyLen);
	}

	/* We asked for HTTP/1.0, so we should get that back */
	if (!replyStr.startsWith("HTTP/1.0 200")) {
	    throw new IOException("Unable to tunnel through "
		    + tunnelHost + ":" + tunnelPort 
		    + ".  Proxy returns \"" + replyStr + "\"");
	}

	/* tunneling Handshake was successful! */
    }
}

Open in new window


This code works if i do:       new SSLSocketClientWithTunneling().doIt("www.google.com:443/HTTPS", 443);
instead of:
new SSLSocketClientWithTunneling().doIt("https://necsapi.statnett.no:443/HTTPS", 443);

I hope someone can help me!

KInd regards,

Mark
0
MarkVrenken
Asked:
MarkVrenken
  • 8
  • 8
1 Solution
 
girionisCommented:
Can you access the https://necsapi.statnett.no from a browser?
0
 
MarkVrenkenAuthor Commented:
Yes i can, I then have to select the certificate. I think I got a little further but now i get
java.io.IOException: Unable to tunnel through "myProxy" Proxy returns "HTTP/1.0 403 Forbidden"
0
 
girionisCommented:
When you read the keystore, are you sure you read the correct one?
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
MarkVrenkenAuthor Commented:
Yes. I added it to cacerts, and get the right certificate.
0
 
girionisCommented:
Do you send the correct username/password?
0
 
MarkVrenkenAuthor Commented:
I fixed the 403 error. It was because I set my forward to the proxy as
https://necsapi.statnett.no:443/HTTPS" but this was already added in my code, stupid me!

so the proxy forwarded this tunnel://https://necsapi.statnett.no:443/HTTPS/1.0:443
so instead I used this necsapi.statnett.no which then is forwarded as tunnel://necsapi.statnett.no:443

but now i get the following error which your questions were leading to. namely i get this error:PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

I don't know how I should edit my code to add the right certificate. I know I added the right certificate to my cacerts. but I'm not sure how to access this in Java and present it to the server
0
 
girionisCommented:
0
 
MarkVrenkenAuthor Commented:
Thank you this solved the next problem. Now I can access the site but I get the websites 403 page. (I print the page this is a part of the page):

</head>
       PeerHost necsapi.statnett.no
<body>
<div id="header"><h1>Error</h1></div>
<div id="content">
 <div class="content-container"><fieldset>
  <h2>Forbidden: Access is denied.</h2>
  <h3>You do not have permission to view this directory or page using the credentials that you supplied.</h3>

 </fieldset></div>
</div>
</body>
</html>

So something is wrong with me presenting the server certificate? I don't know how I should approach this problem. I have received a certificate (.pfx) from the server people which I installed for my browser. So when I browse to the page, I get prompted to select the certificate and I can view the content. However through java I have to do this in another way. So my question now is: How do I present the certificate to the server so that I get "logged in"?

Thanks for your help I appreciate it!
0
 
girionisCommented:
It doesn't have to do with the certificate, it looks like a problem with the site, it's probably password protected. You need to authenticate yourself with a user/pass.
0
 
MarkVrenkenAuthor Commented:
Okay, but why can i access the site through my browser then? On the browser I only have to select the certificate.
0
 
girionisCommented:
Maybe the browser is using cookies to identify you. Try something else. Delete all the cookies for this site and load it again from the browser.
0
 
MarkVrenkenAuthor Commented:
I have never had to insert any credentials in the browser, just the certificate selection
0
 
girionisCommented:
Then the only reasonable explanation is that the browser redirects you to another page. Since you cannot follow the redirection from your application you get the forbidden error message. Do something else. If you use firefox install Live HTTP headers and have a look at the request. You will see if it redirects you to another page or not.
0
 
MarkVrenkenAuthor Commented:
I didn't have firefox, I installed it but I get the forbidden access denied for the site(403).
This is not in chrome nor IE, so that's strange....
0
 
MarkVrenkenAuthor Commented:
HTTP request status: 200 (OK)
Name      Value
Date      Thu, 31 Jan 2013 14:26:22 GMT
X-Content-Type-Options      nosniff
Server      Microsoft-IIS/7.5
X-AspNet-Version      4.0.30319
X-Powered-By      ASP.NET
Content-Type      application/xml;charset=iso-8859-1
Cache-Control      no-cache
DataServiceVersion      1.0;
Content-Length      661

this is what I get in chrome http headers if i have selected the certificate

I think you are right about the redirection by the way..
because the URL i enter is :https://necsapi.statnett.no
and the URL after selecting the certificate is: https://necsapi.statnett.no/odata.svc/
0
 
girionisCommented:
I am getting a forbidden error with ff, ie and chrome.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 8
  • 8
Tackle projects and never again get stuck behind a technical roadblock.
Join Now