NGINX TCP Load Balancing "if" directive is NOT allowed here

by Ocean Airdrop   Last Updated December 07, 2017 10:00 AM

I am hoping someone can help me with the following. I am trying to setup a reverse proxy for load balancing using nginx over tcp/udp.

I want to be able to redirect some traffic based the client ip address that is connecting up to the proxy server. For this I am using the built-in nginx variable $remote_addr.

The version of nginx I am using is: nginx/1.10.3 (Ubuntu).

The error message I am getting is: nginx: [emerg] "if" directive is not allowed here

This is my config file looks like this:

user www-data;
worker_processes auto;
pid /run/nginx/pid

events {
    worker_connections 768;
}

stream {
    upstream prod_backend {
        server 192.168.137.129:23;
    }
    upstream test_backend {
        server 192.168.137.131:23;
    }

    server {
        listen 23;

        if ( $remote_addr = 192.168.137.132 ) {
            proxy_pass test_backend;
        }

        proxy_pass prod_backend;
    }
}

http {
}

After seeing this answer here, I have tried using the Geo module but get the same problem.

user www-data;
worker_processes auto;
pid /run/nginx/pid

events {
    worker_connections 768;
}

stream {
    upstream prod_backend {
        server 192.168.137.129:23;
    }
    upstream test_backend {
        server 192.168.137.131:23;
    }

    geo $test_site {
        default 0;
        192.168.137.132 1;
    }

    server {
        listen 23;

        if ( $test_site ) {
            proxy_pass test_backend;
        }

        proxy_pass prod_backend;
    }
}

http {
}

when I run the above version I get the error:

nginx: [emerg] "geo" directive is not allowed here

I am obviously doing something wrong but don't know what!



Answers 1


As user @Alex_hha pointed out, the "if" directive can only be used within the http directive.

After some research around this area I have now found a solution to the problem.

If you are using the stream directive for generic TCP/UDP traffic an alternative to the if statement is to use the map function.

Using this method my config file now looks like this:

stream {
   upstream prod_backend {
      server 192.168.137.129:23;
   }

   upstream test_backend {
      server 192.168.137.131:23;
   }

   map $remote_addr $backend_svr {
      192.168.137.140:23 "test_backend";
      default "prod_backend";
   }

   server {
      listen 23;
      proxy pass $backend_svr;
   }
}

In this example, if a client connects with the IP address of 192.168.137.140 it will get sent to the test_backend upstream block.

The version of nginx I am using is: nginx/1.12.1 (Ubuntu).

Ocean Airdrop
Ocean Airdrop
December 09, 2017 10:00 AM

Related Questions



Nginx round-robin nor exactly round-robin

Updated February 01, 2018 05:00 AM

Nginx direct to mirror server if online

Updated December 07, 2017 08:00 AM