MQTT over websocket over Apache SSL - apache

I have an mqtt broker providing unencrypted websocket. I would like to proxy it through an Apache which should encrypt the websocket to the outside.
It is an Apache 2.4 on a Windows machine.
My config is:
<VirtualHost *:80>
ServerName test.someurl.com
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://localhost:9876/$1 [P,L]
</VirtualHost>
<VirtualHost *:443>
ServerName test.someurl.com
SSLEngine on
SSLCertificateFile "C:/Program Files (x86)/Apache24/conf/ssl/some_certificate.crt"
SSLCertificateKeyFile "C:/Program Files (x86)/Apache24/conf/ssl/some_key.key"
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://localhost:9876/$1 [P,L]
# Websocket proxy
# wss redirects to working ws protocol
# ProxyPass /wss ws://127.0.0.1:9876 retry=0 keepalive=On
# ProxyPassReverse /wss ws://127.0.0.1:9876 retry=0
</VirtualHost>
I am able to connect through ws / port 80. It works fine. However, I am not able to connect using the wss.
I tried both using a rewriting and also a proxy_pass directives. I tried 100 different solution. However, this one looked most promising as port 80 is working for ws but not for the encrypted part. Any idea? Or I am just blinded by the options O:)

This is an old question, but as I've just got this working:
I have Mosquitto listening on port 8000 (which is firewalled to block any connections other than from localhost)
listener 8000
socket_domain ipv4
allow_anonymous true
protocol websockets
Then setup apache as so:
<VirtualHost *:80>
ProxyPass /ws/ ws://localhost:8000/
ProxyPassReverse /ws/ ws://localhost:8000/
</VirtualHost>
<VirtualHost *:443>
SSLCertificateFile ...
SSLCertificateChainFile ...
SSLCertificateKeyFile ...
ProxyPass /ws/ ws://localhost:8000/
ProxyPassReverse /ws/ ws://localhost:8000/
</VirtualHost>
Finally, the web-application is set to connect like so:
mqtt.connect((window.location.protocol == "https:" ? "wss:" : "ws:") + "//example.org/ws/");
Note that the proxy protocol can be "ws" or "wss" - both seem to work interchangeably. This is the connection between apache and mosquitto, there's no need to encrypt (they're on the same host). The use of the "/ws/" suffix on the path means I can do without mod_rewrite, and simply use mod_proxy.
This approach is the only way I could require authentication when accessed over HTTPS (which is public) but not over HTTP (which is behind the firewall).

Related

Apache Reverse Proxy to Figma Prototype with Websocket

I am trying to reverse proxy a Figma prototype to the domain I have with SSL configured. Proxying it to the main Figma page works but I cannot connect it to my prototype page.
For example, how can I connect to the following Figma sample page?
https://www.figma.com/proto/KVm2roB2LnduHTLJjKjkfn/Prototyping-in-Figma
Below is the conf file used for reverse proxying to the Figma main home page with https://exampledomain.com. So this works, but if I try to access the prototype page at https://exampledomain.com/proto/KVm2roB2LnduHTLJjKjkfn/Prototyping-in-Figma , it displays only the loading page and does not proceed to the prototype.
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
Header always set Strict-Transport-Security "max-age=63072000; includeSubdomains;"
SSLUseStapling on
ServerName exampledomain.com
DocumentRoot /var/www/exampledomain
ProxyRequests Off
SSLProxyEngine On
ProxyPreserveHost Off
ProxyPass / https://www.figma.com/
ProxyPassReverse / https://www.figma.com/
SSLEngine on
SSLCertificateKeyFile myserver.key
SSLCertificateFile myserver.crt
SSLCertificateChainFile myserver.ca-bundle
</VirtualHost>
</IfModule>
I think the problem here is the Websocket configuration, so I enabled mod_proxy_wstunnel on Apache and added the below configurations, but wasn't successful.
RewriteEngine on
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule .* "wss://www.figma.com/$1" [P,L]
I'm unsure if it is even possible to configure Websocket to a non-local website as I don't know if I can find Figma's Websocket port number. How can I connect Figma prototype via reverse proxy and change the URL to my domain?

