Trying to get Websockify/noVNC to work through a reverse proxy - apache

I'm trying to figure out how to get noVNC to work through a reverse proxy, and while it works if I connect directly to it, it doesn't seem to work if I try to reverse proxy.
namely:
I run it as ./utils/launch.sh --vnc localhost:5901
if I connect to it as https://<machine>:6080/vnc.html?host=<machine>&port=6080
it works fine and I can connect to the vnc session
However, I want to be able to connect to it via a reverse proxy over port 443.
In Apache 2.4.10 (-8 in Debian Jessie), I've configured my proxy line to be
ProxyPass /home http://127.0.0.1:6080/
ProxyPassReverse /home http://127.0.0.1:6080/
ProxyPass /websockify wss://127.0.0.1:6080/websockify retry=3
ProxyPassReverse /websockify wss://127.0.0.1:6080/websockify retry=3
and I connect to it as https://<machine>/vnc.html?host=<machine>&port=6080
This still works, as while the fetch of the html/javascript is going through the reverse proxy, I'm still telling the websocket connection to go over 6080 and it works.
However, when I change it to https://<machine>/vnc.html?host=<machine>&port=443
I get the html/javascript just fine, but when it goes to make the connection, in firefox (and chrome and IE, but this error is from firefox in specific) I quickly get
Firefox can't establish a connection to the server at wss://<machine>/websockify.
and in noVNC I see the error message
127.0.0.1: ignoring socket not ready

Turns out, if one wants to proxy websockets through an https proxy, one should make the proxy part normal websockets (ws://) not secure web sockets (wss://) which makes sense as the https proxy would have handled the ssl portion already and there is nothing to do.
ProxyPass /websockify ws://127.0.0.1:6080/websockify retry=3
ProxyPassReverse /websockify ws://127.0.0.1:6080/websockify retry=3
make that change and everything works.

Related

Apache mod_proxy: forward secure websocket to non-secure

The websocket library I rely on (PHP-Websockets) does not yet support secure sockets (wss). My website is served over https though, so I cannot use insecure ws connections.
I'm trying to use Apache's mod_proxy to forward the secure request that comes from the browser on to the client.
Javascript
var ws = new WebSocket('wss://example.com/_ws_/');
Apache VirtualHost
ProxyPass "/_ws_/" "ws://127.0.0.1:8080/"
ProxyPassReverse "/_ws_/" "ws://127.0.0.1:8080/"
# I've also tried "/_ws_/" "ws://example.com:8080/" Same error below
Upon trying to connect, the browser receives a 500 Server Error. The logs show:
No protocol handler was valid for the URL /_ws_/. If you are using a DSO version of mod_proxy, make sure the proxy submodules are included in the configuration using LoadModule.
I've confirmed that if I remove the proxy rules, stop redirecting users to https and try to connect to insecure sockets from the browser: new WebSocket('ws://example.com/'), things work just fine.
My loaded Apache modules include mod_ssl.c, mod_proxy.c and mod_proxy_http.c
Apache 2.4
To reverse proxy WebSockets, you also need to load the mod_proxy_wstunnel module.

xampp Apache enable proxy for interent operations

I have followd this answer https://serverfault.com/a/249582 to enable proxy and put a line to forward internet operations. However, since I use http://localhost to browse my website, it also redirected localhost to the proxy server and thus my website cannot even load.
How can I bypass local addresses such as localhost, 127.0.0.1 or internal network IP such as 192.168.1.50, such that fopensock can work normally?

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!

HTTP to HTTPS mapping using proxy servers

I have a java application which is trying to call a HTTPS endpoint which is setup in my internal network. Also this request go through a corporate proxy.
Having said that, I don't want to implement a HTTPS client at my application level. Instead I will just trigger a plain http request, then further my proxy will take the http request and delegate it to the HTTPS endpoint. So that the proxy will take care of handling the SSL certificates & keys.
Is this something possible with Apache Httpd or Squid ?
Basically I dont want my application to worry about the SSL cerificates etc. Instead this can be managed at the proxy level ?
this should be easy with apache. in your virtual host add
ProxyPass /myapp https://somehost.com/myapp
ProxyPassReverse /myapp https://somehost.com/myapp
then you can use yourinternalhost.company.com/myapp/
then watch your error log about SSLProxyCheck* messages (depends on the ssl certificate)
see http://httpd.apache.org/docs/2.4/mod/mod_ssl.html#sslproxycheckpeercn
mod_proxy:
httpd.apache.org/docs/2.4/mod/mod_proxy.html (see proxyremote for using another (corporate) proxy

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.