Unable to make http2 requests to an Apache Server, though the server sends "Upgrade:h2" in response headers - apache

I have enabled mod_http2 for the Apache Web Server, and made the necessary changes in the conf, still any request made from a browser to the server follows http/1.1 Protocol
The server sends a Upgrade:h2 header field but the browser still continues to make http/1.1 requests.
How can i make a h2 request from Mozilla/Chrome?
I'm using Mozilla Firefox 48.0

Check that HTTP/2 support is enabled in Firefox:
In the address bar of Firefox, type "about:config", then search for "network.http.spdy.enabled.http2" and make sure that it is set to true.
Firefox implements HTTP/2 only on TLS
So, you will have to access the website using https://xxxxx

Browsers currently only support HTTP/2 via https. See http://caniuse.com/#feat=http2 the note number 2.

The HTTP/2 standard imposes some extra requirements on https, no cipher from a specified black list may be used.
An acceptable Apache SSL configuration regarding this is:
SSLCipherSuite ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!3DES:!MD5:!PSK
SSLProtocol All -SSLv2 -SSLv3
This needs to be changed in the httpd config file and NS_ERROR_NET_INADEQUATE_SECURITY should not occur after httpd restart.

Related

NGINX Webserver with Apache Reverse Proxy http2

i have configued my Apache to act as a Reverse Proxy.
Now i wanted to enabled http2 to speed it up.
Apache has the module enabled and Nginx also.
When i enter
Protocols h2 h2c http/1.1
ProtocolsHonorOrder Off
ProxyPass / h2://192.168.2.100/
ProxyPassReverse / https://192.168.2.100/
into the apache site configuration, Nginx throws a 400 Bad Request Error.
Using this code instead works:
Protocols h2 h2c http/1.1
ProtocolsHonorOrder Off
ProxyPass / https://192.168.2.100/
ProxyPassReverse / https://192.168.2.100/
Nginx Config:
listen 443 ssl http2;
How do i need to configure this section to work properly?#
I realize that this post is over a year old, but I ran into a similar issue after upgrading nginx to 1.20.1. Turns out that nginx was receiving multiple Host headers from Apache when HTTP2 was used. Adding RequestHeader unset Host resolved the issue.
This is more a comment than an answer but it looks like you're new so maybe I can help (at the risk of being totally wrong).
I'm working on configuring Nginx as a reverse proxy for Apache to run a Django application (By the way, I have never heard of anyone using Apache as a reverse proxy for Nginx).
But there's some discussion in the Nginx documentation that makes me think it might not even be possible:
Reading through the Nginx docs on proxy_pass they mention how using websockets for proxying requires a special configuration
In that document it talks about how websockets requires HTTP1.1 (and an Upgrade and Connection HTTP header) so you can either basically fabricate them proxy_set_header between your server and proxy or you can pass them along if the client request includes them.
Presumably in this case, if the client didn't send the Upgrade header, you'd proxy_pass the connection to a server using TCP, rather than websockets.
Well, HTTP2 is (I assume) another Upgrade and one likely to have even less user agent support. So at the least, you'd risk compatibility problems.
Again, I have never configured Apache as a (reverse) proxy but my guess from your configuration is that Apache would handle the encryption to the client, then probably have to re-encrypt for the connection to Nginx.
That's a lot of overhead just on encryption, and probable browser compatibility issues...and probably not a great set up.
Again, I'm not sure if it's possible, I came here looking for a similar answer but you might want to reconsider.

How to use Apache as a reverse-proxy for WebSockets with Undertow as the server

I have WebSockets enabled using an Undertow server. When I run the Undertow server directly, WebSockets work well. I serve my pages using HTTPS and I test the endpoint using "wss:" in javascript: it works.
But now, I try to use Apache as a reverse proxy and I want it to let WebSocket connections reach the Undertow server. This is my current Virtual Host:
<VirtualHost *:80 *:443>
ServerName test.example.org
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.org/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.org/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/example.org/chain.pem
ProxyPass / http://test.example.org:44444/
ProxyPassReverse / http://test.example.org:44444/
</VirtualHost>
Here, Undertow is started as a HTTP server (not HTTPS) on port 44444 and the SSL security is done by Apache.
All the HTML pages work well, but when I try to start a WebSocket connection, I get this error (Chrome) :
WebSocket connection to 'wss://test.example.org/websockets/echo' failed: Error during WebSocket handshake: 'Upgrade' header is missing
And, when I look at the Network tab, I see that indeed two headers are missing in the response from the server, when the "wss://" call is made: "Connection: Upgrade" and "Upgrade: WebSocket". Those headers are present when I connect to Undertow directly, without Apache.
The "Sec-WebSocket-Accept" and "Sec-WebSocket-Location" headers are there but, and I guess this is a second issue, "Sec-WebSocket-Location" is 'ws://test.example.org/websockets/echo' not 'wss://test.example.org/websockets/echo' since Undertow runs on HTTP, not HTTPS.
Last thing, the mod_proxy_wstunnel documentation says "The connection is automatically upgraded to a websocket connection". What does this mean? Apache is upgrading the HTTP connection to a WebSocket connection by itself? This is not what I want! I want to handle the initial HTTP request and the upgrading processes by myself, using Undertow. I use informations from the initial HTTP connection to validate if the user can be connected to the requested endpoint and, if so, I programmatically call Undertow's WebSocketProtocolHandshakeHandler#handleRequest(exchange) to upgrade to a WebSocket connection. I just want Apache to let everything pass without interfering.
Any help on how to run WebSockets using Undertow behind an Apache reverse-proxy?
I got tired and decided to try Nginx.
Within 3 hours, not only did I get WebSockets working, but all my sites on a server were moved to it. Super easy.
The magical lines for WebSockets, in nginx.conf, are:
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
I understand that "Upgrade" is a special "hop-by-hop" header which has to be explicitly configured to be kept.
I hope there is a similar solution for Apache, but man, there is so few documentation about this!

