Apache mod_headers modification not passing through on ProxyPass - apache

I have web socket GET requests that are coming to an Apache http sever and are being forwarded to a Apache Tomcat 8.5.x server (represented here as 192.168.1.77:80).
I'm attempting to use mod_headers to set the "upgrade" header value.
Inside my VirtualHost tag, I have the equivalent to the following:
<LocationMatch "/somewhere">
ProxyPass ws://192.168.1.77:80/socket
RequestHeader set Upgrade "myvalue"
</LocationMatch>
This does not work as I would expect it to. The set seems to be applying to Apache http but not Apache Tomcat.
In Apache http, when I add %{Upgrade}i to my LogFormat, I see the "Upgrade" header is set to "myvalue".
However, in the Tomcat logs, if I add *%{Upgrade}i", I see that my RequestHeader set operation did not take effect, and Tomcat records the original value for the "Upgrade" header in the original GET request.
Note: I have already tried adding the "early" argument like so:
<LocationMatch "/somewhere">
ProxyPass ws://192.168.1.77:80
RequestHeader set Upgrade "myvalue" early
</LocationMatch>
Any thoughts as to what is going wrong or what I might be missing?

I'm using mod_proxy_wstunnel, and apparently the upgrade header "WebSocket" is hard-coded in that module.

Related

Fixing multiple broken headers in Apache 2.4

I'm using Apache 2.4.52 and I have two headers I'd like to fix in my apache config. The problem is only one RequestHeader works at a time.
I can only get 'SOME-TOKEN' RequestHeader working if I comment out or remove SOME-API-KEY from the config.
Note: this problem happens using either method from the code below. Only the SOME_API_KEY header works, in order for SOME-TOKEN header to work, I have to remove the other RequestHeader.
RequestHeader set SOME-API-KEY "expr=%{req:SOME_API_KEY}"
RequestHeader set SOME-TOKEN "expr=%{req:SOME_TOKEN}"
I've also tried this - from here: https://httpd.apache.org/docs/2.4/env.html#examples
The same problem exists, only the SOME-API-KEY RequestHeader works. Again, if I remove SOME-API-KEY RequestHeader, SOME-TOKEN header will begin working as expected.
SetEnvIf ^SOME.API.KEY$ ^(.*)$ fix_some_api_key=$1
RequestHeader set SOME-API-KEY %{fix_some_api_key}e env=fix_some_api_key
SetEnvIf ^SOME.TOKEN$ ^(.*)$ fix_some_token=$1
RequestHeader set SOME-TOKEN %{fix_some_token}e env=fix_some_token
Additional info: This api is a separate vhost using mod_wsgi, I do have WSGIPassAuthorization ON set. I've tried using one RequestHeader in the main apache config, one in the vhost config and both in the virtualhost config to no avail.

Apache LocationMatch matching urls starting with...

I'm using apache to redirect AJAX request to server backend in my AJAX app.
Everything that starts with /service/ should go to service backend:
<LocationMatch "/service">
ProxyPass http://backend:8080/service Keepalive=On
Header set Cache-Control "no-cache, no-store, must-revalidate"
</LocationMatch>
Everything that starts with /auth goes to authentication server:
<LocationMatch "/auth">
ProxyPass http://keycloak:8090/auth/ Keepalive=On
</LocationMatch>
I was happy with my apparently working solution, unless the auth channel was added to backend, and them I've noticed, that requests to /service/auth/info are not consumed by backend, but land in authentication server.
Apparently I have some understanding problem. How should I match URLs that start with given string, and not contain it somewhere in the middle?
Use the caret (^) to indicate the beginning of the string:
<LocationMatch "^/service">

Apache 2.4.25 some headers being stripped in proxied request

