As a Proxy Program sitting in between Server and Browser , how can we notify a browser to use either http1.1 or http2.0 protocol
The answer depends on whether your "proxy" is a forward proxy configured on the browser, or a reverse proxy configured on the server.
In the first case (forward proxy), because the target scheme is https, the browser will issue a HTTP CONNECT to the forward proxy and the forward proxy will create a tunnel to the server.
Once the tunnel is created, the browser and the server will communicate directly with the forward proxy only forwarding bytes in both directions.
In this case, client and server will negotiate directly the protocol via ALPN because they communicate directly, with the forward proxy only forwarding bytes (but not inspecting or otherwise changing them).
Therefore in this case you don't need to inform the client of anything, because client and server communicate directly.
In the second case (reverse proxy) the browser will connect to the reverse proxy thinking it's its final destination.
For a request to https://example.com, the DNS will resolve the reverse proxy address, and the reverse proxy must offer a valid certificate for example.com.
If the reverse proxy needs to forward the request to a server, then it does not matter what protocol it will use, since the client will never be aware of this communication between the reverse proxy and the server.
If the reverse proxy supports only HTTP/1.1 and the server supports HTTP/2, then the reverse proxy cannot tell the client that the server supports HTTP/2 because the client never talks directly to the server: the client only sees the reverse proxy and because the reverse proxy only supports HTTP/1.1 then they will never be able to speak HTTP/2, even if the server does.
If the reverse proxy supports both HTTP/1.1 and HTTP/2, then the client and the reverse proxy will speak HTTP/2. It does not matter what protocol the reverse proxy speaks to the server: it can be HTTP/1.1, HTTP/2, FastCGI, etc. But the protocol that the reverse proxy uses with the server is of no interest to the client because the client will never be able to talk directly to the server.
The client only ever speaks to the reverse proxy, so the protocol that they negotiate is the only one that matters to the client.
In this case also you don't need to inform the client of anything, because the client can only communicate with the proxy and can only use the protocol that it negotiated with the proxy.
Related
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 require to interact to RabbitMQ using java client. As, enterprise environment are restrictive for I would require to raise firewall request. But, I came to know for port 443 and HTTPs or HTTP post we don't require firewall.
Is it possible to publish request and get response for RabbitMQ using HTTP Proxy
you can configure the amqp port
cp /usr/share/doc/rabbitmq-server-[rabbitmq version]/rabbitmq.config.example /etc/rabbitmq/rabbitmq.config
Then search for
%%{tcp_listeners, [5672]}
And remove ‘%%’,
change 5672 to opened port, Then restart rabbitmq server.
or you will need to use socks as another solution
We have a number of Jetty http(s) servers, all behind different firewalls. The http servers are at customer sites (not under our control). Opening ports in the firewalls at these sites is not an option. Right now, these servers only serve JSON documents in response to REST requests.
We have web clients that need to interact with a given http server based on URL parameter or header value.
This seems like a straightforward proxy server situation - except for the firewall.
The approach that I'm currently trying is this:
Have a centralized proxy server (also Jetty based) that listens for inbound registration requests from the remote http servers. The registration request will take the form of a Websocket connection, which will be kept alive as long at the remote HTTP server is available. On registration, the Proxy Server will capture the websocket connection and map it to a resource identifier.
The web client will connect the proxy server, and include the resource identifier in the URL or header.
The proxy server will determine the appropriate Websocket to use, then pass the request on to the HTTP server. So the request and response will travel over the Websocket. Once the response is received, it will be returned to the web client.
So this is all well and good in theory - what I'm trying to figure out is:
a) is there a better way to achieve this?
b) What's the best way to set up Jetty to do the proxying on the HTTP Server end of the pipe?
I suppose that I could use Jetty's HttpClient, but what I really want to do is just pull the HTTP bytes from the websocket and pipe them directly into the Jetty connector. It doesn't seem to make sense to parse everything out. I suppose that I could open a regular socket connection on localhost, grab the bytes from the websocket, and do it that way - but it seems silly to route through the OS like that (I'm already operating inside the HTTP Server's Jetty environment).
It sure seems like this is the sort of problem that may have already been solved... Maybe by using a custom jetty Connection that works on WebSockets instead of TCP/IP sockets?
Update: as I've been playing with this, it seems like another tricky problem is how to handle request/response behavior (and ideally support muxing over the websocket channel). One potential resource that I've found is the WAMP sub-protocol for websockets: http://wamp.ws/
In case anyone else is looking for an answer to this one - RESTEasy has a mocking framework that can be used to invoke the REST functionality without running through a full servlet container: http://docs.jboss.org/resteasy/docs/2.0.0.GA/userguide/html_single/index.html#RESTEasy_Server-side_Mock_Framework
This, combined with WAMP, appears to do what I'm looking for.
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.
i am here looking for resources or sample code for proxy server which can handle both http and https requests written in java. i searched google and found lot of data on how to handle http requests but not https.
A proxy cannot handle HTTPS and still provide end to end security. It is not possible using SSL/TLS which is what HTTPS is built on.
And a proxy that doesn't provide end-to-end security only has limited utility. So I'm not surprised you can't find an existing implementation.
I'm assuming that you want a normal HTTPS proxy here, that is a proxy that will not look into the request but merely relay all the traffic to the actual HTTPS server after the user-agent has used the HTTP CONNECT method. This is how HTTP proxy servers are normally used for HTTPS requests by browsers.
I haven't tried, but you could look at Jetty and its ConnectHandler.