Matt
Matt

Reputation: 175

Whitelisting one IP while blocking multiple countries with nginx?

I'm trying to restrict traffic to only a handful of countries, but I also want to whitelist a single IP address. Here's my conf file:

    # restrict access by country
    geoip_country /usr/share/GeoIP/GeoIP.dat;
    map $geoip_country_code $allow_visit {
        default no;
        US Yes;
        GB Yes;
        IL Yes;
        CA Yes;
    }

    ##
    # Virtual Host Configs
    ##

    server { # simple reverse-proxy

        listen       80;
        server_name  xXmySiteXx;

        root /usr/share/nginx/html;
#       root /var/www/html;
        index index.php index.html index.htm;   

            if ($scheme != "https") {
                return 301 https://$host$request_uri;
            } # managed by Certbot

    # reject unauthorized countries
    if ($allow_visit = no) {
        return 403;
    }

I've tried adding the following:

if($remote_addr = ipInQuestion) {
    set $allow_visit = yes;
}

But when I try to reload nginx, it fails. Any ideas what I'm doing wrong or the better way to do this?

EDIT:

The error I get from nginx is:

nginx: [emerg] unknown directive "if($remote_addr"

Upvotes: 0

Views: 861

Answers (2)

jpevarnek
jpevarnek

Reputation: 381

You figured out the issue with that if, but you still could end up running into problems from the set statement being within an if.

In order to get rid of the set within the if, your best option is to make another map:

map $remote_addr $real_allow_visit {
    default $allow_visit;
    ipInQuestion no;
}

Upvotes: 1

Matt
Matt

Reputation: 175

I know it's bad practice, but I was able to get the variable to set using the if method... I had to tweak the second portion of my code to:

if ($remote_addr = ipInQuestion) {
    set $allow_visit yes;
}

Specifically I needed to add the space between if and ( and delete the = from the set statement. After doing these things, nginx passed tests and would reload.

Upvotes: 0

Related Questions