Route mqtt and websocket traffic through apache2 - ssl

I have a emqx broker setup on Ubuntu EC2.
When I try to connect to emqx through websocket with IP address, it works fine.
But when I use subdomain, the connection fails.
My Apache Config is
<VirtualHost *:80>
ServerName subdomain.example.com
ServerAlias subdomain.example.com
ServerAdmin admin#domain.in
RewriteEngine On
#RewriteCond %{REQUEST_URI} ^/socket.io [NC]
#RewriteCond %{QUERY_STRING} transport=websocket [NC]
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule ^/mqtt/(.*) ws://localhost:8083/mqtt/$1 [P,L]
ProxyPreserveHost On
ProxyRequests Off
ProxyPass / http://localhost:8083/
ProxyPassReverse / http://localhost:8083/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
Apache access Logs
I changed the log level of apache to 'debug' and these are the error logs. Looks like it is trying to find the /mqtt folder.
I have already enabled mode "proxy_wstunnel.load". How can I connect to mqtt and ws using subdomain?

Add a ServerAlias directive under ServerName
Example:
ServerName domain.com
ServerAlias subdomain.domain.com
Try adding this too
ProxyPass "/" "http://127.0.0.1:8083/mqtt"
ProxyPassReverse "/" "http://127.0.0.1:8083/mqtt"
If you're are not sure if the broker is using socket.io, then remove this line:
#RewriteCond %{REQUEST_URI} ^/socket.io

Related

Attempting to reconnect to the server 1 of 8

Problem with Blazor Test application. I run this app. over Apache server with proxy:
<VirtualHost *:*>
RequestHeader set \"X-Forwarded-Proto\" expr=%{REQUEST_SCHEME}
</VirtualHost>
Listen 192.168.0.190:44366
# for ASP.NET app TestBlazor
<VirtualHost 192.168.0.190:44366>
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:44366/
ProxyPassReverse / http://127.0.0.1:44366/
ServerName 192.168.0.190:44366
# ServerAlias 192.168.0.190:44366
</VirtualHost>
However, a message appears every minute: Attempting to reconnect to the server. Where can be problem ?
Firefox console:
I found the answer here:WebSockets and Apache proxy : how to configure mod_proxy_wstunnel?
Virtual host must be configured as follows:
<VirtualHost *:*>
RequestHeader set \"X-Forwarded-Proto\" expr=%{REQUEST_SCHEME}
</VirtualHost>
Listen 192.168.0.190:44366
# for ASP.NET app TestBlazor
<VirtualHost 192.168.0.190:44366>
ServerName 192.168.0.190:44366
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule /(.*) ws://localhost:44366/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule /(.*) http://localhost:44366/$1 [P,L]
ProxyPass / http://localhost:44366/
ProxyPassReverse / http://localhost:44366/
</VirtualHost>

Websockets not working while running Portainer with Httpd proxying

