nginx allow|deny $realip_remote_addr

4.2k views Asked by At

Using nginx you can allow and deny ranges and ips (https://www.nginx.com/resources/admin-guide/restricting-access/). Using the realip module, you can change the ip it uses to the real IP after cloudflare. (http://nginx.org/en/docs/http/ngx_http_realip_module.html)

Now here's the thing, I want to blacklist any ip that isn't Cloudflare or localhost. This is proving rather difficult, I've tried putting it before setting the real_ip module setup, and no cigar.

Is this possible at all? It seems like a flaw if the user isn't going through cloudflare, it allows for a lot more abuse towards a certain vhost.

There is the $realip_remote_addr variable, but I can't for the life of me find a way to make the allow/deny use that instead of the normal $remote_addr.

Edit: It's been brought to my attention a firewall can assist in this. Unfortunately I really only need this for a few vhosts.

3

There are 3 answers

0
Gaëtan Duchaussois On BEST ANSWER

You can do it easily with a geo block

geo $realip_remote_addr $giveaccess {
      default 0;
      IPBLOCK1 1;
      IPBLOCK2 1;
      …
    }
    server {
       …
       location / {
         if ($giveaccess = 0){
          return 403 "$realip_remote_addr";
          #use it for debug
        }
    }
0
Cory Ory On

Such simplicity allows for great things.

It's smarter to use $realip_remote_addr == $remote_addr because $http_* can be falsified by the client sending such requests. (Pointed out to me by a friend).

EDIT: Okay so the point above taken into account, it's best to use the Lua module for this.

Something similar to below.

access_by_lua_block {
    if ngx.var.remote_addr == ngx.var.realip_remote_addr then
            return ngx.redirect("http://somewhere.else.please/");
    end
}
4
Satys On

I think that you want to block the direct access of your machine, i.e., through ip of your machine.

You can use http header set by cloudflare for this. Whenever there is a request through cloudflare, it sets $http_cf_connecting_ip to the ip of the machine accessing your machine.

So you can write a condition, to deny all requests that have an empty $http_cf_connecting_ip.