nginx rate limiting with X-Forwarded-For header

Solution 1:

Yes, typical rate-limiting configuration definition string looks like:

 limit_req_zone  $binary_remote_addr zone=zone:16m rate=1r/s;

where $binary_remote_addr is the unique key for limiter. You should try changing it to $http_x_forwarded_for variable which gets the value of X-Forwarded-For header. Although this will increase memory consumption because $binary_remote_addr is using compressed binary format for storing IP addresses and $http_x_forwarded_for is not.

 limit_req_zone  $http_x_forwarded_for zone=zone:16m rate=1r/s;

Solution 2:

The limit_req_zone directive defines the variable to be used as key for request grouping.
Usually, the $binary_remote_addr is used rather than $remote_addr because it is smaller and saves space.

Maybe you alternatively want to use the RealipModule.
This will rewrite the remote address variables to the address provided in a custom header and will also make logging and other variable usage easier.