NGINX Webserver with Apache Reverse Proxy http2 - apache

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.

Related

does icecast force ssl if enabled?

In the documentation for icecast 2.4.2 I see the following about ssl.
ssl If set to 1 will enable HTTPS on this listen-socket. Icecast must
have been compiled against openSSL to be able to do so.
However this wording is unclear to me whether or not the ssl is forced for this port or not? I am wondering this because we are running into an issue where safari is forcing ssl redirect and we want to keep the server listening on both ssl and non-ssl on the same port ( if thats possible )
Another thing is that it says it must be compiled against openSSL but we are installing it from apt in xenial. Does this mean its default to ssl?
Thanks~!
However this wording is unclear to me whether or not the ssl is forced for this port or not?
On that particular socket, it is. A server bound to that socket cannot support HTTPS and non-HTTPS at the same time. Usually, you'll use port 80 for HTTP and port 443 for HTTPS.
Note that you can have multiple sockets bound to Icecast, simply by putting in multiple <listen-socket> sections. It's common to serve both HTTP and HTTPS this way.
I am wondering this because we are running into an issue where safari is forcing ssl redirect
Your server configuration is irrelevant here. Icecast will not redirect HTTP requests to HTTPS. It's possible that you hit the stream on HTTPS once and that Safari cached this. It's also possible that you turned on HSTS or something for your domain. You would have to debug this with a tool like Fiddler.
and we want to keep the server listening on both ssl and non-ssl on the same port
You say "keep the server listening"... that's not possible. If it appears you're set up this way today, that's not accurate.
In a sense it does. Icecast if you are using it as its own server will not resolve the enabled ssl port unless its https://.
You also cannot use the same port for both ssl and non-ssl.
Finally the xenial ubuntu package also is not compiled for ssl.

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!

How to override scheme and is_ssl in apache HTTP Server for mod_proxy_ajp

We are running Tomcat 7 behind a load balancer that works also as SSL terminator, and an Apache HTTP Server 2.4. The Apache connects to the Tomcat via mod_proxy_ajp.
For the application it is important that Tomcat is aware that the request is coming in via HTTPS and is thus secure. As e.g. this article recommends, it is common to configure this on the Tomcat's Connector using the attributes secure="true" and possibly scheme="https" proxyPort="443". While this works, it is inconvenient since we are using HTTP for some purposes as well, and thus we would need to set up two Tomcat connectors for this purpose. And it has a smell, since this way we basically tell Tomcat to override the wrong information it gets from the Apache HTTP Server that the request is HTTPS instead of HTTP, instead of telling the Apache that it should send the correct information on the protocol and secure status.
So my question: is it somehow possible to configure the Apache HTTP Server itself that it passes the correct information via the AJP protocol: that the request is received via HTTPS and is secure? The problem is that it doesn't know it's HTTPS, since there is a SSL terminator before it and the requests arrives via HTTP, as far as it is concerned. Can I tell the Apache somehow that it's actually HTTPS?
A partial solution seems to be to set the protocol on a ServerName directive in the virtual host in the Apache HTTP server:
ServerName https://whatever
This way any Location: headers in redirects seem to be rewritten to https in the Apache, but the Tomcat is still passed the wrong information via AJP.
I always thought that AJP transfers this information automagically - but I'm not using mod_proxy_ajp, rather mod_jk. It's one of the reasons why I much prefer AJP over HTTP (and proxying).
Might be worth to change the module/connection

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.

GeoServer under https

i am using apache web server on localhost:80 and Geoserver served from tomcat on localhost:8080
I recently installed SSL certificate on apache and it works fine except for that i get the message that says i have insecure content which i thought they were GeoServer layers. So now I'm trying to enable SSL for GeoServer and have Openlayers content like htis https://example.org:8080/geoserver but still not sure what's the best approach to do that.
My suggestion:
Add a (reverse) proxy in Apache and configure your web application that is connects only to the Apache proxying the GeoServer.
ProxyPass "/geoserver" "http://localhost:8080/geoserver"
ProxyPassReverse "/geoserver" "http://localhost:8080/geoserver"
This way you only need to allow HTTPS in the firewall and nobody from outside will have the chance to reach GeoServers web interface unless you enable port 8080 on the firewall. Also see https://gis.stackexchange.com/q/4323/109339 for further details.
Please note that you should set the https://docs.geoserver.org/stable/en/user/configuration/globalsettings.html#proxy-base-url of GeoServer with the public reachable URL via your Apache, e.g. https://your-apache.com/geoserver - otherwise the absolute URLs generated from GeoServer in e.g. GetCapabilities start with http://localhost:8080/geoserver (which is not reachable anymore).
If you had not already Apache in use, I would recommend nginx.