Jetty server running SPDY behind an Apache firewall

I have an application at /mine running on a Jetty server that supports SPDY. It is sitting behind an Apache firewall that is being used as a proxy.
The application at /mine gets routed by the following config rules on Apache:
RewriteRule ^/mine$ /mine/ [R,L]
ProxyPass /code/ https://jettyserver:9443/mine/ nocanon
ProxyPassReverse /mine/ https://jettyserver:9443/mine/ nocanon
As a result, when I hit apache/mine/, my browser is not negotiating SPDY with my application.
Adding mod_spdy to the proxy would be the correct approach but I cannot currently do that with the Apache we are running.
Is there a way I can get this to work?
For that particular configuration you want to run, I am afraid there is no way to get it working with SPDY or HTTP/2.
Apache configured as a reverse proxy talks HTTP/1.1 to Jetty, so there is no way to get SPDY or HTTP/2 into the picture at all (considering you cannot make Apache talk SPDY).
However, there are a number of alternative solutions.
Let's focus on HTTP/2 only because SPDY is now being phased out in favour of HTTP/2.
The first and simplest solution is just to remove Apache completely.
You just expose Jetty as your server, and it will be able to speak HTTP/2 and HTTP/1.1 to browsers without problems.
Jetty will handle TLS and then HTTP/2 or HTTP/1.1.
The second solution is to put HAProxy in the front, and have it forward to Jetty.
HAProxy will handle TLS and forward clear-text HTTP/2 or HTTP/1.1 to Jetty.
The advantage of these two solutions is that you will benefit of the HTTP/2 support of Jetty, along with its HTTP/2 Push capabilities.
Not only that, Jetty also gets you a wide range of Apache features such as rewriting, proxying, PHP/FastCGI support, etc.
For most configurations, you don't need Apache because Jetty can do it.
The first solution has the advantage that you have to configure one server only (Jetty), but you will probably pay a little for TLS because the JDK implementation used by Jetty is not the most efficient around.
The second solution has the advantage that TLS will be done more efficiently by HAProxy, and you can run it more easily on port 80. However, you have to configure two servers (HAProxy and Jetty) instead of just one.
Have a look at the Jetty HTTP/2 documentation and at the Webtide blogs where we routinely add entries about HTTP/2, configurations and examples.

Force ssl certificate to be included in CORS pre-flight request

