I have an interesting problem. My company is hosting a small application server for a client, and they want to restrict access to only a few IPs. The client is a large company with many divisions, and each division has their own networking structure.
I won't go into the details, but because of my company's internal structure for web servers, we can't use the conventional allow,deny syntax in Apache. We have load balancers which forward to web servers which then forward to the application server itself. Instead, we use something like the following in our Apache configurations:
RewriteCond %{HTTP:X-Forwarded-For} !^213.212.45.54
We make use of the X-Forwarded-For header to match external IPs. The problem is that one of our client's divisions (call it division A) has their Internet setup to go through an internal proxy. Their internal proxy forwards the workstation IP of each user to our web server. This means that the X-Forwarded-For header for those users looks something like this:
10.123.16.23, 213.212.45.54, 172.20.162.2
The 10 address is the workstation IP of each user in their network, the 213 is the WAN IP of that division, and the 172 is my company's load balancer.
My company has confirmed that if we add the workstation IP of a user to the Apache configuration, they are able to access the page without problem. However, to add every single IP would be tedious.
Is there a way to tell Apache to only pay attention to the middle IP (the WAN IP) using regular expressions? Or is there a better way to configure Apache?
I haven't tested this, but you could construct a regex that searches for your IP string anywhere in the field. The first ^ in your regex means it must match the beginning of the string, which is not the case here.
Something as simple as this could work:
RewriteCond %{HTTP:X-Forwarded-For} !213\.212\.45\.54
The backslashes are necessary in front of the dots because otherwise the . matches any numer of any characters, including matching nothing, it's the equivalent of a * in wildcard syntax.
Like this, if the string 213.212.45.54 is found anywhere in the X-Forwarded-For header, the regex will match.
Related
I have a bit problem with my site.
So setup is ElasticBeanstalk(NGINX) + Cloudflare
But each day around 4AM I have direct IP attack to my server.
Around 300 requests in 1-2 minutes.
Bot try to access some resources like
GET /phpMyadmi/index.php HTTP/1.1
GET /shaAdmin/index.php HTTP/1.1
POST /htfr.php HTTP/1.1
For now all of them going to 80 or 8080 ports.
And successfully handled by Nginx configuration that redirect it to example:443
server {
listen 80 default_server;
listen 8080 default_server;
server_name _;
return 301 https://example.com$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
ssl on;
...
So questions are,
have many site owners/devOps face the same attack. What is your action to prevent such attacks.
For now it is handled very well and did not affect on server work, should I worry about it? Or just filter out logs with /phpmy/ pattern and forgot about it.
Before this attacks I have request with method PROPFIND, should I blocked it for security reasons? It is handled by default server for now.
I know that I can use Cloudflare Argotunel or ELB + WAF. But I am not really want to do it for now.
I have found one solution on stackoverflow. Is whitelist of all cloudflare ips. But i think it is not a good one.
Also another solution that should work I guess it is to check Host header, and compare it with 'example.com'.
To answer your specific questions:
Every public IP receives unwanted traffic like you describe, sadly its pretty normal. This isnt really an attack as such, its just a bot looking for signs of specific weaknesses, or otherwise trying to provoke a response that contains useful data. This data is no doubt later used in actual attacks, but its basically automated recognisance on a potentially massive scale.
This kind of script likely isnt trying to do any damage, so as long your server is well configured & fully patched its not a big concern. However these kinds of scans are first step towards launching an attack - by identifying services & application versions with known vulnerabilities - so its wise to keep your logs for analysis.
You should follow the principle of least privilege. PROPFIND is related to WebDAV - if you dont use it, disable it (or better white list the verbs you do support and ignore the rest).
If your site is already behind CloudFlare then you really should firewall access to your IP so only Cloudflares IPs can talk to your server. Those IPs do change, so I would suggest a script to download the latest from https://www.cloudflare.com/ips-v4 and have it periodically update your firewall. Theres a slightly vuage help article from CloudFlare on the subject here: https://support.cloudflare.com/hc/en-us/articles/200169166-How-do-I-whitelist-Cloudflare-s-IP-addresses-in-iptables-
If for whatever reason you cant firewall the IP, your next best option is something like fail2ban (www.fail2ban.org) - its a log parser that can manipulate the firewall to temporarily or permanently block an IP address based on patterns found in your log files.
A final thought - id advise against redirecting from your IP to your domain name - your telling the bot/hackers your URL - which they can then use to bypass the CDN and attack your server directly. Unless you have some reason to allow HTTP/HTTPS traffic to your IP address, return a 4XX (maybe 444 a " Connection Closed Without Response") instead of redirecting when requests hit your IP. You should then create a separate server block to handle your redirects, but only have it respond to genuine named URLs.
We configured a load balanced URL that will direct the request from "sasstudiodev.org.com" to "http://abcd.org.com:7980/SASStudio" . Note that abcd and sasstudiodev do not have same ip address and sasstudiodev is a load balanced URL. Now we would like to ensure that the host name (i.e. abcd) is not visible to end users. Hence when a user types "sasstudiodev.org.com", SAS should connect to the available mid-tier node based on LB algorithm but the URL displayed in the address bar should NEVER expose the host name, ie. it should still show sasstudiodev.org.com/~/~
Is this possible using httpd or URL rewrite rules?
Yes, it is possible. In fact, you already have a load balancer/reverse proxy set up using Apache by default. To see it working, replace port 7980 to 8080. It is a default set up even when you have a single application server.
You need to change the settings for your virtual host and setup redirect, and should be ready to go.
I'm trying to get a Django application running on my shared web server (hosted with DreamHost). There's one interface I'd like to lock down based on a white-list of IP addresses, but I'm having trouble figuring out how to do it. This interface lives at a virtual URL (in other words, there are no physical files on the server that correspond to the URL; the Django internals serve up the right thing based on the URL passed in). My shared host uses Apache as the web server, which then passes all necessary requests to Passenger.
I currently have an .htaccess file with the following contents in the root of my site:
SetEnvIf Request_URI ^/manage require_auth=true
AuthUserFile /home/myuser/.htpasswd
AuthName "Who Goes There?"
AuthType Basic
order deny,allow
deny from all
Satisfy any
Require user my_web_user
Allow from env=!require_auth
When I visit the /manage URL at my site, I get prompted for credentials just like I would expect. Visiting any other URL doesn't prompt me, so this rule set seems to work.
However, I can't figure out how to add the IP address white list into the mix. I'm aware that the Satisfy any directive is essentially a logical OR of the statements below it. Ideally, I'd like to be able to restrict access to this URL based on IP and require the user to login. But only for that particular path.
Is there something simple I'm missing here, or could the Apache / Passenger setup prevent me from being able to have my cake and eat it too?
You could specify the ranges you allow with "Allow from iprange" CIDR notation works fine, so that all those which do not match will be required to authenticate.
For example:
AuthUserFile /home/myuser/.htpasswd
AuthName "Who Goes There?"
AuthType Basic
Order deny,allow
Allow from 192.168.0.0/16
Satisfy any
Require user my_web_user
This means that all not in range 192.168.0.0 will have to authenticate.
Basically, I have a couple of services. I want to forward every requests with prefix "/secured" to server1 port 80 and all other requests to server 2 port 80. The problem is that on server1, I am running service which accept the request without "/secured" prefix. In other words, I want to forward every requests such as "http://example.com/secured/api/getUser" to server1 as "http://example.com/api/getUser" (remove /secured from request' path).
With AWS ALB, currently the request is sent as http://example.com/secured/api/getUser; which forces me to update my server1's code so that the code handles requests with /secured prefix which doesn't look good.
Is there any easy way to solve this with ALB?
Thanks.
I can confirm that this is unfortunately not possible with the ALB alone - and I agree it really should be.
AWS states:
Note that the path pattern is used to route requests but does not
alter them. For example, if a rule has a path pattern of /img/*, the
rule would forward a request for /img/picture.jpg to the specified
target group as a request for /img/picture.jpg.
I had the same issue, and as Mark pointed out, you can use reverse proxy on your server and do something like this (this is Nginx configuration):
server {
listen 80 default_server;
location /secured/ {
proxy_pass http://localhost:{service_port}/;
}
}
This will strip the /secured part and proxy everything else to your service. Just be sure to have the trailing / after the service port.
I am curious if anyone knows, is it possible to build a varnish config which
looks at inbound headers from clients
and does regexp match, to build a certain header - that is passed on to backed web server?
Context:
-- Varnish server deployed in front of 3-(apache)-webserver pool, acting as cache and LB
-- 3rd party service DDOS proxy was dropped in front of varnish recently
-- now all inbound requests to varnish have an X-Forwarded-For: header already present, indicating what the 'real' client IP address is.
-- the back-end PHP web app running on the apache hosts - wants to see only one IP address, not a 'proper' X-F-F header which shows a comma-delimited list IP1, IP2, IP3 (for external proxy; varnish as proxy, original client IP - for example)
-- ideally what I would like to do: is get Varnish to do regexp pattern match:rebuild on the existing inbound X-F-F headers; and strip away the external DDOS proxy IP address
I had tried something like this in the 'default.vcl' file,
set req.http.X-Forwarded-For = regsub(req.http.X-Forwarded-For, "123.123.123.123"," ");
where 123.123.123.123 is the IP address of the external DDOS / proxy
but this most certainly is not working / is not the correct syntax. I'm having trouble finding good resources online that explain regexp in varnish / or good clear examples that people use.
If anyone can provide a kick in the right direction, certainly it would be greatly appreciated.
Thanks for comment below - I have adjusted my config now as follows,
if (req.http.x-forwarded-for) {
set req.http.X-Forwarded-For =
regsub(req.http.X-Forwarded-For, "\, 123\.123\.123\.123","");
} else {
set req.http.X-Forwarded-For = client.ip;
}
and now I find in my apache logs, for example,
client.ip.real.here, 123.123.123.123 - - [22/Dec/2013:07:45:17 -0800] "GET /PATH/TO/STUFF" "Mozilla/5.0.... like Gecko"
which suggests to me the regexp is not actually doing what I thought I wanted. Is there any way to 'test' varnish interactively, ie, feed a given VCL rule set some defined input, and then get varnish to feed out specific output; kind of a 'dry run' processing as a way to facilitate debug ?
Thanks!