Converting string IP address to binary address

What I’m trying to do:

I have previously successfully implemented Rate limiting in an NGINX reverse proxy - excerpt:

geo $limit {
    default  0;       # Unknown users

    123.456.78.999  1;    # Known user IP
    ...
}

map $limit $unknown_user {
    0 $binary_remote_addr;
    1  "";
}

map $limit $known_user {
    0 "";
    1  $binary_remote_addr;
}

I have now had a Web Application Firewall (WAF) inserted in front of NGINX, the user’s IP addresses are now stored in $http_x_forwarded_for variable.

Accordingly I must change the config to use that variable as follows:

geo  $http_x_forwarded_for  $limit {
    default  0;       # Unknown users

    123.456.78.999  1;    # Known user IP
    ...
}
map $limit $unknown_user {
    0 $http_x_forwarded_for;
    1  "";
}

map $limit $known_user {
    0 "";
    1  $http_x_forwarded_for;
}

Where I’m stuck:
The original value $binary_remote_addr is, obviously BINARY - and is always 4 bytes for IPv4 addresses - which is good for performance reasons.

However, $http_x_forwarded_for is STRING version - so occupies many more bytes.

I’d like to convert $http_x_forwarded_for to its binary equivalent - e.g. $binary_x_forwarded_for.

Does anyone know if such a String → Binary conversion can be easily done; and can provide sample code for insertion into the virtual host config file in sites-enabled?

What I’ve already tried:
I’ve Googled & looked through NGINX documentation… but found nothing.

As always I am not an NGINX Guru.

The best way to handle X-Forwarded-For, and get a “binary-like” IP, is to use the ngx_http_realip_module. This module is designed for this.

Here’s the doc: Module ngx_http_realip_module

I tried to build a sample configuration:

http {
    # Define your WAF's IP address or subnet as a trusted proxy
    # Replace with your actual WAF IP/subnet
    set_real_ip_from   192.168.1.0/24; # Example: your WAF's subnet
    set_real_ip_from   10.0.0.0/8;     # Example: another trusted proxy range

    # Specify the header containing the real client IP
    real_ip_header     X-Forwarded-For;

    # If your WAF or other proxies add multiple IPs to X-Forwarded-For,
    # and the leftmost is the client, use real_ip_recursive on;
    # This will strip trusted IPs from the right until it finds a non-trusted one.
    real_ip_recursive  on; 

    # Now, $remote_addr and $binary_remote_addr will contain the actual client IP
    # from X-Forwarded-For, provided the request came from a trusted proxy.

    geo $limit {
        default  0;       # Unknown users

        # These IPs will now be matched against the *real* client IP
        123.456.78.999  1;    # Known user IP
        ...
    }

    map $limit $unknown_user {
        0 $binary_remote_addr; # Uses the "real" client IP in binary
        1  "";
    }

    map $limit $known_user {
        0 "";
        1  $binary_remote_addr; # Uses the "real" client IP in binary
    }

    # ... your other NGINX configuration ...
}

Let us know how it goes

davemc

1 Like