I am trying to make a (non-simple) CORS GET request (AJAX) made by my client server (running on Apache # port 443) to a 3rd party endpoint server (running on Tomcat # port 8443), which fails to trigger when tried over HTTPS.
When SSL is not enabled it works just fine indicating that the CORS is set up properly.
The problem is that since the GET is (not-simple) it sends a pre-flight OPTIONS request.
According to this:
Pre-flight OPTIONS request failing over HTTPS
Pre-flighted requests don't include the client certificate. He states this is in the CORS spec however I was unable to find this specifically listed in the spec:
http://www.w3.org/TR/cors/
The third party cannot enable
SSLVerifyClient optional
as they require all communication be sent with SSL.
However they do have their CORS setup right and they have
access-control-allow-credentials: "true"
In our AJAX call we included in the xhrFields
withCredentials: true
So we are telling it to pass withCredentials (which includes cert / cookie / etc)
And on our APACHE we have
SSLOptions +ExportCertData
Somehow when we make the call though, they are still seeing the error "key/cert was not included "
Am I missing something? Is there a way to force this in Apache?
At the moment I'm getting ready to create a man the middle script to attach the cert to the initial request but it seems like there has to be a better way.
Any suggestions?

Apache HTTPD/mod_proxy/Tomcat and SSL with client auth

I'm sure this is an FAQ but I couldn't find anything I recognized as being the same question.
I have several web-apps running in Tomcat, with some pages e.g. the login page protected by SSL as defined by confidentiality elements in their web.xmls. One of the apps also accepts client-authentication via certificate. I also have a rather extensive JAAS-based authorization & authentication scheme, and there is all kinds of shared code and different JAAS configurations etc between the various webapps.
I really don't want to disturb any of that while accomplishing the below.
I am now in the process of inserting Apache HTTPD with mod-proxy and mod-proxy-balancer in front of Tomcat as a load balancer, prior to adding more Tomcat instances.
What I want to accomplish for HTTPS requests is that they are redirected 'blind' to Tomcat without HTTPD being the SSL endpoint, i.e. HTTPD just passes ciphertext directly to Tomcat so that TC can keep doing what it is already doing with logins, SSL, web.xml confidentialty guarantees, and most importantly client authentication.
Is this possible with the configuration I've described?
I am very familiar with the webapps and SSL and HTTPS and Tomcat, but my knowledge of the outer reaches of Apache HTTPD is limited.
Happy to have this moved if necessary but it is kind of programming with config files ;)
This sounds similar to this question, where I've answered that it's not possible:
You can't just relay the SSL/TLS traffic to Tomcat from Apache. Either
your SSL connection ends at Apache, and then you should reverse proxy
the traffic to Tomcat (SSL [between Httpd and Tomcat] is rarely useful in this case), or you make
the clients connect to Tomcat directly and let it handle the SSL
connection.
I admit it's a bit short of links to back this claim. I guess I might be wrong (I've just never seen this done, but that doesn't strictly mean it doesn't exist...).
As you know, you need a direct connection, or a connection entirely relayed, between the user-agent and the SSL endpoint (in this case, you want it to be Tomcat). This means that Apache Httpd won't be able to look into the URL: it will know the host name at best (when using Server Name Indication).
The only option that doesn't seem to depend on a URL in the mod_proxy documentation is AllowCONNECT, which is what's used for forward proxy servers for HTTPS.
Even the options in mod_proxy_balancer expect a path at some point of the configuration. Its documentation doesn't mention SSL/HTTPS ("It provides load balancing support for HTTP, FTP and AJP13 protocols"), whereas mod_proxy talks at least about SSL when mentioning CONNECT.
I would suggest a couple of options:
Using an iptables-based load-balancer, without going through Httpd, ending the connections in Tomcat directly.
Ending the SSL/TLS connection at Httpd and using a plain HTTP reverse proxy to Tomcat.
This second option requires a bit more configuration to deal with the client certificates and Tomcat's security constraints.
If you have configured your webapp with <transport-guarantee>CONFIDENTIAL</transport-guarantee>, you will need to make Tomcat flag the connections as secure, despite the fact it sees them coming from its plain HTTP port. For Tomcat 5, here is an article (originally in French, but the automatic translations isn't too bad) describing how to implement a valve to set isSecure(). (If you're not familiar with valves, they are similar to filters, but operate within Tomcat itself, before the request is propagated to the webapp. They can be configured within Catalina) I think from Tomcat 5.5, the HTTP connector secure option does exactly that, without requiring your own valve. The AJP connector also has a similar option (if using mod_proxy_ajp or mod_jk).
If using the AJP connector, mod_proxy_ajp will forward the first certificate in the chain and make it available within Tomcat (via the normal request attribute). You'll probably need SSLOptions +ExportCertData +StdEnvVars. mod_jk (although deprecated as far as I know) can also forward the entire chain sent by the client (using JkOptions +ForwardSSLCertChain). This can be necessary when using proxy certificates (which are meaningless without the chain up to their end-entity certificate).
If you want to use mod_proxy_http, a trick is to pass the certificate via an HTTP header (mod_header), using something like RequestHeader set X-ClientCert %{SSL_CLIENT_CERT}s. I can't remember the exact details, but it's important to make sure that this header is cleared so that it never comes from the client's browser (who could forge it otherwise). If you need the full chain, you can try out this Httpd patch attempt. This approach would probably need an extra valve/filter to turn the header into the javax.servlet.request.X509Certificate (by parsing the PEM blocks).
A couple of other points that may be of interest:
If I remember well, you need to download the CRL files explicitly for Httpd and configure it to use them. Depending on the version of Httpd you're using, you may have to restart it to reload the CRLs.
If you're using re-negotiation to get your client-certificate, a CLIENT-CERT directive will not make Httpd request a client certificate as far as I know (this is otherwise done via a valve that can access the SSLSession when using the JSSE connector directly). You may have to configure the matching path in Httpd to request the client-certificate.