conditional proxypass ajp rules using ip whitelist - apache

I've successfully created a ProxyPass ajp rule which works fine, but now i want to restrict the access of certain urls using an ip-whitelist. In other words, when someone comes from an ip that is not on the whitelist the request should not be proxypassed (and, ideally, some sort of access denied should be issued)
i don't have control over the machine i'm proxy-passing to, so i can't put the ip-whitelist on that machine's configuration. That's why i'm trying to configure this on the same machine that has the proxypass rule.
Defining a <Location /path> with 'Allow from'-rules doesn't work, because the request is still proxypassed. I guess this simply means the proxypass rules preceed the location-rules.
I've tried to work around it by setting an environment variable depending on the remote-address (because then i could proxy non-whitelist-ips to nonexistent url - not pretty, but it would achieve the goal), but it seems the proxypass rule doesn't work with environment variables. Something as simple as this:
SetEnv custom_proxypath=/
ProxyPass %{ENV:custom_proxypath} ajp://10.50.40.21:8009/
ProxyPassReverse %{ENV:custom_proxypath} ajp://10.50.40.21:8009/
doesn't work. while
ProxyPass / ajp://10.50.40.21:8009/
ProxyPassReverse / ajp://10.50.40.21:8009/
works perfectly.
I'm out of options. Does anyone else have a suggestion how to approach this?

I learned this today.... SetEnv is applied later in the request cycle than the ProxyPass, so it isn't set in time. However, SetEnvIf is applied early enough, as are environment variables set with RewriteCond/RewriteRule. You should be able to refactor this to a SetEnvIf that is always true and that will do the trick.

Related

Apache 2.2 Allow from env=_variable_

