I am using this config with apache 2.4.53 and declaring a reverse proxy for 2 different domains, each with an identical config as shown.
<VirtualHost *:443>
ServerName www.example.com
SSLProxyEngine on
ProxyPreserveHost On
<Location "/">
Require all granted
ProxyPass http://192.168.163.10/
ProxyPassReverse http://192.168.163.10/
</Location>
SSLEngine on
SSLCertificateFile /etc/httpd/conf/vhosts/certs/cert.pem
SSLCertificateKeyFile /etc/httpd/conf/vhosts/certs/privkey.pem
SSLCertificateChainFile /etc/httpd/conf/vhosts/certs/fullchain.pem
</VirtualHost>
The request is going down to a target server using apache 2.2.22.
There www.example.com is declared as <VirtualHost *:80>.
The content of the website delivered is shown and https is used. Nevertheless I am facing problems using the CMS-interfaces (two different CMSes) the target is providing. Both let me log in successfully but one (silverstripe) is not showing the admin interface at all, the other (modx) is showing it but if I like to save my content it will display ...saving... all the time but won't save at all. Both is working with reverse proxy when the <VirtualHost *:80> at the RP is listening http.
Maybe my general understanding about RP is wrong. Is it okay to define it like I did and hope to get a valid https connection? It is obvious that the last step (RP-> target) is not encrypted, so maybe this is a no-go?
If it is a valid config has anyone got an idea why (maybe cookies?) this behaviour appears?
Any help is very welcome.
Thanks.
Related
So far, I've got a funny problem. I had a socket running on my server for months, and I've came up with an idea of changing the host name.
After I did change the host name, and the links to the certificates, the socket no longer worked.
I own both domain names currently, let's say they are example-old.com and example.com, and I have certificates for both domains, issued by Cloudflare, both are wildcard ones (i.e., for example.com and *.example.com).
I didn't change the server, I didn't even restart it. When I change example back to example_old, both server name and certificate paths, everything works again. However, once I put the newer domain name here, nothing changes for it - socket.example.com just resolves as a 404 (as it would be even without virtual host declaration).
So, here's the code in /etc/apache2/sites-available/000-default.conf which declared my socket server.
<VirtualHost *:80>
ServerName socket.example.com
ServerAdmin webmaster#localhost
DocumentRoot /var/www/html
ProxyVia on
RewriteEngine on
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>
<VirtualHost *:443>
DocumentRoot /var/www/html
ServerName socket.example.com
SSLEngine on
SSLCertificateFile /var/www/subdomains/example/example.pem
SSLCertificateKeyFile /var/www/subdomains/example/example.key
SSLCertificateChainFile /var/www/subdomains/example/example.pem
SSLProxyEngine On
ProxyPreserveHost On
ProxyRequests Off
# This is for websocket requests
ProxyPass /wss wss://localhost:9024/
ProxyPassReverse /wss wss://localhost:9024/
ProxyPass /wchat wss://localhost:9025/
ProxyPassReverse /wchat wss://localhost:9025/
ProxyPass / https://localhost:3333/
ProxyPassReverse / https://localhost:3333/
</VirtualHost>
I don't really remember if this change is the only one that has to be done in order for changing my socket server.
As a socket, I use Workerman for PHP. As neither the port, nor the server changed, I left my file socket.php untouched. When I launch the socket.php with the new domain names in /etc/apache2/sites-available/000-default.conf, everything is silent, it doesn't respond neither to new connections, nor to anything else.
I also experimented with leaving running socket under the old domain name, declaring the same virtual host for the new domain name and trying to launch another instance of socket. The one, running on the old domain, works perfectly, while the new doesn't.
What could I do wrong? As far as I understand, there're must be something else that I must have done months ago when launching the original socket server. However, I don't remember what was it.
I found the solution finally, if anyone is wondering
Switched flexible to full encryption on Cloudflare and everything started working
I know, I know, Apache is not the best tool to use as HTTP proxy, however I need it on my server.
Here's my virtual host configuration:
<VirtualHost *:*>
RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}
</VirtualHost>
<VirtualHost *:80>
ServerName my.public.domain
Redirect / https://my.public.domain/
</VirtualHost>
<VirtualHost *:443>
ProxyPreserveHost On
ProxyPass / http://127.0.0.1:50001/
ProxyPassReverse / http://127.0.0.1:50001/
ServerName my.public.domain
ErrorLog ${APACHE_LOG_DIR}my-app-error.log
CustomLog ${APACHE_LOG_DIR}my-app-access.log common
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/my-cert/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/my-cert/privkey.pem
</VirtualHost>
In UseUrls method i have http://localhost:50001 configured as main URL, and this is redirected by Apache to HTTPS #443.
It works as charm, however I see this in logs:
warn: Microsoft.AspNetCore.HttpsPolicy.HttpsRedirectionMiddleware[3]
Failed to determine the https port for redirect.
In my configuration Apache handles https traffic, BTW, I can't communicate my app with Apache locally over HTTPS, it just doesn't work. I also think it's pointless to encrypt local internal traffic.
Unfortunately my solution requires some hacking to work 100% properly - I need to provide my public site URL in my app configuration - otherwise the app doesn't know what it's external address is. I mean - I build some links manually, because this is the core of my question - I don't know where the framework would keep such information. For example NavigationManager thinks my site URL is "http://localhost:50001", so if I need absolute URL in my app I can't use NavigationManager directly, I need to "manually" create the URL in app.
Links generated by Identity have "http" instead of "https", but it works because apache redirects everything to https.
Is there a way (and HOW) to do it more properly - a mean to officially tell the AspNET.Core it has specific external URL?
Where you have ServerName my.public.domain, use the following:
For port 80:
ServerName http://my.public.domain:80
For port 443:
ServerName https://my.public.domain:443
I have an httpd server configured and working. The server returns "It works" and I can see the SSL is installed correctly.
The next step I undertook was configuring the reverse proxy, so that the users requests are redirected and I can have more customers' apps under one subdomain. The httpd configuration (shown below) I use is not mine, I am just attempting to reconfigure it to work for me. But with no big success up to now. There are directives that may be incorrect, but I have not tried commenting anything out.
#Apache is listening on port 443
Listen 443
SSLSessionCache shmcb:c:/Apache24/logs/shmcb_cache(512000)
SSLSessionCacheTimeout 300
Mutex default ssl-cache
SSLRandomSeed connect builtin
SSLCryptoDevice builtin
<VirtualHost *:443>
#ProxyPreserveHost On
SSLProxyEngine On
ServerName XXXX.sk
ServerAdmin admin
# Logs
ErrorLog /var/log/rsk_error_log
TransferLog /var/log/rsk_access_log
# Server Certificate and Private Key:
SSLCertificateFile /ssl/certificate.crt
SSLCertificateKeyFile /ssl/private.key
SSLCertificateChainFile /ssl/chain.crt
#Include conf/extra/proxy-443-to-8890.conf
ProxyPass /customer http://172.17.0.4:8080
ProxyPassReverse /customer http://172.17.0.4:8080
</VirtualHost>
Now when I type XXXX.sk/customer I receive a response which is a login screen, but it is incorrectly rendered, the CSS is not used at all. There are many errors appearing. When I log in, no response is returned and the URL is corrupted.
Can any of you, using httpd in a reverse proxy mode, please share your configs, at least a part of them?
The default webroot in base-component is mapping to / in url. All of resources like css, js etc is using "/" to build url, So Although the proxying is
ProxyPass /customer http://172.17.0.4:8080
The actual js location is still
/lib/jquery/jquery-ui.min.css
not
/customer/lib/jquery/jquery-ui.min.css
To make it work, the reverse proxy would need more messy location proxy_pass configurations.
So using additional path to proxy the webroot is not suggested.
I have a host with a single web app and at the moment I am accessing it via www.hostnameA.com/ as the web app is deployed to tomcat/webapps as the tomcat ROOT web app.
Now I need to add another web app to my host and I also want this one to have no context either but will access it via another hostname www.hostnameB.com/ but I can only deploy one ROOT tomcat web app.
I should have added that I am using apache as well and my virtual host looks like:
<VirtualHost *:80>
ServerName www.hostnameA.com
ProxyRequests Off
ProxyPreserveHost On
<Proxy *>
Order deny,allow
Allow from all
</Proxy>
ProxyPass / http://localhost:8080/
ProxyPassReverse / http://localhost:8080/
</VirtualHost>
I tried renaming the war file to webAppA and then appending that to the proxypass but it gave me a 400 error and kept appending /webAppA to the URL:
ProxyPass / http://localhost:8080/webAppA
Is there a solution to this? I dont really want to run multiple instances of tomcat on different ports just for this, is there another option?
As discussed above, most straightforward solution would be to use Apache's mod_proxy_ajp, allowing proxying and AJP forwarding at the same time. Configuration should look something like:
<VirtualHost *:80>
ServerName www.hostnameA.com
ProxyPass / ajp://localhost:8009/webAppA/
ProxyPassReverse / http://www.hostnameA.com/webAppA
[...]
...and same with B for www.hostnameB.com.
I want to proxy a website – let’s call it “APP” - through Apache 2.4 using two different reverse proxies with different host names (virtual hosts). Let’s call those proxies “Alfa” and “Beta”. I want Alfa to be the “public proxy” which will show the normal version of the website. The Beta proxy will limit public access to certain client IPs, but here I want to show – on top of each page of the website – some type of sensitive information. Let’s call those portions of sensitive information “SENS”.
Here’s my current apache config.
Listen 443
NameVirtualHost *:443
SSLStrictSNIVHostCheck off
## Virtual host for the Alfa Proxy
<VirtualHost *:443>
ServerName alfa.mysite.org
RewriteEngine On
<Location /app/>
ProxyPass http://x.x.x.x:8080/app/
ProxyPassReverse http://x.x.x.x:8080/app/
</Location>
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile conf/alfa.crt
SSLCertificateKeyFile conf/alfa.key
</VirtualHost>
## Virtual host for the Beta Proxy
<VirtualHost *:443>
ServerName beta.mysite.org
RewriteEngine On
<Location /app/>
Require ip 192.168.0
ProxyPass http://x.x.x.x:8080/app/
ProxyPassReverse http://x.x.x.x:8080/app/
</Location>
SSLEngine on
SSLCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL
SSLCertificateFile conf/beta.crt
SSLCertificateKeyFile conf/beta.key
</VirtualHost>
In order to show SENS only to the users of Beta, I need to programmatically detect which proxy requests come from. Now, I’ve looked into the use of Reverse Proxy Request Headers such as “X-Forwarded-Server”. Let’s say I define some kind of security filter in APP (e.g Spring Filter) that allows SENS to be rendered on page only if X-Forwarded-Server equals “beta.mysite.org”. This should work just fine.
But my question is this: Can I be sure not some kind of tampering with the proxy headers occur that would allow users of the alfa.mysite.org actually view the SENS-portions of my website?
If so, are there any other ways of doing this a “secure manner”.
Having two different versions of APP or deploying APP on two different containers is something I want to avoid here.
Any comments or suggestions are appreciated.
According to the Apache documentation, the x-forwarded-server header can be a comma separated list when multiple proxies are used. So I wouldn't consider it safe from a security point of view.
Under the assumption that your backend server is not directly access, you could try the following.
Set your own HTTP Header which value changes depending on which VirtualHost it passes.
You only have to check then for the existence of the header in the backend.
ServerName alfa.mysite.org
RewriteEngine On
<Location /app/>
#Set - The request header is set, replacing any previous header with this name
RequestHeader set MyCustomHeader "remote"
</Location>
ServerName beta.mysite.org
RewriteEngine On
<Location /app/>
Require ip 192.168.0
#The request header is set, replacing any previous header with this name
RequestHeader set MyCustomHeader "local"
..
</Location>