Apache reverse proxy for websockets

I'm using Apache on my server to proxy traffic on port 80 and 443 out to separate VM's running different websites and services. I'm having trouble setting up a proxy for MeshCentral which requires websockets. I'm using Debian 10 with Apache 2.4.38.
I can load MeshCentral, but once I login it tries to use websockets and I get the following error;
Firefox can’t establish a connection to the server at wss://example.com/control.ashx?auth=Uu7PBFNsswzzWoQaVNPH2N3ZwkWbx7DSsljaaY8cxthO5fcPVSz#sqLbGzyOpvxTxvfmV7WgwLdRklqLNYC5KQTjrZPCYDcNDvJ0AY7V8DGdUk68jK3sPfnc$Sl7rvhaQwR1xBukiZ8=. meshcentral.js:27:21
I've added the wstunnel proxy
a2enmod proxy_wstunnel
And setup HTTP and HTTPS proxies which work fine
/etc/apache2/sites-enabled/000-default.conf
<VirtualHost *:80>
ServerName example.com
ProxyPreserveHost On
ProxyPass "/" "http://192.168.200.11/"
ProxyPassReverse "/" "http://example.com/"
</VirtualHost>
/etc/apache2/sites-enabled/000-default-le-ssl.conf
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerName example.com
RewriteEngine on
RewriteCond ${HTTP:UPGRADE} websocket [NC]
RewriteCond ${HTTP:CONNECTION} upgrade [NC]
RewriteRule /(.*) "wss://example.com/$1" [P]
ProxyPreserveHost On
ProxyPass "/" "https://192.168.200.11/"
ProxyPassReverse "/" "https://example.com/"
SSLProxyEngine On
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/mydomain.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/mydomain.com/privkey.pem
</VirtualHost>
</IfModule>
I've restarted apache before I tried loading the page in firefox and also tried google-chrome, same error.
You can try with:
Ubuntu
a2enmod proxy
a2enmod proxy_http
a2enmod proxy_wstunnel
Centos
Open the module configuration file for proxies.
sudo vi /etc/httpd/conf.modules.d/00-proxy.conf
All modules related to proxying are listed in this configuration file. Verify that the following lines exist and are uncommented.
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_wstunnel modules/mod_proxy_wstunnel.so
If you made any changes to the file, save them now.
Restart Apache Web Server to apply your changes.
sudo systemctl restart httpd
Configuration:
<VirtualHost *:443>
ServerName ws.serverlab.ca
RewriteEngine on
RewriteCond ${HTTP:Upgrade} websocket [NC]
RewriteCond ${HTTP:Connection} upgrade [NC]
RewriteRule .* "wss:/localhost:3000/$1" [P,L]
<Proxy balancer://backend-cluster>
BalancerMember http://server01:3000
BalancerMember http://server02:3000
BalancerMember http://server03:3000
</Proxy>
ProxyPass / balancer://backend-cluster/
ProxyPassReverse / balancer://backend-cluster/
ProxyRequests off
</VirtualHost>
ServerName ws.serverlab.ca
The hostname of the virtual web host that will handle the WebSocket connections.
RewriteEngine on
Used to set the status of the RewriteEngine to either on or off. To support WebSockets it must be turned on.
RewriteCond ${HTTP:Upgrade} websocket [NC]
A condition that must be matched in order for a request to be processed by the RewriteRule.
RewriteCond ${HTTP:Connection} upgrade [NC]
To something
RewriteRule . “wss:/ws-backend%{REQUEST_URI}” [P]*
Rewrite all incoming requests to use the wss protocol, and replace the destination hostname to that of a backend service.
Documentation from: How to Reverse Proxy Websockets with Apache 2.4

How to set apache HTTP to HTTPS redirection on internal proxy?

