Apache proxypass - show local file if exist - apache

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.

Related

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>

How to correctly set Documentroot in Apache serving Plone

I have a Plone site called example.com located at /var/www/Plone (I think). I have the following settings for the site located in sites-available for vhosts (excerpt):
<VirtualHost 10.0.1.4:8082>
ServerAdmin webmaster#localhost
ServerName wiedhas.noip.me
DocumentRoot /var/www/Plone
When I try to reach my site wiedhas.noip.me, apache loads the Plone directory tree and not my Plone site. I can browse through the file system of /var/www/Plone but it is not loading the site. I must not have set the documentroot to the correct directory of my site? Any help much appreciated.
This an excellent docu about running plone behind apache and more.
http://docs.plone.org/manage/deploying/front-end/apache.html
A simple example with ssl, how a vhost could look like:
<VirtualHost $IP:80>
ServerName my.domain.com
Redirect / https://my.domain.com
</VirtualHost>
<VirtualHost $IP:443>
ServerName my.domain.com
ErrorLog logs/my.domain.com-http-error.log
CustomLog logs/my.domain.com-http-access.log combined
Include vhosts.d/....ssl.inc
RewriteEngine On
RewriteRule ^/(.*) http://127.0.0.1:$PORT_OF_PLONE/VirtualHostBase/https/%{SERVER_NAME}:%{SERVER_PORT}/zodb/path/top/plone/VirtualHostRoot/$1 [P,L]
</VirtualHost>
The most important part is the rewrite rule:
RewriteRule ^/(.*) http://127.0.0.1:$PORT_OF_PLONE/VirtualHostBase/https/%{SERVER_NAME}:%{SERVER_PORT}/zodb/path/top/plone/VirtualHostRoot/$1 [P,L]
$PORT_OF_PLONE = Port of your running plone instance
/zodb/path/top/plone = That's where you added the plone site in zope.
Took me a while to get mine going so maybe this helps:
My vhosts looks like this (where my plone site is called 'mywebsite'):
#---------------------------------
# www.mywebsite.com
#---------------------------------
<VirtualHost *:80>
ServerName www.mywebsite.com
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteRule ^/(.*)$ http://127.0.0.1:8081/VirtualHostBase/http/%{SERVER_NAME}:80/mywebsite/VirtualHostRoot/$1 [L,P]
</IfModule>
</VirtualHost>
Hope that helps :)
As you see in the first and correct answer you do not need DocumentRoot. DocumentRoot points to a directory with files to render by Apache. But Plone brings it's own server, the Zope application server, which runs on a different port than Apache. The RewriteRule redirects the incoming request to the application server and modifies the response in a way that the redirection is hidden for the client.

ProxyPassReverse dropping HTTPS

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>

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.

Apache mod-proxy ProxyErrorOverride for specific URL patterns

I am using Apache 2.2 with mod-proxy and I have configured it with several ProxyPass statements to proxy from remote URL to local URL. I need to have custom error documents returned from Apache for these proxied URLs so I set "ProxyErrorOverride On" in my mod-proxy configuration along with some ErrorDocument directives (with local URL path) to return custom error pages for a few HTTP status codes of interest. However, when a status code is returned for which I have NOT created an ErrorDocument directive for, Apache replaces the response body with a default error page instead of leaving the original response body intact. This won't work with the application. So I really have 2 questions:
1) Is it possible to configure Apache to leave the original response body intact for a particular status code if I don't have an ErrorDocument override defined for it?
2) Is it possible to have the ProxyErrorOverride directive only apply to some of the URLs in my ProxyPass statements?
As arober11 pointed out in the comment above:
Afraid the answer is: No and No. If the directive could be limited to
a location, directory, or set of URL's, then there would be something
in the "Context" section, of the man page:
httpd.apache.org/docs/2.2/mod/mod_proxy.html#proxyerroroverride
on the other hand: you can always add it to mod_proxy.c yourself.
For question 2:
Definitely doable. Using internal redirects to either new host or port this is possible. Brief outline using hosts (add noErrorOverrideUrl,doErrorOverrideUrl in DNS or /etc/hosts of apache-machine):
NameVirtualHost *:80
<VirtualHost *:80>
RewriteEngine On
RewriteRule ^(/noErrorOverrideUrl/.*) http://noErrorOverrideUrl$1 [L,P]
RewriteRule ^(/doErrorOverrideUrl/.*) http://doErrorOverrideUrl$1 [L,P]
</VirtualHost>
<VirtualHost *:80>
ServerName noErrorOverrideUrl
ProxyErrorOverride Off
ProxyPass ...
...
</VirtualHost>
<VirtualHost *:80>
ServerName doErrorOverrideUrl
ProxyErrorOverride On
ProxyPass ...
...
</VirtualHost>
Brief outline using ports:
Listen 80
Listen 81
Listen 82
<VirtualHost *:80>
RewriteEngine On
RewriteRule ^(/noErrorOverrideUrl/.*) http://server:81$1 [L,P]
RewriteRule ^(/doErrorOverrideUrl/.*) http://server:82$1 [L,P]
</VirtualHost>
<VirtualHost *:81>
ProxyErrorOverride Off
ProxyPass ...
...
</VirtualHost>
<VirtualHost *:82>
ProxyErrorOverride On
ProxyPass ...
...
</VirtualHost>
You can upgrade apache and use the If sentence avaible on 2.4+
<VirtualHost *:80>
...
<If "%{REQUEST_URI} =~ m#^\/QA(.*)$#">
ProxyErrorOverride Off
</If>
..
</VirtualHost>
Documentation