ProxyPassReverse dropping HTTPS - apache

On my home network, I have a web server and a DNS server. I have various other application servers that I have added redirects for so I can simply visit sites like myapplication.domain.com or www.domain.com/application to get to my various services. I have a Subsonic server running on another server, and my goal is to be able to visit https://subsonic.domain.com and get my Subsonic traffic served over SSL on my web server. Eventually I hope to access this from outside the home, which is why it's important to proxy the non-secured HTTP traffic over HTTPS, but for right now, I'm just trying to get it working at home.
When I visit https://subsonic.domain.com, I end up getting an "unable to connect" error. The address I appear to be redirected to is subsonic.domain.com/login.view. If I tack HTTPS onto the front of that URL, I get the login page I'm looking for. Once I log in again, however, the URL changes, I'm redirected, and I end up losing the HTTPS again an have to keep re-adding it. Obviously I am doing something wrong.
I have set up a VirtualHost for subsonic.domain.com and am trying to use ProxyPass and ProxyPassReverse to get the traffic redirected in the way I want. Here is my VirtualHost for this site:
<VirtualHost subsonic.domain.com:443>
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/])$ /$1/ [L,R=301]
ProxyRequests Off
ProxyErrorOverride Off
ProxyPreserveHost On
ServerAdmin webmaster#localhost
ProxyPass / http://192.168.1.5:4040/
ProxyPassReverse / http://192.168.1.5:4040/
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/apache.crt
SSLCertificateKeyFile /etc/apache2/ssl/apache.key
</VirtualHost>
SSL is definitely up and running with no problem. I have another identical virtualhost for another directory that works fine (redirects on https://www.domain.com/directory), so I'm not sure what the problem is here. After the ProxyPassReverse, the URL just seems to be losing the https:// part. If I add it in, the site works fine until I visit another page and https:// is lost again. If I visit the application server directly at http://192.168.1.5:4040, I have no issues whatsoever.
Any advice would be most welcome.
EDIT
A little clarification on what I'm trying to do. I want to have my Apache server doing all of my redirecting and handling all of my SSL requests. Basically, from the browser to the Apache server is HTTPS, the ProxyPass from the Apache server to the application server us unencrypted HTTP (which is fine, this is my internal network), the ProxyPassReverse from the application server to the Apache server is plain HTTP, then the Apache server sends out the traffic as HTTPS.
Here's another VirtualHost that does what I want for a different subdomain. This is tested and works 100%. I connect to my Apache server via HTTPS, the Apache server contacts my ownCloud server in plain old HTTP, the response to my Apache server is plain HTTP, then the Apache server returns the request in HTTPS to the browser:
<VirtualHost www.domain.com:443>
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*[^/])$ /$1/ [L,R=301]
ProxyRequests Off
ProxyErrorOverride Off
ProxyPreserveHost On
ServerAdmin webmaster#localhost
ProxyPass /owncloud/ http://192.168.1.251/owncloud/
ProxyPassReverse /owncloud/ http://192.168.1.251/owncloud/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/apache.crt
SSLCertificateKeyFile /etc/apache2/ssl/apache.key
</VirtualHost>

So I ran into this problem as well and while commenting out ProxyPreserveHost fixes the problem with the configuration above, there is a better way.
The ProxyPass1 statement tells Apache to take an incoming request on the URI and pass it through to the specified host. With ProxyPreserveHost On, Apache does not change the Host: HTTP header and passes the request unmodified. (By default it changes it to match the backend host specified in the ProxyPass statement).
The ProxyPassReverse2 statement tells Apache to match the host specified with the Host: header on the outgoing response and if it matches to adjust the Location:, Content-Location:, and URI: headers to match the VirtualHost or more specifically what Apache thinks is the canonical name.
So with the following configuration:
<VirtualHost subsonic.domain.com:443>
ProxyPreserveHost On
ProxyPass / http://192.168.1.5:4040/
ProxyPassReverse / http://192.168.1.5:4040/
</VirtualHost>
This is taking a request:
https://subsonic.domain.com/ -> http://192.168.1.5:4040/
but since ProxyPreserveHost is on, it is leaving the Host: header in the request intact as subsonic.domain.com
Your web application is most likely sending a response from subsonic.domain.com but that does not match the ProxyPassReverse rule you have specified:
http://subsonic.domain.com/ <- http://subsonic.domain.com/
So the configuration:
<VirtualHost subsonic.domain.com:443>
ProxyPreserveHost On
ProxyPass / http://192.168.1.5:4040/
ProxyPassReverse / http://subsonic.domain.com/ # Changed to match canonical host
</VirtualHost>
This rule should match the replies coming from the proxy host.

