Apache Reverse Proxy based on subdomain - regex

I am currently trying to set up Apache2 as reverse proxy rewriting based on a subdomain's hostname.
Any request sent to *.accepted-terms.mydomain.tld should be forwarded to a local port using the Host *.mydomain.tld. Simply, the .accepted-terms in the middle should be cut away.
Eg
foo.accepted-terms.mydomain.tld → foo.mydomain.tld:6443
bar.accepted-terms.mydomain.tld → bar.mydomain.tld:6443
<VirtualHost *:443>
SSLEngine on
[...] # SSL Certificates
SSLProxyEngine On
ProxyPreserveHost On
ServerName accepted-terms.mydomain.tld
ServerAlias *.accepted-terms.mydomain.tld
ProxyPass / https://0.0.0.0:6443/
ProxyPassReverse / https://0.0.0.0:6443/
#-------- Here, the fun starts:
SetEnvIf Host ^(.*)accepted-terms\.mydomain\.tld$ new_host=$1
RequestHeader set Host %{new_host}emydomain.tld
#------- Here, the fun should be done.
RequestHeader set Cookie "disclaimer_accepted=true"
</VirtualHost>
Unfortunately, my tries based on SetEncIf and the Host were unsuccessful. Is there any way to realize this?

I found a solution.
<VirtualHost *:443>
# [...] SSL
SSLProxyEngine On
SSLProxyCheckPeerName Off
ServerName accepted-terms.mydomain.tld
ServerAlias *.accepted-terms.mydomain.tld
SetEnvIf Host ^(.*).accepted.onionroot.network$ new_host=$1
RequestHeader set Host %{new_host}e.onionroot.network
RequestHeader set Cookie "disclaimer_accepted=true"
ProxyPreserveHost On
ProxyPass / https://0.0.0.0:6443/ retry=1 acquire=3000 timeout=600 Keepalive=On
ProxyPassReverse / https://0.0.0.0:6443/
</VirtualHost>
It seems like reordering the configuration solved the issues.

Related

Reverse Proxy for Django App 404 Not Found