I have an Apache 2.2 set up with LDAP Authorization, which is working fantastically as expected, and have also made it so that I can bypass Authentication when accessing it locally.
Allow from localIP hostnameA hostnameB, etc...
If I curl from the server, I don't get any Auth Required. So all good and working as expected.
What I need now is to make one particular URL to also bypass authorisation.
I have tried all the usual solution of using SetEnvIf;
SetEnvIf Request_URI "^/calendar/export" bypassauth=true`
Allow from env=bypassauth IP_ADDRESS HOSTNAME_A HOSTNAME_B
But this is just not working!!
Local access is still unrestricted, but remotely it is not (no change there)
If I dump out my server environment variables on that URL's script, I can see my bypassauth variable is being passed.
I just cannot for the life of me figure out why the Allow from env=bypassauth part is not working, while it still obeys the additional directive parameters.
I also tried another suggestion, using the Location directive;
<Location /calendar/export>
Satisfy Any
Allow from all
AuthType None
SetEnv WTF 123
</Location>
Again, I can see my new environmental variable (WTF) appear on this URL (when I dumped the server envs in the script), so I know that the SetEnv and SetEnvIf directives are working.
Is there anything I'm missing (any Apache2.2 quirks?), as all the solutions I've seen so far just are not working. It's as if my Allow from changes are having no effect after restarting Apache. I'm starting to feel my sanity slip.
Is there also a particular order when writing the directives for Satisfy Any, Order allow, deny and the Auth* directives, which might be effecting this?
Finally managed to figure it out!! :)
Seems my url was being processed by mod_rewrite (my environmental variable being prefixed by REWRITE_ should have rung alarm bells), which according to this post https://stackoverflow.com/a/23094842/4800587, the mod_rewrite is performed AFTER our SetEnvIf and Allow directives.
Anyway, long story short; I used the rewritten/final URL and the Location section to bypass authentication using the Allow any directive. So I changed...
<Location "/calendar/export">
Allow from all
</Location>
to..
<Location "/calendar/index.php/export">
Allow from all
</Location>
which is the final URL (after rewrite), and now works.

How to set up a seamless proxy in Apache to get around my ISP's firewall?

I'm really hoping someone can help me out with this because I've been at it for several days and I think I'm going crazy!
I'm trying to do what to me sounds like a stupidly simple thing. I want to set up a proxy server using Apache on a dedicated machine that I rent so that I can get around my ISPs nonsense firewall. I am aware that I could use a VPN, I don't want to do that for reasons that should hopefully become clear after I explain the details of what I want.
First of all, I don't want the proxy server to be used for every request. Only for the sites that are blocked by my ISP.
Suppose I try to access blockedsite.com/path/to/resource and it fails. I then simply want to change the URL in the address bar to proxy.myserver.com/proxy/blockedsite.com/path/to/resource and have Apache handle everything to provide me with a seamless experience. That means,
ProxyPassReverse should modify the response headers to use to the proxy server.
All URLs in the response body should be modified to use the proxy
Here's what I have so far:
<VirtualHost *:80>
ServerName proxy.myserver.com
ProxyRequests off
ProxyPass /proxy/ http://
ProxyPassReverse /proxy/ http://
ProxyPassReverse /proxy/ https://
ProxyHTMLURLMap http:// /proxy/
ProxyHTMLURLMap https:// /proxy/
<Location /proxy/>
ProxyPassReverse /
AddOutputFilterByType SUBSTITUTE text/html
Substitute "s|</title>|</title><meta name='referrer' content='no-referrer' />|ni"
ProxyHTMLEnable On
#ProxyHTMLURLMap / /app1/
RequestHeader unset Accept-Encoding
Order allow,deny
Allow from all
</Location>
</VirtualHost>
This setup works beautifully for URLs that don't try to redirect me elsewhere. But if for example I try to access proxy.myserver.com/proxy/facebook.com I am still being redirected on the client side to https://www.facebook.com instead of https://proxy.myserver.com/proxy/www.facebook.com as I would like. The extra weird thing is that when I set up my own test site which does nothing except redirect me to an HTTPS address, the ProxyPassReverse rule for HTTPS does actually seem to work... but not when I try to access sites like Facebook or Google.
I see no reason to ramble on about my issues, what I'm looking for is astoundingly simple: a transparent, seamless experience! Aside from sticking proxy.myserver.com/proxy/ in front of the URL in the address bar, I shouldn't have to do anything else for it to work. Yet that is not the case and despite over a week of searching, I have found nothing online to help me with this. It's as if I'm the only person in the universe to want to create a simple proxy with Apache that actually works as a firewall-get-arounder.
Please can someone lend me a hand here?! Even just to tell me I'm going about this all wrong and should give up and install Squid or something??
Your last paragraph contains the right answer. You should indeed just "install Squid or something". In particular, I'd recommend Apache Traffic Server - http://trafficserver.apache.org/ - this is exactly what it's made for.
While Apache httpd can do proxying, it's not it's primary function, and so there are always things that will end up being frustrating with it. We could get your above scenario working, but it's really not the right tool for the job.

How to make yii2 module load at root level

I'm more of a frontend guy (CSS, javascript) trying to expand my knowledge about backend (apache, proxies) (so try to be gentle) and I'm asking after serveral hours of documentation, trying different approaches but so far nothing worked. I'm aware that I might be oblivious to concepts that go without saying for someone knowing their way around backend.
I have this Yii2 application, with a module, working fine. I would like this module to be available at the root level of another domain, on the same machine.
From everything I've read, the following code, placed in vhosts of my apache, should work:
<VirtualHost *:80>
ServerName buletin
ProxyPass / http://bdc/ik2/frontend/web/buletin/default/
ProxyPassReverse / http://bdc/ik2/frontend/web/buletin/default/
</VirtualHost>
I'm expecting to see the default action of my module when I go to http://buletin.
What am I missing?
Ok, in case someone else has the same problem, just double check all of your app's redirects and make sure everything works inside your module. If it doesn't, either add it as exception to the ProxyPass i.e.:
ProxyPass /ik2/frontend/web/themes/ http://bdc/ik2/frontend/web/themes/
ProxyPass /ik2/frontend/web/img/ http://bdc/ik2/frontend/web/img/
ProxyPass /ik2/frontend/web/assets/ http://bdc/ik2/frontend/web/assets/
#(all exceptions need to be placed above general ProxyPass and ProxyPassReverse)
or make it available inside your module.
In my case, I wasn't logged in the "new" website and it was redirecting me to /site/login, which did not exist (no buletin/default/site/login). Once I handled it and I added the exceptions for the assets and images to the ProxyPass, it's all working smoothly.

How can LocationMatch and ProxyPassMatch be Combined?

I am setting up an Apache 2.4.6 server on an internal machine for testing purposes. One of the things that Apache server is supposed to do is act as a reverse-proxy for another server found on localhost:3030.
The server on localhost:3030 expects one out of a few dataset names on its first path level (for now, the set comprises only of the dataset experimental, but some more will be added later on), so I am trying to pass that through from the requested path.
In my vhost, this works:
<Location /experimental/>
ProxyPass http://localhost:3030/experimental/
ProxyPassReverse /
</Location>
For additional datasets, I could copy that and replace experimental with the other dataset names. Obviously, that leads to a lot of code duplication/redundancy, which is both a source of errors and a maintenance horror.
Therefore, I would like to become somewhat more flexible and treat several datasets in a single such block. This should be possible with the LocationMatch directive.
As indicated by this comment and this page, I need to replace ProxyPass ProxyPassMatch when using that inside a LocationMatch block. Essentially, the docs state the same:
The same will occur inside a LocationMatch section, however ProxyPass does not interpret the regexp as such, so it is necessary to use ProxyPassMatch in this situation instead.
The LocationMatch docs explain:
From 2.4.8 onwards, named groups and backreferences are captured and written to the environment with the corresponding name prefixed with "MATCH_" and in upper case. This allows elements of URLs to be referenced from within expressions and modules like mod_rewrite. In order to prevent confusion, numbered (unnamed) backreferences are ignored. Use named groups instead.
That information is only valid as of Apache 2.4.8, which is presumeably why the following does not work on my 2.4.6 installation:
<LocationMatch /(?<dataset>experimental)/>
ProxyPassMatch http://localhost:3030/%{env:MATCH_DATASET}/
ProxyPassReverse /
</LocationMatch>
On the other hand, this page and that posting imply that the numerical group index ($1) can be used (as the help text is valid only as of httpd 2.4.8, my suspicion / hope is that the numerical reference works before 2.4.8 (?)
In any case, I have tried this:
<LocationMatch "/(experimental)/">
ProxyPassMatch http://localhost:3030/$1/
ProxyPassReverse /
</LocationMatch>
yet according to the logs, the internal call invokes http://localhost:3030/$1/ instead of http://localhost:3030/experimental/ when requesting the experimental path on the vhost URL.
The ProxyPassMatch docs only say:
When used inside a LocationMatch section, the first argument is omitted and the regexp is obtained from the LocationMatch.
However, the text does not bother to provide an example for how to combine LocationMatch and ProxyPassMatch. What am I doing wrong?
The doc also states When the URL parameter doesn't use any backreferences into the regular expression, the original URL will be appended to the URL parameter., which seems to be your case.
Further more, you are missing the host in your ProxyPassReverse directive.
This should work just fine:
<LocationMatch "^/experimental/.*$">
ProxyPassMatch http://localhost:3030
ProxyPassReverse http://localhost:3030
</LocationMatch>
Got this working on Apache 2.4.29:
<LocationMatch "/fruit/(?:apple|banana|pear)">
ProxyPass http://localhost:8080
ProxyPassReverse http://localhost:8080
</LocationMatch>
The URL called by Apache is for example
http://localhost:8080/fruit/apple
The (?: is crucial when you are using parentheses in this example.

How to use environment variable from mod_rewrite for interpolate proxypass in httpd.conf

I'm using apache 2.4 and trying to use environment variable inside conf file for proxy pass. There's a thread [Apache proxypass using a variable URL with interpolate ]talking about this:
RewriteEngine on
RewriteMap lowercase int:tolower
#This sets the variable to env:
RewriteRule ^ - [E=SERVER_NAME:${lowercase:%{SERVER_NAME}}]
#Now interpolate makes variables available for proxypass & proxypassreverse:
ProxyPassInterpolateEnv On
ProxyPass / ajp://${SERVER_NAME}:8009/ interpolate
ProxyPassReverse / ajp://${SERVER_NAME}:8009/ interpolate
But when I tried this myself, I get a "AH00111: Config variable ${SERVER_NAME} is not defined" error. Which means Apache2.4 treats the ${SERVER_NAME} as config variable, rather than environment variable.
I also tried using the mod_rewrite sytax for the variable, like this,
ProxyPass / ajp://%{ENV:SERVER_NAME}:8009/ interpolate
ProxyPassReverse / ajp://%{ENV:SERVER_NAME}:8009/ interpolate
But %{ENV:SERVER_NAME} was treated as plaintext string, and created an error since it's not a valid URL pass.
Config variables are defined with "Define" block at server launch. What I want is to have the SERVER_NAME changing at runtime using mod_rewrite.
I can't use the mod_rewrite [P] argument, since I need to have the ProxyPassReverse block working with variable as well. mod_rewrite can't deal with rewriting the response, and therefore can't mimic the function of ProxyPassReverse.
Any ideas on how to use environment variable in interpolate proxypass conf directives?
It turns out Apache will still load and work fine, even with the warnings, using this syntax:
ProxyPassReverse / ajp://${SERVER_NAME}:8009/ interpolate
This issue was identified in this mailing list thread. The discussion is about another issue, but they mention this problem and discuss the idea of adding a second interpolation syntax to ProxyPass, etc. However, I have not found a bug report, and it seems as of Apache 2.4.10, the mod_proxy code still supports only the ${varname} syntax, which conflicts with the overall httpd.conf interpolation.
I haven't found a way to disable those specific warnings, but if you are willing to live with the warnings, Apache should still work for you.
One caveat is that if there is a system environment variable present with the same name when Apache is loading, it will overwrite the value you are trying to interpolate at runtime.