Lua / Openresty: How to get real client IP address


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

Leave a Reply