Good afternoon everyone,
I'm having some issues with my HTTP server. I've made my own HTTP server (A lightweight HTTP server due some circumstances and needings) that I want to implement on a software I have. This HTTP API also is used to allow HTTPS, but my main issue comes actually with HTTP.
One issue I'm facing is retrieving HTTPS connections on the HTTP server. Using HTTPS as the server and HTTP as the connection from the client gets denied, as the Handshake fails and gives an Exception to the server. The problem using the HTTP server with an HTTPS client is that this connections keeps running, but the message is encrypted. As it's encrypted, I can't read the information and get details like the Content-Length, so the server is waiting for an end that will never come as it can't read correctly the data.
I was wondering if there's a way in Java to detect if the client is using encrypted responses to deny this connections instead of trying to read them. The main issue with this sockets is that they aren't detected as SSLSockets, they are normal sockets that can't decrypt the information in the InputStream.
Thank you in advance.
Are you aware that HTTP and HTTPS are usually served on different port numbers? So 80 is for HTTP and 443 for HTTPS. For non-privileged ports often 8000 and 8443 are used. A client that connects using TLS on a HTTP-only port is faulty, and your HTTP server should easily detect non-HTTP traffic:
If the first word received isn't one of the HTTP verbs supported by your server, such as GET, HEAD, POST, PUT, OPTIONS, etc. your server should send a 400 or 408 response (408 is request timeout, your server should only wait a reasonable amout of time for the request header) and then close the connection.
Related
I have server application which runs on local host and the client also runs on local host.
As of now I am using java.net.serversocket and any application which has the ip and port detail of server can listen to the port.
My requirement is to secure the ports or secure the communication between the server and client application such that only my application client (authorised) one can listen to the ports or connect to server application. The data sent to and from client and server also has to be secured.
Apologies if naming conventions are not correct. I have been searching for solution and couldn't get anything for this, all I got is how to connect and make application communicate using socket programming , but no where I got the answer as how to secure the communication.
What you need here is some sort of authentication method to authorise only your client to communicate with the server. If you are using an existing communication protocol then it might have a specification for authentication already. If you are using your own protocol then you'll have come up with your own design for authentication.
It could be as simple as the server issuing some sort of request for authentication to the client. The client would then have to provide a satisfactory response (eg a user/password) otherwise the server would close the connection.
I would recommend taking a look at how some other protocols (eg HTTP) handle authentication to get some insight and also understand potential pitfalls.
I am using embedded jetty and spring for java to java communication over http. My problem is that my server application must handle plain TCP messages also on the same port.
Is there a way to detect if a TCP message arrived which cannot be handled by the servlet?
Thanks for the answers I add some more details:
I cannot modify the client. The reason for this is that the old version of the client uses pure java tcp socket and it turned out that the new server must be backward compatible with the old client.
Have to use the same port
Old client messages are short serialized text over simple socket. 1: open connection, 2: send text, 3: close connection
My server looks something like this: http://kielczewski.eu/2013/11/using-embedded-jetty-spring-mvc/
I do not need to parse the message. It is enough to detect that a message was arrived which is not using http and get the source host name.
You might want to take a look at how to add a custom ConnectionFactory to the ServerConnector of your HTTP port.
This ConnectionFactory concept is how the PROXY Protocol is supported within Jetty currently.
In your case, you might have something like ...
MyTcpConnectionFactory tcpConnectionFactory = new MyTcpConnectionFactory();
ServerConnector http = new ServerConnector(server);
http.addFirstConnectionFactory(tcpConnectionFactory);
server.addConnector(http);
In your case, you would override the newConnection(Connector connector, EndPoint endPoint) method and implement the check for your TCP flow, or the HTTP flow.
If its your flow, you handle the communications on that connection yourself and then throw an IOException when you are done indicating that you don't want jetty to process that connection as HTTP.
Otherwise you return that Connection object to Jetty to process as HTTP.
You are in for a wild ride here my friend. You need to realize that HTTP IS TCP ... its just the content being sent on the TCP socket that classifies it as HTTP or not. That being said, you can intercept the Connection with a filter ie
1) create a filter (google Java Application Server Filters and check the Jetty implementation) for ALL incoming connections
2) check for URI on the request, if it fails, then the request is not HTTP (might want to double check on the request testing logic here)
3) Redirect the request to the appropriate Servlet / Function based on serial socket / http request
On another note, why not use https (port 443) for http and port 80 for your socket requirments ?
I stand corrected. Filters wont work.
In that case, you will have to code a mini firewall. you have to scan all inputs for https headers and redirect accordingly. Can you at least provide some context on the plain TCP messages you want to receive? do you have any control over the sending code ? you do know you can upgrade a TCP/HTTP connection to a websocket (involves client and server) and it will work even better than plain TCP, same port connections, and comes built in Jetty so no custom boiler plates, just a websocket servlet
I am trying to insert a header on all HTTPS requests that passes my proxy server.
I read that HTTPS request headers can not be tampered with.
Is there any way that I can insert a header on HTTPS requests?
Only if the proxy is the endpoint of the TLS connection with the client (i.e. the proxy decrypts the requests). Otherwise it won't actually see any HTTP headers at all, just TCP sessions containing encrypted data.
It is common for a reverse proxy local to the web server(s) to terminate TLS connections for performance - the Web server can dedicate more resources to serving applications because it doesn't need to spend CPU cycles on de/encryption.
If you do this, your server certificate must identify the proxy server, not the web server. Otherwise clients will get a warning about the identity of the server differing from the certificate identity.
If you don't control or trust the infrastructure between the proxy and your server you could re-encrypt the ongoing requests.
Unless you are willing to terminate the SSL connection on your proxy, no you can't. This is one of the main goals of SSL. The data and that includes the headers are encrypted from the client to the server.
If you decide to terminate / intercept the SSL connection on your proxy, the clients will get a warning in their browsers. If you are in charge of all the browsers of all the clients you would be able to install a custom certificate and the clients wouldn't get warned anymore.
My node app is up and running (listening). It is in essence a bunch of rest api handlers.
I am sending http requests from my test java client using general java codes (Apache httprequest and httpclient to execute the simple http commands).
The thing is the java http client side instantly gets an IO exception after send the request to the app. Saying " org.apache.http.conn.HttpHostConnectException: Connection to http://xxxxxxx.herokuapp.com:38084 refused"
Is there any thing i missed so as to make http calls from a java client?
thanks.
You are never supposed to connect to any port other than 80 or 443 when connecting to foo.herokuapp.com. Granted, your app listens on some port (given by the PORT environment variable), but you still need to connect to port 80 (for http).
You are not connecting directly to your dyno(s), bur rather to a Heroku gateway. Heroku's gateway will do the routing (from the gateway to your application) and port forwarding for you.
I would recommend using curl to try to replicate the connection problem. If it works correctly with curl (or for that matter, in your browser), than you know you have a Java client issue.
I have a HTTP server with runs with HTTP and HTTPS, written using Javas NIO and SSL libraries. In HTTPS mode it can communicate with or without the client certificate. However, I would like to perform renegotiation. Here the client will connect with HTTPS, browse resources and then when they hit a highly secure resource the server challenges the client for its certificate. I have been having a few problems with this and need to know what the workflow should be. Here is what I have observed with both IE 9 and Chrome.
1) When the client requests the secure resource, I respond to the HTTP request in full. I then challenge the client for their cert upon completion with
engine.setNeedClientAuth(true);
engine.beginHandshake();
The result is a TCP FIN from the client (it closes its side of the connection), and the renegotiation fails.
2) When the client requests the secure resource, I challenge for the cert before responding. In this scenario the exchange occurs, both browsers will popup a request for the cert, however as soon as it pops up the prompt a TCP FIN is sent from the client and renegotiation terminates. The client then sends another request which eventually has the certificate, at times I have to challenge twice.
So my question here is, what is supposed to happen? Is the initial browser connection supposed to remain open, or is termination like this normal?
NOTE: Another very interesting observation here is that, in scenario 2, when the browser closes the TCP connection, it then reconnects after you choose the certificate. It does not however repost the request, it just sits there and expects the server to respond? In NIO terminology its sits waiting on an OP_READ, which means there is no data on the socket input buffer. Do the browsers expect a response to the original message that it terminated the connection for??
Strange that there is absolutely no documentation or a specification for this workflow, yet for all the browsers I've tested they seem to follow this workflow.
(1) is insecure and therefore pointless to discuss further. You've already leaked the information before you even ask for the credentials.
(2) is the correct way to do this. The client shouldn't be closing the connection if it is configured to allow renegotiation. Due to an SSL security problem last year or so there was temporarily a phase where SSL renegotiation was disallowed by default. You may be running into this. In that case you should be issuing an HTTP redirect first, and closing the connection at your end to force the client to use a new connection, and the new connection should ask for a client certificate. How you arrange that in your code is up to you.