I am proxying requests from server A (Apache 2.4) to server B (Apache 2.2) as following:
RequestHeader set X_REMOTE_USER %{REMOTE_USER}s
ProxyPass / https://www.server_b.com/
ProxyPassReverse / https://www.server_b.com/
When I print the environment variables on server B, I see HTTP_X_REMOTE_USER. However, when I do the same proxying to server C (Apache 2.4), apache doesn't set an environment variable with that name.
It appears that going from 2.2 to 2.4 some of the environment variables set from request headers are no longer being set. Is this correct? If so, how do I make 2.4 work like 2.2?
You can use SetEnvIf to set an environment variable based on a request header. For example:
SetEnvIf X_REMOTE_USER "^(.*)$" HTTP_X_REMOTE_USER=$1

virtual host not working when cloudflare is enabled

Before cloudflare, I was able to access the phpMyAdmin link such as
example.com/ctrl/pmasetup
After CloudFlare, I get a 403 (coming from my own apache server, not CloudFlare's error page)
Forbidden
You don't have permission to access /ctrl/pmasetup on this server.
I feel like I need to add the CloudFlare's reverse proxy somewhere on the server, which I did in /etc/hosts which now looks like:
127.0.0.1 localhost localhost.localdomain
104.25.68.32 example.com <- This is the ip of my site when CloudFlare is enabled on it
I also added it in httpd.conf in the virtual host config:
<VirtualHost *:80>
ServerAdmin support#example.com
DocumentRoot /var/www/example.com
ServerName example.com
ErrorLog logs/example.com-error_log
CustomLog logs/example.com-access_log combinedio
Alias /ctrl /var/www/ctrl
<Location /ctrl>
<RequireAny>
Require all denied
Require ip {my ip}
Require ip 104.25.68.32 <- CloudFlare IP, again
</RequireAny>
</Location>
#Header always set Access-Control-Allow-Origin "http://example.com"
Header always set Access-Control-Allow-Origin "*"
Header always set Access-Control-Allow-Methods "POST, GET, OPTIONS"
Header always set Access-Control-Max-Age "1000"
Header always set Access-Control-Allow-Headers "*"
RewriteEngine On
RewriteCond %{REQUEST_METHOD} OPTIONS
RewriteRule ^(.*)$ $1 [R=200,L]
</VirtualHost>
Edit: Even when commenting the entire RequireAny block, I still get a 403 when CloudFlare is enabled.
Edit 2: if inside the location tag I ONLY have Require all granted, then it works. So, how can I disallow everybody BUT the few IP's I put initially?
Edit 3: It most likely is because CloudFlare changes your IP as a visitor, then my apache config doesn't recognize it. Any idea?
EDITED -- See below;
I believe you should allow cloudflare's ip ranges to access the site. After all, the request comes from cloudflare not the client.
CloudFlare's ip ranges can be found on their website at:
https://www.cloudflare.com/ips/
They also provide an easy "text/plain" format following both theses urls:
CloudFlare IPv4 Ranges & CloudFlare IPv6 Ranges
There's also a little tool i know of, for nginx tho, available at:
https://www.8ball.me/nginx/ngx-cfips.zip
EDIT -- I've created a new version since this post. Today actually (2017.05.31). The url is still valid. It's got a --help function detailing how to setup as a cronjob and include into nginx. Same CloudFlare urls are used.
When there is an option denying I believe you need to use RequireAll instead of RequireAny (since RequireAny is the default behaviour in 2.4 so there is no need to specify it like you do). Try it.

Debug Environment Variables in Apache VirtualHost

I'm using ProxyPass while attempting to set a request header in my vhost w/:
<VirtualHost *:443>
...
RequestHeader set X-REMOTE-USER "%{REMOTE_USER}s"
ProxyPass / http://127.0.0.1:9292/
ProxyPassReverse / http://127.0.0.1:9292/
...
</VirtualHost>
However when inspecting the headers that are getting sent to my application running on port 9292 I see:
"HTTP_X_REMOTE_USER"=>"(null)"
Does this mean that REMOTE_USER is not set or am I using RequestHeader incorrectly? Is there a way to debug what environment variables I have available to me within the vhost?
The problem is that, those variables are available for mod_rewrite but not to mod_headers.
Here you can found a complete answer to a similar problem:
REMOTE_USER through Apache reverse proxy
To get a list of all available enviroment variables you can use printenv command in the server, or browse this list of common enviroment variables.