NGINX: IP Geolocation by Cloudflare and “nested” if conditions
Tags: todayilearned, tutorial
Published: 2022-06-12 05:20:05

---
title: NGINX: IP Geolocation by Cloudflare and “nested” if conditions
published: true
date: 2022-04-02 08:38:44 UTC
tags: todayilearned,tutorial
canonical_url: https://rtfm.co.ua/en/nginx-ip-geolocation-by-cloudflare-and-nested-if-conditions/
---

![](https://cdn-images-1.medium.com/max/130/0*pft2fOozAuSSuwqB.jpg)

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:

1. redirect all visitors from Russian IPs to another web domain — _russki-voenny-korabl-idi-nahuy.com_
2. during this, I’d like to filter requests and leave requests from the russian Yandex search system unimpacted, so it will proceed to return my RTFM blog in its search results for russian auditory.

### 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](https://support.cloudflare.com/hc/en-us/articles/200168236-Configuring-Cloudflare-IP-Geolocation) header.

Go to your Cloudflare _Dashboard > Network_, activate the option, it’s free even in its basic plan:

![](https://cdn-images-1.medium.com/max/1024/0*sLXxNDx5YPN4gOBp.png)

Then, in your virtualhost config for NGINX, in the server `{}` block use the [`proxy_set_header`](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#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:

1. is a visitor from russia
2. 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](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](https://www.iplocation.net) service:

![](https://cdn-images-1.medium.com/max/586/0*HRMohuQOz4eB_d_M.png)

_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](https://yandex.com/support/webmaster/robot-workings/check-yandex-robots.html)).

So:

1. create a variable called `$http_cf_ipcountry` from the `CF-IPCountry` header;
2. in the first ifcondition 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_;
3. in the second if condition check the `User-Agent`, and if it's == _Firefox_ then add another value to the `$visitor` variable - "_redirect_;
4. in the third `if` condition checks the value of the `$visitor` variable, and if it is equal to the _rusredirect_ string, then make a rewrite to the _russki-voenny-korabl-idi-nahuy.com_ domain;

Also, you can set the [`rewrite_log`](http://nginx.org/en/docs/http/ngx_http_rewrite_module.html#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](https://russki-voenny-korabl-idi-nahuy.com) break;
    }
...
```

Check the config file and reload `nginx`:

```
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
```

Go to the blog with the Firefox browser:

![](https://cdn-images-1.medium.com/max/451/0*9qir3Louk9azquDi.png)

access_log:

```
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
```

error_log:

```
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”
```

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](https://russki-voenny-korabl-idi-nahuy.com) break;
    }
...
```

Done.

_Originally published at_ [_RTFM: Linux, DevOps, and system administration_](https://rtfm.co.ua/en/nginx-ip-geolocation-by-cloudflare-and-nested-if-conditions/)_._

* * *