In my VirtualHost for Subsonic, I had to disable the ProxyPreserveHost On directive. I can now access the site externally and internally.
For some reason, this worked fine for my other VirtualHost, but for this one it did not. I'm assuming it's because in my one VirtualHost, the ProxyPass is working on a directory and not a hostname. In my VirtualHost for Subsonic, I don't specify a directory.
To anyone that actually knows what they're talking about in regards to Apache, VirtualHosts, redirects, etc, please feel free to clarify if I'm not describing accurately what's going on.
Here is my VirtualHost for anyone else that is experiencing this same issue.
<VirtualHost subsonic.domain.com:443>
#RewriteCond %{REQUEST_FILENAME} !-d
#RewriteCond %{REQUEST_FILENAME} !-f
#RewriteRule ^(.*[^/])$ /$1/ [L,R=301]
ProxyRequests Off
ProxyErrorOverride Off
#ProxyPreserveHost On - This line now commented out
ServerAdmin webmaster#localhost
ProxyPass / http://192.168.1.5:4040/
ProxyPassReverse / http://192.168.1.5:4040/
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined
SSLEngine on
SSLCertificateFile /etc/apache2/ssl/apache.crt
SSLCertificateKeyFile /etc/apache2/ssl/apache.key
</VirtualHost>

Related

How to Redirection and apply TLS with single web server multiple ports using RewriteEngine and ProxyPassReverse in Apache configuration

I'm running into a very serious problem.
Hope someone kind can help.
Please see the code below first.
This is part of my Apache configuration.
First, the URL of the target web server is http://localhost:30001 ~ 30010. Identifies the site to be accessed through each PORT.
When I receive input as "http://localhost/wksp/30001", I use RewriteEngine to make it "http://localhost:30001". This part works without any problems.
However, I tried to apply TLS and run "https" through ProxyPass and ProxyPassReverse again, but it is very difficult.
From what I understand, ProxyPassReverse accesses "http://localhost:[PORT]/" at first, but then communicates with Proxy through "https://localhost/".
Therefore, when communicating with the https protocol, the PORT cannot be dynamically acquired. For example, if http://localhost:30001 is the target, you need to communicate with the proxy server through port 30001.
In my code now, when HTTPS=on, PORT is written as 30001, but what I want is to keep holding the variable $1 when HTTPS=off.
If you have another approach, that's fine. lots of advice Thank.
<VirtualHost *:443>
...
SSLEngine On
ProxyPreserveHost On
SSLProxyEngine On
ProxyRequests Off
RequestHeader set Front-End-Https "On"
...
RewriteEngine On
RewriteRule ^/wksp/(.*) http://localhost:$1 [P]
ProxyPassReverse / http://localhost:$1
<Location />
Order allow,deny
Allow from all
RewriteEngine On
RewriteCond "%{HTTPS}" =off
RewriteRule ^:(.*) http://localhost:$1/ [P]
ProxyPassReverse http://localhost:$1/
RewriteCond "%{HTTPS}" =on
ProxyPass http://localhost:30001/
ProxyPassReverse http://localhost:30001/
</Location>
</VirtualHost>
If HTTPS=on, if you change the url port of ProxyPass and ProxyPassReverse to $1, the following error is displayed.
httpd[1584880]: AH00526: Syntax error on line 55 of /etc/httpd/conf.d/wksp-tls.conf:
ProxyPass Unable to parse URL: http://localhost:$1/

Apache redirecting to http after log in in ShinyProxy