On my website I have two applications written in Vue. The first is SPA on port 80, the second is Nuxt SSR on port 8080, which is redirected from localhost:8000.
I managed to set HTTPS on both external ports but only on port 80 HTTP traffic is redirected to HTTPS. On port 8080 HTTPS works, but when i try to visit site with http:// it gives me Apache error Bad Requetst:
"Your browser sent a request that this server could not understand.
Reason: You're speaking plain HTTP to an SSL-enabled server port.
Instead use the HTTPS scheme to access this URL, please."
I want all the traffic on port 8080 to be redirected to HTTPS.
My site.conf:
<VirtualHost *:443>
ServerName site.com
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
Protocols h2 http/1.1
SSLEngine On
SSLCertificateFile cert_path...
SSLCertificateKeyFile key_path...
SSLCertificateChainFile cert_path...
...
</VirtualHost>
<VirtualHost *:80>
...
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L]
...
</VirtualHost>
<VirtualHost *:8080>
...
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
Protocols h2 http/1.1
SSLEngine On
SSLCertificateFile cert_path...
SSLCertificateKeyFile key_path...
SSLCertificateChainFile cert_path...
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:8000/
ProxyPassReverse / http://127.0.0.1:8000/
RewriteEngine On
RewriteCond %{HTTPS} !=on
RewriteRule ^/?(.*) https://%{SERVER_NAME}:8080/$1 [R,L]
</VirtualHost>

How to run socket.io on port 443 where apache is running?

I need to run socket.io on port 443 (where apache run https site with Let's Encrypt)
The idea is to use a apache proxy that will redirect the traffic to the socket.io port.
I found that solution:
<VirtualHost *:443>
ServerName mysite.com
ServerAlias www.mysite.com
SSLEngine on
SSLProxyEngine On
ProxyRequests Off
SSLCertificateFile /etc/apache2/ssl/mysite.com.crt
SSLCertificateKeyFile /etc/apache2/ssl/mysite.com.key
SSLCertificateChainFile /etc/apache2/ssl/ca.cer
DocumentRoot /var/www/errorPages
ErrorDocument 503 /503.html
ProxyPass /503.html !
ProxyPass / http://localhost:3999/
ProxyPassReverse / http://localhost:3999/
RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} ^Upgrade$ [NC]
RewriteRule .* ws://localhost:3999%{REQUEST_URI} [P]
</VirtualHost>
I run the socket.io on port 3999
HTTPS site works fine, howevever I got http 404 errors.
I guess problem is on rewriteCond.
websocket.js:112 WebSocket connection to
'wss://mysite.com/socket.io/?id=11518237&username=john failed: Error
during WebSocket handshake: Unexpected response code: 404
Try mod_proxy_wstunnel
It provides support for the tunnelling of web socket connections to a backend websockets server. The connection is automatically upgraded to a websocket connection
https://httpd.apache.org/docs/2.4/mod/mod_proxy_wstunnel.html
Use different IP addresses for the different uses. You have <VirtualHost *:443> which tries to use all IP addresses for the single virtual host. I think you want a <VirtualHost pub.lic.ip.addr:443> for Let's Encrypt and a <VirtualHost localhost:443> for the socket.io proxy.

Apache 2.2 to 2.4 too many redirects

I have an old server which uses httpd 2.2 and this configuration works fine redirecting HTTP requests to HTTPS.
Moving to CentOS and upgrading to httpd 2.4 the existing configuration causes a too many redirects to occur.
<VirtualHost _default_:80>
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule (.*) https://%{HTTP_HOST}%{REQUEST_URI}
</VirtualHost>
<VirtualHost _default_:443>
SSLEngine on
... SSL Setup ...
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / ajp://localhost:8009/
ProxyPassReverse / ajp://localhost:8009/
</VirtualHost>
I'm using tomcat which is listening on port 8009 internally, I'm not sure why is it happening.
SUGGESTED
The ProxyPassReverse directive doesn't work well with ajp.
Switch to HTTP/HTTPS
Remove the ProxyPassReverse directive
Validate you have set RemoteIPHeader X-Forwarded-For, X-Forwarded-Host, X-Forwarded-Port and X-Forwarded-Proto appropriately as well