Apache: Reverse Proxy based on subdomain - apache

I'm trying to set a reverse proxy by replacing the domain and keeping the subdomain.
What I want to achieve is:
abc.example.org shall be reverse proxied to abc.hello.dev
xyz.example.org shall be reverse-proxied to xyz.hello.dev
Note: abc, xyz, etc. are completely dynamic.
What I'm currently not getting is the syntax for ProxyPass and ProxyPassReverse.
Thank you very much,
Cheers
Fritz

Found the solution:
<IfModule mod_proxy.c>
SetEnvIf Host "^([^.]*).example.org$" SUBDOMAIN=$1
ProxyPassInterpolateEnv On
ProxyPass / https://${SUBDOMAIN}.hello.dev/ interpolate
ProxyPassReverse / https://${SUBDOMAIN}.hello.dev/ interpolate
</IfModule>

Related

ProxyPass Exclude path

i configured an apache proxy to forward all calls to another web server. I need to exclude the path http://my-server/{var1}/api/{all-path} (where var1 is variable) from this rule.
How can I do?
Thanks
I tried with:
ProxyPassMatch ^/(.*)/api/(.*)$ !
ProxyPass / http://127.0.0.1:8080/
but not working.
I'd say you need a negative lookahead in your matching pattern and only a single proxy directive:
ProxyPassMatch ^/[^/]+/(?!api/) http://127.0.0.1:8080/
That should match any path starting with something and a following slash, followed by anything that is NOT "api/".

route network traffic based on the subdirectory requested

I have 3 back end nodes to handle traffic but round robin doesn't work in my case.
Is it possible to use Apache web server and route(proxy) all traffic from A-E to server 1, F-S to server 2 and T-Z to server 3? I don't want the url to change.
For example: build.amz.com/TEST should go to server 3 while build.amz.com/ECHO should go to server 1?
I am new to Apache, any directions towards how to achieve this is helpful
You can try something like this:
ProxyRequests Off
ProxyPreserveHost On
ProxyPassMatch ^/([A-Ka-k]+)(.*) http://server1/$1$2
ProxyPassReverse / http://server1/
ProxyPassMatch ^/([L-Pl-p]+)(.*) http://server2/$1$2
ProxyPassReverse / http://server2/
ProxyPassMatch ^/([Q-Zq-z]+)(.*) http://server3/$1$2
ProxyPassReverse / http://server3/
#ProxyPassMatch ^/(.*) http://serverdefault/$1
#ProxyPassReverse / http://serverdefault/

How to server static files + proxy context