I have sucessfully set up an Apache HTTPD web server and ShinyProxy instance so that I can access a set of shiny apps over https (on server runing amazon linux).
When I visit
https://www.example.com
I (as expected) get the login page provided by the web applicaiton (shiny proxy). For now this is set up to use simple authentication.
However when I log in (which is sucessful) the page i am viewing redirects me to http://example.com . I need it to stay on https especially because google auth will not allow you to redirect to an http page.
I think the problem is probably with my apache config file. The relevant part is
<VirtualHost *:80>
ServerName example.com
Redirect / https://www.example.com/
</VirtualHost>
<VirtualHost *:443>
ServerName example.com
DocumentRoot /var/www/
SSLEngine on
SSLProxyEngine On
SSLCertificateFile <path to crt>
SSLCertificateKeyFile <path to key>
SSLCertificateChainFile <path to bundle>
# This block is needed for the interal workings off the app
<Proxy *>
Allow from localhost
</Proxy>
RewriteEngine on
RewriteCond %{HTTP:Upgrade} =websocket
RewriteRule /(.*) ws://localhost:3600/$1 [P,L]
RewriteCond %{HTTP:Upgrade} !=websocket
RewriteRule /(.*) http://localhost:3600/$1 [P,L]
ProxyPass / http://localhost:3600/
ProxyPassReverse / http://localhost:3600/
ProxyRequests Off
ProxyPreserveHost On
</VirtualHost>
Does anyone have any thoughts about how I might fix this?
I have found a solution, and so am providing the answer in case anyone else is still stuck.
If you are still having this problem for me the issue was the home page image that I was including in my ShinyProxy application.yml file was served over http, so Apache was forcing the whole website back to http. Exchanging the default image for one served over https fixed the problem.
Additionally in the latest version of ShinyProxy (2.4+) you need to include in application.yml under the server block the line
forward-headers-strategy: native

Redirect specifc HTTPS request to a specific port with apache

