From 9fa04a923cd12a34ee97ee055aa263925f060c55 Mon Sep 17 00:00:00 2001 From: WenMing Date: Fri, 12 Jul 2019 11:25:17 +0800 Subject: [PATCH] feature: supported real_ip configure in nginx.conf and added functions to get ip and remote ip. (#236) * feature: supported real_ip configure in nginx.conf and added functions to get ip and remote ip. * fixed code style. --- bin/apisix | 5 + conf/config.yaml | 4 + lua/apisix/core/request.lua | 15 +++ lua/apisix/plugins/limit-conn.lua | 3 +- lua/apisix/plugins/limit-count.lua | 3 +- lua/apisix/plugins/limit-req.lua | 3 +- t/core/request.t | 192 +++++++++++++++++++++++++++++ 7 files changed, 222 insertions(+), 3 deletions(-) create mode 100644 t/core/request.t diff --git a/bin/apisix b/bin/apisix index 98436f5a..e1dda592 100755 --- a/bin/apisix +++ b/bin/apisix @@ -110,6 +110,11 @@ http { server_tokens off; more_set_headers 'Server: APISIX web server'; + real_ip_header {* real_ip_header *}; + {% for _, real_ip in ipairs(real_ip_from) do %} + set_real_ip_from {{real_ip}}; + {% end %} + upstream apisix_backend { server 0.0.0.1; balancer_by_lua_block { diff --git a/conf/config.yaml b/conf/config.yaml index 91d594c3..67c961b6 100644 --- a/conf/config.yaml +++ b/conf/config.yaml @@ -4,6 +4,10 @@ apisix: enable_heartbeat: true enable_admin: true allow_admin: "127.0.0.0/24" + real_ip_header: "X-Real-IP" # http://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header + real_ip_from: # http://nginx.org/en/docs/http/ngx_http_realip_module.html#set_real_ip_from + - 127.0.0.1 + - 'unix:' # port_admin: 9180 # use a separate port etcd: diff --git a/lua/apisix/core/request.lua b/lua/apisix/core/request.lua index f687130e..cfaac65e 100644 --- a/lua/apisix/core/request.lua +++ b/lua/apisix/core/request.lua @@ -24,4 +24,19 @@ function _M.header(ctx, name) end +-- return the remote address of client which directly connecting to APISIX. +-- so if there is a load balancer between downstream client and APISIX, +-- this function will return the ip of load balancer. +function _M.get_ip(ctx) + return ctx.var.realip_remote_addr or ctx.var.remote_addr or '' +end + + +-- get remote address of downstream client, +-- in cases there is a load balancer between downstream client and APISIX. +function _M.get_remote_client_ip(ctx) + return ctx.var.remote_addr or '' +end + + return _M diff --git a/lua/apisix/plugins/limit-conn.lua b/lua/apisix/plugins/limit-conn.lua index 0b5f8cf5..1da057f7 100644 --- a/lua/apisix/plugins/limit-conn.lua +++ b/lua/apisix/plugins/limit-conn.lua @@ -49,7 +49,8 @@ function _M.access(conf, ctx) return 500 end - local key = (ctx.var[conf.key] or "") .. ctx.conf_version + local ip = core.request.get_remote_client_ip(ctx) + local key = ip .. ctx.conf_version local rejected_code = conf.rejected_code local delay, err = lim:incoming(key, true) diff --git a/lua/apisix/plugins/limit-count.lua b/lua/apisix/plugins/limit-count.lua index 74ba74a1..7690f926 100644 --- a/lua/apisix/plugins/limit-count.lua +++ b/lua/apisix/plugins/limit-count.lua @@ -44,7 +44,8 @@ function _M.access(conf, ctx) return 500 end - local key = (ctx.var[conf.key] or "") .. ctx.conf_version + local ip = core.request.get_remote_client_ip(ctx) + local key = ip .. ctx.conf_version local rejected_code = conf.rejected_code local delay, remaining = lim:incoming(key, true) diff --git a/lua/apisix/plugins/limit-req.lua b/lua/apisix/plugins/limit-req.lua index bb8a261c..093cced8 100644 --- a/lua/apisix/plugins/limit-req.lua +++ b/lua/apisix/plugins/limit-req.lua @@ -48,7 +48,8 @@ function _M.access(conf, ctx) return 500 end - local key = (ctx.var[conf.key] or "") .. ctx.conf_version + local ip = core.request.get_remote_client_ip(ctx) + local key = ip .. ctx.conf_version local delay, err = lim:incoming(key, true) if not delay then if err == "rejected" then diff --git a/t/core/request.t b/t/core/request.t new file mode 100644 index 00000000..30adcea9 --- /dev/null +++ b/t/core/request.t @@ -0,0 +1,192 @@ +use t::APISix 'no_plan'; + +repeat_each(1); +no_long_string(); +no_root_location(); +log_level("info"); + +run_tests; + +__DATA__ + +=== TEST 1: get_ip +--- config + location = /hello { + real_ip_header X-Real-IP; + + set_real_ip_from 0.0.0.0/0; + set_real_ip_from ::/0; + set_real_ip_from unix:; + + access_by_lua_block { + local core = require("apisix.core") + local ngx_ctx = ngx.ctx + local api_ctx = ngx_ctx.api_ctx + if api_ctx == nil then + api_ctx = core.tablepool.fetch("api_ctx", 0, 32) + ngx_ctx.api_ctx = api_ctx + end + + core.ctx.set_vars_meta(api_ctx) + } + content_by_lua_block { + local core = require("apisix.core") + local ip = core.request.get_ip(ngx.ctx.api_ctx) + ngx.say(ip) + } + } +--- request +GET /hello +--- more_headers +X-Real-IP: 10.0.0.1 +--- response_body +127.0.0.1 +--- no_error_log +[error] + + + +=== TEST 2: get_ip +--- config + location = /hello { + real_ip_header X-Real-IP; + + set_real_ip_from 0.0.0.0/0; + set_real_ip_from ::/0; + set_real_ip_from unix:; + + access_by_lua_block { + local core = require("apisix.core") + local ngx_ctx = ngx.ctx + local api_ctx = ngx_ctx.api_ctx + if api_ctx == nil then + api_ctx = core.tablepool.fetch("api_ctx", 0, 32) + ngx_ctx.api_ctx = api_ctx + end + + core.ctx.set_vars_meta(api_ctx) + } + content_by_lua_block { + local core = require("apisix.core") + local ip = core.request.get_ip(ngx.ctx.api_ctx) + ngx.say(ip) + } + } +--- request +GET /hello +--- more_headers +X-Real-IP: 10.0.0.1 +--- response_body +127.0.0.1 +--- no_error_log +[error] + + + +=== TEST 3: get_ip and X-Forwarded-For +--- config + location = /hello { + real_ip_header X-Forwarded-For; + + set_real_ip_from 0.0.0.0/0; + set_real_ip_from ::/0; + set_real_ip_from unix:; + + access_by_lua_block { + local core = require("apisix.core") + local ngx_ctx = ngx.ctx + local api_ctx = ngx_ctx.api_ctx + if api_ctx == nil then + api_ctx = core.tablepool.fetch("api_ctx", 0, 32) + ngx_ctx.api_ctx = api_ctx + end + + core.ctx.set_vars_meta(api_ctx) + } + content_by_lua_block { + local core = require("apisix.core") + local ip = core.request.get_ip(ngx.ctx.api_ctx) + ngx.say(ip) + } + } +--- request +GET /hello +--- more_headers +X-Forwarded-For: 10.0.0.1 +--- response_body +127.0.0.1 +--- no_error_log +[error] + + + +=== TEST 4: get_remote_client_ip +--- config + location = /hello { + real_ip_header X-Real-IP; + + set_real_ip_from 0.0.0.0/0; + set_real_ip_from ::/0; + set_real_ip_from unix:; + + access_by_lua_block { + local core = require("apisix.core") + local ngx_ctx = ngx.ctx + local api_ctx = ngx_ctx.api_ctx + if api_ctx == nil then + api_ctx = core.tablepool.fetch("api_ctx", 0, 32) + ngx_ctx.api_ctx = api_ctx + end + + core.ctx.set_vars_meta(api_ctx) + } + content_by_lua_block { + local core = require("apisix.core") + local ip = core.request.get_remote_client_ip(ngx.ctx.api_ctx) + ngx.say(ip) + } + } +--- request +GET /hello +--- more_headers +X-Real-IP: 10.0.0.1 +--- response_body +10.0.0.1 +--- no_error_log +[error] + + + +=== TEST 5: get_remote_client_ip and X-Forwarded-For +--- config + location = /hello { + real_ip_header X-Forwarded-For; + set_real_ip_from 0.0.0.0/0; + set_real_ip_from ::/0; + set_real_ip_from unix:; + + access_by_lua_block { + local core = require("apisix.core") + local ngx_ctx = ngx.ctx + local api_ctx = ngx_ctx.api_ctx + if api_ctx == nil then + api_ctx = core.tablepool.fetch("api_ctx", 0, 32) + ngx_ctx.api_ctx = api_ctx + end + + core.ctx.set_vars_meta(api_ctx) + } + content_by_lua_block { + local core = require("apisix.core") + local ip = core.request.get_remote_client_ip(ngx.ctx.api_ctx) + ngx.say(ip) + } + } +--- request +GET /hello +--- more_headers +X-Forwarded-For: 10.0.0.1 +--- response_body +10.0.0.1 +--- no_error_log +[error]