Among other features provided by Cloudflare, it can add a special header with a country value, from where a visitor came.
As a Ukrainian, I’d like to ban all visitors from russia, but:
- redirect all visitors from russian IPs to another web domain – russki-voenny-korabl-idi-nahuy.com
- during this, I’d like to filter requests and leave requests from the Yandex search system unimpacted, so it will proceed to return RTFM blog in its search results for Russian auditory.
Contents
Cloudflare IP Geolocation and NGINX
The simplest part here is to configure the filter by the header from Cloudflare.
At first, enable the CF-IPCountry header.
Go to your Cloudflare Dashboard > Network, activate the option, it’s free even in its basic plan:
Then, in your virtualhost config for NGINX, in the server {}
block use the proxy_set_header
to create a variable $http_cf_ipcountry
:
... proxy_set_header CF-IPCountry $http_cf_ipcountry; ...
NGINX and “nested” if
And the second part is more interesting.
So, we need to check two conditions:
- is a visitor from russia
- is it a common visitor, or a Yandex search bot?
In NGINX we can not use really nested conditions with if
, e.g:
... if ($country_allowed = no) { if ($http_user_agent !~* (YandexBot) ) { rewrite ^ https://russki-voenny-korabl-idi-nahuy.com break; } } ...
But what we can do here, is to use variables and dedicated if
.
Let’s check.
Enable a VPN, and check where are you now, for example using the https://www.iplocation.net service:
GB – Great Britain.
In the nginx.conf
you can also enable an extended log format for access_log
to see more information, and check the values of the $http_cf_ipcountry
and a new variable $visitor
that we will add below:
... log_format main_ext '$time_local client: $remote_addr fwd_for: $http_x_forwarded_for ' 'status: $status user_agent: "$http_user_agent" ' 'server: "$server_name" country: $http_cf_ipcountry visitor: $visitor'; ...
Next, create conditions and run tests. After tests will be successful, we will change conditions to region RU and “if not equal” Yandex (see Yandex robots in server logs).
So:
- create a variable called
$http_cf_ipcountry
from theCF-IPCountry
header; - in the first
if
condition check the value of the$http_cf_ipcountry
: for now, check for the GB and create a variable$visitor
that will keep a value rus, if the region was == CA; - in the second
if
condition check theUser-Agent
, and if it’s == Firefox then add another value to the$visitor
variable – “redirect; - in the third
if
condition check the value of the$visitor
variable, and if it is equal to the rusredirect string, then make arewrite
to the russki-voenny-korabl-idi-nahuy.com domain;
Also, you can set the rewrite_log
parameter to on, and set the error_log
to the notice level, so you’ll be able to check if rewrites are working as expected.
This is how my config looked during the tests:
... rewrite_log on; access_log /var/log/nginx/rtfm.co.ua-access-ext.log main_ext; error_log /var/log/nginx/rtfm.co.ua-error.log notice; ... proxy_set_header CF-IPCountry $http_cf_ipcountry; if ($http_cf_ipcountry = GB) { set $visitor rus; } if ($http_user_agent ~* (Firefox) ) { set $visitor "${visitor}redirect"; } if ($visitor = "rusredirect") { rewrite ^ https://russki-voenny-korabl-idi-nahuy.com break; } ...
Check the config file and reload nginx
:
[simterm]
root@rtfm-do-production-d10:~# nginx -t nginx: the configuration file /etc/nginx/nginx.conf syntax is ok nginx: configuration file /etc/nginx/nginx.conf test is successful root@rtfm-do-production-d10:~# systemctl reload nginx
[/simterm]
Go to the blog with the Firefox browser:
access_log:
[simterm]
root@rtfm-do-production-d10:~# tail -f /var/log/nginx/rtfm.co.ua-access-ext.log | grep GB 02/Apr/2022:06:22:29 +0000 client: 162.158.91.190 fwd_for: 146.70.46.20,146.70.46.20 status: 302 user_agent: "Mozilla/5.0 (X11; Linux x86_64; rv:98.0) Gecko/20100101 Firefox/98.0" server: "rtfm.co.ua" country: GB visitor: rusredirect
[/simterm]
error_log:
[simterm]
root@rtfm-do-production-d10:~# tail -f /var/log/nginx/rtfm.co.ua-error.log | grep 'rewritten redirect' 2022/04/02 06:22:29 [notice] 21018#21018: *33766595 rewritten redirect: "https://russki-voenny-korabl-idi-nahuy.com", client: 162.158.91.190, server: rtfm.co.ua, request: "GET / HTTP/1.1", host: "rtfm.co.ua"
[/simterm]
Got a visitor from the country: GB
with the user_agent: "Firefox"
, and got a redirect: "https://russki-voenny-korabl-idi-nahuy.com"
– “It works!” (c).
Now, change the conditions to the final version with the RU region and Yandex for User-Agent
:
- set the region:
if ($http_cf_ipcountry = RU)
- and change the
~* (Firefox)
to the not-equal, i.e.!~* (Yandex)
–if ($http_user_agent !~* (Yandex) )
:
... proxy_set_header CF-IPCountry $http_cf_ipcountry; if ($http_cf_ipcountry = RU) { set $visitor rus; } if ($http_user_agent !~* (Yandex) ) { set $visitor "${visitor}redirect"; } if ($visitor = "rusredirect") { rewrite_log on; rewrite ^ https://russki-voenny-korabl-idi-nahuy.com break; } ...
Done.