I have a problem to redirect some request to an other port. Here's my configuration:
I have a public domain like XXXX.ddns.net
I have a Rapsbian server with apache and files in my /var/www folders are correctly served (angular website)
On the same Raspbian server there is a REST server running on the 3000 port
This is running on HTTPS with SSL(letsencrypt)
I would like that all requests to XXXX.ddns.net/api/* to be redirected to the 3000 port.
I change the .htaccess file and the rewrite rule seems to works on local but I can't make it working from my internet site. API requests achieve with a error 500.
Here is my current .htaccess file:
RewriteEngine On
RewriteRule ^api/(.*) https://localhost:3000/api/$1 [QSA]
# not sure if it should be http or https in the rule but nothing works
#RewriteRule ^api/(.*) http://localhost:3000/api/$1 [QSA]
# If an existing asset or directory is requested go to it as it is
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -f [OR]
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_URI} -d
RewriteRule ^ - [L]
# If the requested pattern is file and file doesn't exist, send 404
RewriteCond %{REQUEST_URI} ^(\/[a-z_\-\s0-9\.]+)+\.[a-zA-Z]{2,4}$
RewriteRule ^ - [L,R=404]
Here is my current 000-default-le-ssl.conf file (in /etc/apache2/sites-available):
<IfModule mod_ssl.c>
<VirtualHost *:443>
ServerAdmin webmaster#localhost
DocumentRoot /var/www/html
ServerName XXXX.ddns.net
SSLCertificateFile /etc/letsencrypt/live/XXXX.ddns.net/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/XXXX.ddns.net/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
<Location /api>
ProxyPass http://127.0.0.1:3000/api
ProxyPassReverse http://127.0.0.1:3000/api
</Location>
</VirtualHost>
</IfModule>
If someone could help me to achieve it...
Thanks!
Your self-found solution looks strange to me. You switch on the SSLProxyEngine and than disable all security measures. Is the backend API running under HTTPS and HTTP at port 3000 at the same time? This is not possible.
I use this setup (apache as proxy to backend application) pretty often and would suggest the following configuration:
As I did not understand the purpose of the rewrite directives I left them out. The VirtualHost at port 80 always redirects HTTP requests to HTTPS. If this works add permanent to the directive (permanent is cached by some browsers, see comment in VirtualHost *:80).
The VirtualHost for HTTPS serves content from your DocumentRoot at /var/www/html. The Directory directive takes care that only correctly addressed files are served (no lookups possible). The VirtualHost also provides the proxy for the /api on the same server on port 3000.
It should work for apache 2.4 if your letsencrypt configuration is correct (fill-in the XXXX). Both VirtualHost configurations can be written into a single file, usually located in /etc/apache2/sites-available with a symlink to /etc/apache2/sites-enabled. Please remove/rename your .htaccess file and other configurations before testing this configuration. If you need access control through apache this could also be configured directly in the VirtualHost configuration.
<VirtualHost *:80>
ServerName XXXX.ddns.net
# Always https
Redirect / https://XXXX.ddns.net/
# Redirect permanent / https://XXXX.ddns.net/
</VirtualHost>
<VirtualHost *:443>
ServerAdmin webmaster#localhost
ServerName XXXX.ddns.net
# These are your SSL settings; your responsibility
SSLCertificateFile /etc/letsencrypt/live/XXXX.ddns.net/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/XXXX.ddns.net/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
# Your document root; where the JavaScript application lives
DocumentRoot /var/www/html
<Directory /var/www/html/ >
Options -Indexes +FollowSymLinks -MultiViews
AllowOverride None
Order Allow,Deny
Allow From All
</Directory>
# Reverse proxy settings for api
ProxyRequests Off
ProxyPreserveHost On
<Location /api >
ProxyPass http://127.0.0.1:3000/api
ProxyPassReverse http://127.0.0.1:3000/api
</Location>
</VirtualHost>
Thanks for your help. I don't really know how but it works now!
I dont rember exactly what i did, but the last one was to modify my 000-default-le-ssl.conf file like this:
SSLProxyEngine On
SSLProxyVerify none
SSLProxyCheckPeerCN off
SSLProxyCheckPeerName off
SSLProxyCheckPeerExpire off
<Location /api>
ProxyPass http://127.0.0.1:3000/api/
ProxyPassReverse http://127.0.0.1:3000/api/
ProxyPass https://127.0.0.1:3000/api/
ProxyPassReverse https://127.0.0.1:3000/api/
</Location>

Apache proxypass - show local file if exist

i use apache proxypass to show content from other server to my base server
i use this code
<VirtualHost *:80>
ServerAdmin webmaster#example.com
DocumentRoot /var/www/html/2
ServerName 2.example.com
ProxyPass /tv http://t1.example.com/tv/
ProxyPassReverse /tv http://t1.example.com/tv/
ErrorLog logs/errorlive_log
CustomLog logs/access_live common
</VirtualHost>
so is there a way first to check if file exist on 2.example.com (/var/www/html/2) if file exist show from this server and if file dont exist then request and server from t1.example.com/tv/
-and i have second question:
if server2 serve a video which is located in server1 and on server 2 are watching 10 users (10mbps) , so from which server will be taken 10mbps from server 2 or server 1 or both servers will have 10mbps load
In apache doc,you can see Ordering ProxyPass and RewriteRule Directives
RewriteRule directives are evaluated before ProxyPass ones.
So, you can add a rewrite rule which test if file exist
<VirtualHost *:80>
ServerAdmin webmaster#example.com
DocumentRoot /var/www/html/2
ServerName 2.example.com
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f
RewriteRule .* - [L]
ProxyPass /tv http://t1.example.com/tv/
ProxyPassReverse /tv http://t1.example.com/tv/
ErrorLog logs/errorlive_log
CustomLog logs/access_live common
</VirtualHost>
RewiteCond test if %{REQUEST_FILENAME} is a regular file and then rewriteRule rewrites to the file. It can be a html, image, php file, etc ...
Now, you can adapt to your need.
EDIT
For second question, I forgot to answer. Sorry, my bad.
According to Apache mod_proxy documentation :
"A reverse proxy (or gateway), by contrast, appears to the client just like an ordinary web server. No special configuration on the client is necessary. The client makes ordinary requests for content in the namespace of the reverse proxy. The reverse proxy then decides where to send those requests and returns the content as if it were itself the origin."
So, both server are loaded.

hosting multiple websites on apache under one ip address

I am trying to host multiple websites (app.diff1.com and app.diff2.com running on tomcat server) on my apache server which are running on ports 8082 and 8083 respectively, to access them i want to use a single domain name (app.in.xxx.com/diff) along with a differentiater (diff1/diff2).I used url rewriting to change the domain names respectively. Now when i am trying to access the websites i always end up with hitting the first virtual host.
Please suggest me if i am not approaching the solution correctly.
Code snippet:
in httpd.conf file.
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{HTTP_HOST} ^app\.in\.xxx\.com/([a-z]*)$
RewriteRule ^ http://www.app.%1.com [L,R=301]
</IfModule>
<IfModule mod_proxy.c>
ProxyRequests off
</IfModule>
NameVirtualHost *:80
<VirtualHost *:80>
ServerName www.app.diff1.com
ProxyPass / http://www.app.diff1.com:8082/
ProxyPassReverse / http://www.app.diff1.com:8082/
</VirtualHost>
<VirtualHost *:80>
ServerName www.app.diff2.com
ProxyPass / http://www.app.diff2.com:8083/
ProxyPassReverse / http://www.app.diff2.com:8083/
</VirtualHost>
Move your rewrites into the first listed virtual host, and stop trying to capture the first path component of the URL as if it were part of HTTP_HOST -- capture it in the RewriteRule itself and use $1.
Also see ServerPath which is an esoteric way to do the same mapping.