I've set up the Portainer UI as a docker container, and it's working great if I connect my browser to port 9000 (as in http://foo.bar.com:9000). I can navigate around the UI and open up container consoles (which use websockets) without a problem.
But, what I need to do i connect with SSL (as in https://foo.bar.com).
I set up an httpd container on the same machine, and gave it the following configuration file:
<VirtualHost *:443>
ServerName foo.bar.com
ProxyPass / http://foo.bar.com:9000/
ProxyPassReverse / http://foo.bar.com:9000/
RequestHeader set X-Forwarded-Proto "https"
<Location /api/websocket/>
RewriteEngine on
RewriteCond %{HTTP:UPGRADE} ^WebSocket$ [NC]
RewriteCond %{HTTP:CONNECTION} Upgrade$ [NC]
RewriteRule /api/websocket/(.*) ws://foo.bar.com:9000/api/websocket/$1 [P]
</Location>
## SSL directives
SSLEngine on
SSLCertificateFile "/usr/local/apache2/conf/server.crt"
SSLCertificateKeyFile "/usr/local/apache2/conf/server.key"
## Logging
ServerSignature Off
ErrorLog "logs/error_ssl.log"
CustomLog "logs/access_ssl.log" common
</VirtualHost>
Both httpd and portainer are being brought up by separate docker-compose.yml files.
Now, the Portainer web pages still come up just fine, but the consoles for the containers won't work. Somehow, my websocket configuration above is broken. Any ideas on what I might be doing wrong?
After hours of playing with it, I finally got this to work and wanted to share. First, at least in httpd 2.4, you need to explicitly load mod_proxy_wstunnel.so so make sure and put a LoadModule in. Until you do that, nothing will work.
Here is the httpd configuration that was successful:
<VirtualHost *:443>
ServerName foo.bar.com
ProxyPreserveHost on
ProxyPreserveHost On
ProxyRequests Off
# allow for upgrading to websockets
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule ^/?(.*) ws://foo.bar.com:9000/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule ^/(.*) http://foo.bar.com:9000/$1 [P,L]
ProxyPass "/" "http://foo.bar.com:9000/"
ProxyPassReverse "/" "http://foo.bar.com:9000/"
## SSL directives
SSLEngine on
SSLCertificateFile "/usr/local/apache2/conf/server.crt"
SSLCertificateKeyFile "/usr/local/apache2/conf/server.key"
## Logging
ServerSignature Off
ErrorLog "logs/error_ssl.log"
CustomLog "logs/access_ssl.log" common
</VirtualHost>
Thanks a lot - saved me lot of trouble setting this up in Apache. I'm using it in local network only so I don't care much about https and certs so I've modified it bit to go through http
<VirtualHost *:80>
ServerName foo.bar.com
ServerAlias foo.bar.alias.com
ProxyPreserveHost On
ProxyRequests Off
# allow for upgrading to websockets
RewriteEngine On
RewriteCond %{HTTP:Upgrade} =websocket [NC]
RewriteRule ^/?(.*) ws://localhost:9000/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket [NC]
RewriteRule ^/(.*) http://localhost:9000/$1 [P,L]
ProxyPass "/" "http://localhost:9000/"
ProxyPassReverse "/" "http://localhost:9000/"
# Logging
ErrorLog ${APACHE_LOG_DIR}/portainer_error.log
CustomLog ${APACHE_LOG_DIR}/portainer_access.log combined
</VirtualHost>

Redirect http to https only works after page refresh Apache2

I have installed SSL Certificates on my website and on the example.com everything works fine, meaning that typing example.com redirects correctly to https://example.com. However, I have installed a certificate for a subdomain as well such that the link becomes: subdomain.example.com.
My goal is to have subdomain.example.com redirect to https://subdomain.example.com . This might sound weird but this semi-works meaning that when I first surf to subdomain.example.com it uses the http protocol but when I refresh that same page it switches to https protocol.
This is my VirtualHost conf file (port 80):
<VirtualHost *:80>
ServerName subdomain.example.com
ServerSignature Off
ProxyPreserveHost On
AllowEncodedSlashes NoDecode
<Location />
Require all granted
ProxyPassReverse http://127.0.0.1:8181
ProxyPassReverse http://example.com/
</Location>
RewriteEngine on
#Forward all requests to gitlab-workhorse except existing files like error documents
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_URI} ^/uploads/.*
RewriteRule .* http://127.0.0.1:8181%{REQUEST_URI} [P,QSA,NE]
# needed for downloading attachments
DocumentRoot /opt/gitlab/embedded/service/gitlab-rails/public
RewriteCond %{SERVER_NAME} =subdomain.example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
#RewriteCond %{SERVER_PORT} !443
#RewriteRule ^(/(.*))?$ https://%{HTTP_HOST}/ [R=301,L]
</VirtualHost>
I have removed to non related lines from this sample above. Here is the 443 conf file:
< IfModule mod_ssl.c>
SSLStaplingCache shmcb:/var/run/apache2/stapling_cache(128000)
<VirtualHost *:443>
ServerName subdomain.example.com
ServerSignature Off
< IfModule mod_ssl.c>
SSLStaplingCache shmcb:/var/run/apache2/stapling_cache(128000)
<VirtualHost *:443>
ServerName subdomain.example.com
ServerSignature Off
ProxyPreserveHost On
AllowEncodedSlashes NoDecode
<Location />
Require all granted
#Allow forwarding to gitlab-workhorse
ProxyPassReverse http://127.0.0.1:8181
ProxyPassReverse http://domain/
</Location>
RewriteEngine on
#Forward all requests to gitlab-workhorse except existing files like error documents
RewriteCond %{DOCUMENT_ROOT}/%{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_URI} ^/uploads/.*
RewriteRule .* http://127.0.0.1:8181%{REQUEST_URI} [P,QSA,NE]
# needed for downloading attachments
DocumentRoot /opt/gitlab/embedded/service/gitlab-rails/public
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/subexample.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
Header always set Strict-Transport-Security "max-age=31536000"
SSLUseStapling on
Header always set Content-Security-Policy upgrade-insecure-requests
</VirtualHost>
</IfModule>
Worth noting is that I am using certbot.
Hopefully someone can help me.
You say "My goal is to have subdomain.example.com redirect to https://subdomain.example.com".
Then why have all that proxy configuration in your :80 VirtualHost? Simply force the redirection to :443, and let :443 handle the proxy (and other).
So your VirtualHost would become:
<VirtualHost *:80>
ServerName subdomain.example.com
CustomLog logs/subdomain_80_access.log combined
ErrorLog logs/subdomain_80_error.log
RewriteEngine On
RedirectMatch ^/(.*)$ https://subdomain.example.com/$1
</VirtualHost>

Configure Apache with multiple ProxyPass and different ports

so i have a config file that states this
<VirtualHost *:80>
ProxyPreserveHost On
ProxyRequests Off
ServerName www.aaaaaaaa.yyyyyyyyy.co.uk
ServerAlias aaaaaaa.yyyyyyy.co.uk
ProxyPass / http://localhost:5000/
ProxyPassReverse / http://localhost:5000/
RewriteEngine on
RewriteCond %{SERVER_NAME} =www.aaaaaaa.yyyyyyyyy.co.uk [OR]
RewriteCond %{SERVER_NAME} =aaaaaa.yyyyyyyyy.co.uk
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
<VirtualHost *:80>
ProxyPreserveHost On
ProxyRequests Off
ServerName www.xxxxxx.yyyyyyyy.co.uk
ServerAlias xxxxxxx.yyyyyyyyy.co.uk
ProxyPass / http://localhost:8989/
ProxyPassReverse / http://localhost:8989/
RewriteEngine on
RewriteCond %{SERVER_NAME} =www.xxxxxxxxxxx.yyyyyyyy.co.uk [OR]
RewriteCond %{SERVER_NAME} =xxxxxx.yyyyyyyyyy.co.uk
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
when visiting aaaaaaa.yyyyyyyyy.co.uk it redirects to https which is the desiered effect and launches the correct app.
however when i visit xxxxx.yyyyyyy.co.uk it shows the correct app but does not redirect to https, when i physically type https://xxxx.yyyyyy.co.uk it redirects me to the same app as aaaaaaa.yyyyyyyyyy.co.uk.
how can i make this work!
The main issue here is certbot dosn't play nice with multiple hosts in 1 file.
The steps to correct the problem where;
1 remove all certificates
2 recreate all virtual hosts in there own file within sites-availible
(minus the rewrite portion)
example content of one conf file
<VirtualHost *:80>
ProxyPreserveHost On
ProxyRequests Off
ServerName www.aaaaaaaa.yyyyyyyyy.co.uk
ServerAlias aaaaaaa.yyyyyyy.co.uk
ProxyPass / http://localhost:5000/
ProxyPassReverse / http://localhost:5000/
</VirtualHost>
3 after doing this for all virtual hosts (sites) run the command
certbot --apache
and create new certificates for all making sure to select the redirect function at the end.
worked great!

How to configure apache2 subdomains to route to different servers

I am running apache 2.4.7 and presently all my traffic is going to a backend server on 8080 on the same server/instance.
I want my www traffic to go to a new server/instance and all my other subdomains (app, api, etc.) to go to the existing 8080.
Can somebody provide some direction?
Help appreciated.
<VirtualHost *:80>
ProxyPreserveHost On
ServerAdmin webmaster#example.com
ServerName example.com
Redirect "/" "https://www.example.com/"
RewriteEngine On
RewriteCond %{HTTP:X-Forwarded-Proto} !https
RewriteRule ^.*$ https://%{SERVER_NAME}%{REQUEST_URI}
ServerAlias www.example.com
DocumentRoot /var/www/example.com/public_html/
Redirect "/ft/" "/"
ErrorLog /var/www/example.com/logs/error.log
CustomLog /var/www/example.com/logs/access.log combined
ProxyPass / http://0.0.0.0:8080/
ProxyPassReverse / http://0.0.0.0:8080/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
If you want to do an external redirect to the new server for the www subdomain, you'll need to add the following to your configuration, under the other rewrite rules:
RewriteCond ${HTTP_HOST} ^www\. [NC]
RewriteRule ^ https://www.example.com/${REQUEST_URI} [L,R=301]
And you would need to remove the ServerAlias directive. This is also assuming you've already pointed DNS to the new host.
If the new box serving the www content is to be another backed server, you would need another virtual host. Add the following at the top instead:
<VirtualHost *:80>
ServerName www.example.com
ProxyPass / http://other-box/
ProxyPassReverse / http://other-box/
</VirtualHost>
And you still would need to remove the ServerAlias directive.