I am following this guide to try show this url www.mycompany.com/testblog instead of www.mycompany.com:8000/testblog
These are my current config files setup inside my website.comssl.conf file
<VirtualHost *:80>
ServerAdmin webmaster#localhost
ServerName website.com
ServerAlias www.website.com
DocumentRoot /var/www/website.com
Redirect permanent / https://website.com/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
`
<VirtualHost *:443>
ServerAdmin webmaster#localhost
ServerName website.com
ServerAlias www.website.com
DocumentRoot /var/www/website.com
SSLEngine on
SSLCertificateFile /etc/ssl/certs/website.com.cer
SSLCertificateKeyFile /etc/ssl/private/website.com.key
SSLCertificateChainFile /var/www/website.com/SSLCert/SSLIntermediateCertificate.cer
ProxyPreserveHost On
ProxyPass /testblog https://website.com:8000/testblog
ProxyPassReverse /testblog https://website.com:8000/testblog
</VirtualHost>
However, when I run my server and try to access the URL www.mycompany.com/testblog I get a 404 Not Found error
Have you load proxy module
On Centos/RedHat
$> grep -R "mod_proxy" /etc/httpd/conf.modules.d/
.....
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
.....
On Ubuntu
$> a2enmod proxy
$> a2enmod proxy_http
ProxyPass /testblog https://website.com:8000/testblog
ProxyPassReverse /testblog https://website.com:8000/testblog
This is very uncommon to do for two reasons:
Normally you reverse proxy stuff that's not available via public domain name. Often it runs on the same machine or on another machine in the same network. In this case, use the IP instead (127.0.0.1 for the local machine or the IP shown in ip addr command on the other machine)
You're using https: but backend services are normally not SSL protected. Also port 8000 is very uncommon for SSL.
In other words, are you sure you want this and not ProxyPass /testblog http://127.0.0.1:8000/testblog

Apache2 : Limit virtual host to one domain name

i want to do something but i can't find an answer (Maybe i baldy searched). I don't know if it is possible so say me if it's not.
I would like to limit an apache virtual host to one and only domain name : bde.yggdrasil.cafe. So that if the user try to access this website using 90.90.3.57 or another domain name it is listed as not existing website. Here is my extra/bde.conf which is included in httpd.conf, you'll understand the problem :
<VirtualHost *:80>
ServerName bde.yggdrasil.cafe
ServerAdmin my#email.fr
DocumentRoot /srv/http/bdeweb
#Some django config
#[...]
RewriteEngine on
RewriteCond %{SERVER_NAME} =bde.yggdrasil.cafe
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
Listen 443
<VirtualHost *:443>
ServerName bde.yggdrasil.cafe
ServerAdmin my#email.fr
DocumentRoot /srv/http/bdeweb
#Some django config
#[...]
SSLEngine on
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/bde.yggdrasil.cafe/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/bde.yggdrasil.cafe/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
If i use this code and i try to connect to 90.90.3.57 or yggdrasil.cafe using http protocol my request is catched by django which return an error 400 (It is good but not what i want to get). if i connect to bde.yggdrasil.cafe using http it redirect me correctly to https.
DNS Redirection
I think it can be usefull so i give you my DNS Redirections :
yggdrasil.cafe --> 90.90.3.57
bde.yggdrasil.cafe --> yggdrasil.cafe
Removing Django config
If i remove the django configuration in my HTTP virtual host and i use the following file :
<VirtualHost *:80>
ServerName bde.yggdrasil.cafe
RewriteEngine on
RewriteCond %{SERVER_NAME} =bde.yggdrasil.cafe
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
Listen 443
<VirtualHost *:443>
ServerName bde.yggdrasil.cafe
ServerAdmin my#email.fr
DocumentRoot /srv/http/bdeweb
#Some django config
#[...]
SSLEngine on
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/bde.yggdrasil.cafe/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/bde.yggdrasil.cafe/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
If i try to connect to my server using 90.90.3.57 or yggdrasil.cafe i fall on "Indexes of /" (Wich is bad, realy bad).
I would like apache to ignore the connection if the user doesn't user the subdomain "bde.yggdrasil.cafe".
Why i want to do that ?
This domain is for all my stuff, including a future personal showcase website i would like to host on "yggdrasil.cafe" domain name (without subdomain).
So the important is not the result but i would like to know if it is possible to add an other VirtualHost on "yggdrasil.cafe" domain name afterward without django catching it.
Thanks for your time :)
Solution
As said by Dusan Basic
Of course, just add another VirtualHost with ServerName yggdrasil.cafe; for the beginning you can have simple RewriteRule ^ - [F]
It fixed the problem :)

Configure apache to respond with error page for incorrect hosts

django docs:
You should also configure the Web server that sits in front of Django to validate the host. It should respond with a static error page or ignore requests for incorrect hosts instead of forwarding the request to Django. This way you’ll avoid spurious errors in your Django logs (or emails if you have error reporting configured that way). For example, on nginx you might setup a default server to return “444 No Response” on an unrecognized host:
I am using Apache and this works:
http://serverip -> 404 error
http://www.example.com -> https://www.example.com -> django site
http://example.com -> https://example.com -> django site
Now I have a problem with https://serverip
I get a not secure message by my browser because I only have a SSL Cert for example.com, www.example.com and after I accept the security warning I see the django site but I want 404 error page.
How can I achieve this or do I misunderstand the django docs?
Update Config:
assume the django site is /var/www/html/index.html for simplification
000-default.conf:
<VirtualHost *:80>
Redirect 404 /
</VirtualHost>
example.com.conf:
<VirtualHost *:80>
ServerAdmin example#example.com
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
RewriteEngine on
RewriteCond %{SERVER_NAME} =www.example.com [OR]
RewriteCond %{SERVER_NAME} =example.com
RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [END,NE,R=permanent]
</VirtualHost>
example.com-le-ssl.conf:
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin example#example.com
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/html
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>
</IfModule>

AWS Apache2 reverse proxy with godaddy not working

I have purchased a godaddy domain and AWS EC2 instance with elastic ip. In godaddy I created following entries
A-name entry ( mydomain.com ) pointing to elastic ip
And a C-name entry (app2.mydomain.com) pointing to same elastic ip
Inside amazon EC2 instance , I am running two applications
app1 - running on localhost:3000
app2 - running on localhost:4000
Now, I am trying to achieve below
mydomain.com should point to app1 running on localhost:3000
app2.mydomain.com should point to app2 running on localhost:4000
I have installed apache2 on EC2 and followed below links to configure reverse proxy
link1
I created myproxy.conf under apache2/sites-available as below
<VirtualHost mydomain.com:80>
ServerName mydomain.com
ProxyPreserveHost On
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
</VirtualHost>
<VirtualHost app2.mydomain.com:80>
ServerName app2.mydomain.com
ProxyPreserveHost On
ProxyPass / http://localhost:4000/
ProxyPassReverse / http://localhost:4000/
</VirtualHost>
But I can't get it working. But when I change the conf as below
<VirtualHost *:80>
ServerName app2.mydomain.com
ServerAdmin admin#mydomain.com
ProxyPreserveHost On
ProxyPass / http://localhost:4000/
ProxyPassReverse / http://localhost:4000/
</VirtualHost>
Both mydoamin.com and app2.mydomain.com launch same app2 application.
I could not figure out what I am missing.
Edit
Soon after I post this, I tried something which seems to work. I added *.80 instead of app2.mydomain.com
<VirtualHost *:80>
ServerName app2.mydomain.com
ServerAdmin admin#mydomain.com
ProxyPreserveHost On
ProxyPass / http://localhost:4000/
ProxyPassReverse / http://localhost:4000/
</VirtualHost>
<VirtualHost *:80>
ServerName mydomain.com
ServerAdmin admin#mydomain.com
ProxyPreserveHost On
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
</VirtualHost>
Currently you are trying to run code on apache2 default port 80.
You need to run both application on diff port.Try running code on different port
<VirtualHost *:8081>
Listen 8081
ServerName mydomain.com
ServerAdmin admin#mydomain.com
ProxyPreserveHost On
ProxyPass / http://localhost:3000/
</VirtualHost>
Don't forget to open port in listen mode by LISTEN port_no

How do I properly handle multiple VirtualHosts on one server with only one having SSL?

I have the following apache2 VirtualHost config:
<VirtualHost {my_server_ip}:443>
ServerName securesite.com
ServerAlias www.securesite.com
DocumentRoot /data/web/securesite.com/
Options -Indexes
SSLEngine On
SSLCertificateFile /etc/ssl/securesite.com/securesite.com.crt
SSLCertificateKeyFile /etc/ssl/securesite.com/server.key
SSLCertificateChainFile /etc/ssl/securesite.com/gd_bundle.crt
</VirtualHost>
<VirtualHost *:80>
DocumentRoot /data/web/unsecuresite.com/
ServerName unsecuresite.com
ServerAlias www.unsecuresite.com
</VirtualHost>
The problem is that I can access https://unsecuresite.com/ and the server returns the data for securesite.com and the browser complains.
Why does this happen? Why does ServerName for 443 matches other server names?
Can I somehow handle this? Maybe catch the request, handle it with regex and redirect it to its proper place?
EDIT
ports.conf says:
NameVirtualHost *:80
Listen 80
<IfModule mod_ssl.c>
NameVirtualHost {my_server_ip}:443
Listen 443
</IfModule>
When you connect to https://securesite.com/, then you are actually connecting to port 443. Since there is only one site listening on port 443, the first match is returned (even though the ServerName does not match.
Your configuration basically boils down to:
<VirtualHost {my_server_ip}:443>
ServerName securesite.com
# ...
</VirtualHost>
<VirtualHost *:80>
ServerName unsecuresite.com
# ...
</VirtualHost>
This means that any request to port 80 (http) will be served by unsecuresite.com and requests to port 443 (https) are served by securesite.com.
Even if you add a <VirtualHost *:443> ServerName unsecuresite.com, you can still not simply trick the user to redirect without having a valid certificate for unsecuresite.com. (That would result in a ugly certificate warning.)
If your unsecuresite.com vhost is not supposed to handle HTTPS, then just ignore it. With nginx you could reset a connection if the hostname does not match, I don't know if something similar exists for Apache.
I solved it with the following method:
<VirtualHost {my_server_ip}:443>
ServerName securesite.com
ServerAlias www.securesite.com
DocumentRoot /data/web/securesite.com/
Options -Indexes
SSLEngine On
SSLCertificateFile /etc/ssl/securesite.com/securesite.com.crt
SSLCertificateKeyFile /etc/ssl/securesite.com/server.key
SSLCertificateChainFile /etc/ssl/securesite.com/gd_bundle.crt
RewriteEngine on
RewriteCond %{HTTP_HOST} !^(www\.)?(securesite\.com){1}$ [NC]
RewriteRule ^(.*)$ http://%{HTTP_HOST}$1 [R=301]
</VirtualHost>