Supports CloudFlare, Incapsula, Sucuri, Any Proxy …
function str_split(s, sep) if sep == nil then sep = '%s' end local res = {} local func = function(w) table.insert(res, w) end string.gsub(s, '[^'..sep..']+', func) return res end function get_client_ip() -- Default to REMOTE_ADDR local ip = ngx.var.remote_addr local proxy_headers = { ngx.var.http_cf_connecting_ip, -- CloudFlare ngx.var.http_incap_client_ip, -- Incapsula ngx.var.http_x_sucuri_clientip, -- Sucuri ngx.var.http_x_forwarded_for -- Any Proxy } -- Check for alternate headers indicating a forwarded IP address for _,proxy_header in ipairs ( proxy_headers ) do if proxy_header then local forwarded_ips = str_split( proxy_header , ',' ) local forwarded_ip = forwarded_ips[1] if forwarded_ip then ip = forwarded_ip break end end end return ip; end
Note: if you use reverse proxy, you should use:
location / { proxy_set_header Host $host; proxy_set_header X-Forwarded-For $remote_addr; proxy_pass http://YOUR_PROXY; }
Test:
location = /test/ip { default_type 'text/html'; content_by_lua_block{ local ip = get_client_ip() ngx.say(ip) } }
Online demo: http://5.161.72.222/test/ip