I am wondering how to configure my httpd server to serves the following pages:
My need is to serve static content located in my /var/www/static when url is /context/static and to proxy the remaining to a tomcat server
In this order:
/context/static/* --> files served by httpd
/context/* --> resources served by tomcat
I have tried to rewrite /context/static/* to a folder pointing to my /var/www/static and added the ProxyPath directive for the remaining but I can't get it working.
What are the best practices and how to achieve that ?
Thanks in advance
Well, in fact it is quiet easy...
Having such folders configured:
/var/www/static/
|- css/*
|- js/*
\ medias/*
The following httpd configuration will redirect static/* to the /var/www and the rest will be proxied
# first rewrite for statics
RewriteEngine On
RewriteRule ^/context/static/(.+)$ /static/$1
# then proxy remaining...
ProxyPass /context http://127.0.0.1:8080/context
ProxyPassReverse /context http://127.0.0.1:8080/context
I've found the following approach that works and is quite general. (4/12/2018)
Location/Proxypass expressions always take priority over any other location block, so you have to Exclude the paths that you don't want to be proxied. the "?!" does that in the regex. Since static content is, um, static, it is not so bad to require that the apache configuration be updated if another directory is needed to be served directly for a different media type.
The following was taken from a server that was proxying a Python Flask application.
<LocationMatch "^/(?!js|css|media)" >
ProxyPass http://127.0.0.1:5000
ProxyPassReverse http://127.0.0.1:5000
</LocationMatch>
<Location "/">
Require all granted
</Location>
Both of the existing answers rely on Regular Expressions. While they work, it is possible to do this without such complicated constructs. ProxyPass can take "!" as a second parameter, in which case it doesn't proxy the matching URL. For example
ProxyPass /context/static/ !
ProxyPass /context http://127.0.0.1:8080/context
ProxyPassReverse /context http://127.0.0.1:8080/context
or, with multiple exclusions,
ProxyPass /js !
ProxyPass /css !
ProxyPass /media !
ProxyPass / http://127.0.0.1:5000/
ProxyPassReverse / http://127.0.0.1:5000/
These exceptions need to come before the more general rule in order to take precedence.
Thanks to freenode user "thumbs" in #httpd.

How to rewrite / proxy an Apache URI to an application listening on a specific port / server?

They say that Apache's mod_rewrite is the swiss-army knife of URL manipulation, but can it do this?
Lets say I want to add a new application to my Apache webserver, where the only configurable option of the app is a port number.
I want to use & give out URLs of the form "http://hostname.example.com/app" rather than "http://hostname.example.com:8080". This would ensure that clients would be getting through the institution's firewall as well, and it's generally tidier.
My application includes absolute URIs in php, javascript and css, so I want to prepend my own root location to the URI in the applications internal links. I have no access to DNS records and so can't create another name-based virtual server.
Using Apache's mod_rewrite and mod_proxy modules, I can transparently redirect a client to the correct home-page of the application. But links within that homepage don't point a client to links relative to the new base URL.
So, what's the best way of proxying a request to an application that is listening on a specific port?
For example, if I had an application listening on port 8080, I could put this in my Apache configuration:-
<VirtualHost *:80>
SSLProxyEngine On
ServerName myhost.example.com
RewriteEngine On
UseCanonicalName On
ProxyVia On
<Location "/application">
RewriteRule ^/application/?(.*) http://localhost:8080/$1 [P,L]
</Location>
</VirtualHost>
This would work fine if the application didn't use absolute URLs, but it does. What I need to do is rewrite URLs that are returned by the application's css, javascript and php.
I've looked at the ProxyPass and ReverseProxyPass documentation, but I don't think these would work..?
I've also come across Nick Kew's mod_proxy_html, but this isn't included in the standard Apache Distribution, and my institution's webserver seems to have been fine for years without it.. Other than trawling manually (or using a grep -r | sed type expression) through the application's source code, or using this 3rd party add-on, are there any other ways to go about this?
Could I perhaps use some of the internal server variables in a mod_rewrite rule? For example a rewrite rule based on ’HTTP_REFERER'?
Using mod_proxy would work just fine. For instance, I mapped https://localhost/yalla/ to point to a subdirectory of my webserver:
LoadModule proxy_module modules/mod_proxy.so
ProxyRequests On
<Proxy *>
Order deny,allow
Allow from localhost
</Proxy>
ProxyPass /yalla/ http://yalla.ynfonatic.de/tmp/
If you implement this, you'll note that the pictues of the directory-listing aren't visible; this is because they're below the /tmp/ directory on the remote server, hence not visible.
So, in your case you'd do:
LoadModule proxy_module modules/mod_proxy.so
ProxyRequests On
<Proxy *>
Order deny,allow
Allow from localhost # Or whatever your network is if you need an ACL
</Proxy>
ProxyPass /app/ http://hostname.example.com:8080/
Like with everything in Apache configuration, watch those trailing slashes when referring to directories.
Good luck!
Alex.

AJP proxy that maps internal servlet name to a different external name

Using apache2 I want to set up an AJP proxy for a Tomcat server that maps an internal servlet URL to a completely different URL externally. Currently I am using the following configurations:
Apache2 configuration:
<IfModule mod_proxy.c>
ProxyPreserveHost on
ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
ProxyPassReverse /external_name ajp://192.168.1.30:8009/servlet_name
</IfModule>
Note that external_name and servlet_name are different.
Tomcat 6 configuration:
<Connector port="8009" protocol="AJP/1.3" redirectPort="8443" />
This however does not work. Apache seems to forward http requests to Tomcat.
However the URLs and redirects returned by Tomcat are still using the original servlet_name and Apache does not map them to external_name.
Is this possible at all with AJP? If not can it be done using a plain http proxy instead?
Mapping different names between Apache and Tomcat can be quite tricky and depends much on how the web application builds its urls for the response.
Basically your setup is correct, but if your application uses its own servlet_name for redirects and urls ProxyPassReverse won't map them.
If you need this kind of setup have a look at mod_proxy_html (Apache 3rd party module) which will parse and rewrite also the contents, not only the url and response headers as mod_proxy.
( A late answer, but I just ran into this problem myself. )
It appears that ProxyPassReverse using ajp: doesn't work because the headers returned from a redirect don't have an ajp: URL in Location:, they have a http: URL. ProxyPassReverse just causes a rewrite of matching headers, and
that string doesn't match what's being returned.
This should work (provided the Location: field uses that numerical address
and not a host name.)
ProxyPreserveHost on
ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
ProxyPassReverse /external_name http://192.168.1.30/servlet_name
( You can use 'curl -I' to inspect the redirect headers and debug. )
See this note, or a more involved solution here using mod_proxy_html
for rewriting the URLs in web pages as well.
Additionally to the answer from Steven D. Majewski there is one more problem. If the target application uses the request host name to create a redirect (302 Moved Temporarily), it won't work with multiple host names. One must create multiple configurations for every name, like this:
ProxyPassReverse /external_name http://server.com/servlet_name
ProxyPassReverse /external_name http://server.org/servlet_name
ProxyPassReverse /external_name http://server.co.uk/servlet_name
Actually the ProxyPreserveHost on must solve this issue and replace the HOST header in the incoming requests with the address or IP specified in ProxyPass. Unfortunately it seems to be the ProxyPreserveHost doesn't work with ajp connectors. The tomcat in my configuration still received the host name got from browser instead replacing it with 192.168.1.30. As result the browser based redirects still didn't work for every name.
Following configuration didn't work as well :-(
# NOT WORKING !!!
ProxyPassReverse /external_name http://%{HTTP_HOST}/servlet_name
The workaround was using http instead of ajp.
ProxyPreserveHost on
ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
ProxyPassReverse /external_name http://192.168.1.30/servlet_name
Did somebody investigate it deeply?
For me, this seemed to cause problems:
ProxyPreserveHost on
ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
ProxyPassReverse /external_name http://192.168.1.30/servlet_name
While this seemed to work:
ProxyPreserveHost on
ProxyPass /external_name ajp://192.168.1.30:8009/servlet_name
ProxyPassReverse /external_name ajp://192.168.1.30:8009/servlet_name
I don't know why but it just did.