Skip to content

Commit c6d5fcf

Browse files
authored
feat: support setting real ip (#20)
1 parent e68463c commit c6d5fcf

File tree

5 files changed

+299
-0
lines changed

5 files changed

+299
-0
lines changed

lib/resty/apisix/client.lua

+23
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ local base = require("resty.core.base")
33
local get_request = base.get_request
44
local C = ffi.C
55
local NGX_ERROR = ngx.ERROR
6+
local NGX_OK = ngx.OK
67

78

89
base.allows_subsystem("http")
@@ -11,8 +12,14 @@ base.allows_subsystem("http")
1112
ffi.cdef([[
1213
typedef intptr_t ngx_int_t;
1314
typedef uintptr_t off_t;
15+
typedef unsigned char u_char;
16+
1417
ngx_int_t
1518
ngx_http_apisix_client_set_max_body_size(ngx_http_request_t *r, off_t bytes);
19+
20+
ngx_int_t
21+
ngx_http_apisix_set_real_ip(ngx_http_request_t *r, const u_char *text, size_t len,
22+
unsigned int port);
1623
]])
1724
local _M = {}
1825

@@ -28,4 +35,20 @@ function _M.set_client_max_body_size(bytes)
2835
end
2936

3037

38+
function _M.set_real_ip(ip, port)
39+
-- APISIX will ensure the IP and port are valid
40+
if not port then
41+
port = 0
42+
end
43+
44+
local r = get_request()
45+
local rc = C.ngx_http_apisix_set_real_ip(r, ip, #ip, port)
46+
if rc ~= NGX_OK then
47+
return nil, "error while setting real ip, rc: " .. tonumber(rc)
48+
end
49+
50+
return true
51+
end
52+
53+
3154
return _M

patch/1.19.3/nginx-real_ip.patch

+52
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
diff --git auto/modules auto/modules
2+
index f1c63f3..a71f9d7 100644
3+
--- auto/modules
4+
+++ auto/modules
5+
@@ -578,7 +578,7 @@ if [ $HTTP = YES ]; then
6+
7+
ngx_module_name=ngx_http_realip_module
8+
ngx_module_incs=
9+
- ngx_module_deps=
10+
+ ngx_module_deps=src/http/modules/ngx_http_realip_module.h
11+
ngx_module_srcs=src/http/modules/ngx_http_realip_module.c
12+
ngx_module_libs=
13+
ngx_module_link=$HTTP_REALIP
14+
diff --git src/http/modules/ngx_http_realip_module.c src/http/modules/ngx_http_realip_module.c
15+
index 9586ebe..05a40ea 100644
16+
--- src/http/modules/ngx_http_realip_module.c
17+
+++ src/http/modules/ngx_http_realip_module.c
18+
@@ -311,6 +311,15 @@ ngx_http_realip_cleanup(void *data)
19+
}
20+
21+
22+
+#if (NGX_HTTP_APISIX)
23+
+ngx_int_t
24+
+ngx_http_realip_set_real_addr(ngx_http_request_t *r, ngx_addr_t *addr)
25+
+{
26+
+ return ngx_http_realip_set_addr(r, addr);
27+
+}
28+
+#endif
29+
+
30+
+
31+
static char *
32+
ngx_http_realip_from(ngx_conf_t *cf, ngx_command_t *cmd, void *conf)
33+
{
34+
diff --git src/http/modules/ngx_http_realip_module.h src/http/modules/ngx_http_realip_module.h
35+
new file mode 100644
36+
index 0000000..8593c4b
37+
--- /dev/null
38+
+++ src/http/modules/ngx_http_realip_module.h
39+
@@ -0,0 +1,13 @@
40+
+#ifndef _NGX_HTTP_REALIP_H_INCLUDED_
41+
+#define _NGX_HTTP_REALIP_H_INCLUDED_
42+
+
43+
+
44+
+#include <ngx_config.h>
45+
+#include <ngx_core.h>
46+
+#include <ngx_http.h>
47+
+
48+
+
49+
+ngx_int_t ngx_http_realip_set_real_addr(ngx_http_request_t *r, ngx_addr_t *addr);
50+
+
51+
+
52+
+#endif /* _NGX_HTTP_REALIP_H_INCLUDED_ */

src/ngx_http_apisix_module.c

+64
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,17 @@
11
#include <ngx_config.h>
22
#include <ngx_core.h>
33
#include <ngx_http.h>
4+
#include <ngx_http.h>
5+
#include <ngx_http_realip_module.h>
46
#include "ngx_http_apisix_module.h"
57

68

9+
static ngx_str_t remote_addr = ngx_string("remote_addr");
10+
static ngx_str_t remote_port = ngx_string("remote_port");
11+
static ngx_str_t realip_remote_addr = ngx_string("realip_remote_addr");
12+
static ngx_str_t realip_remote_port = ngx_string("realip_remote_port");
13+
14+
715
static void *ngx_http_apisix_create_loc_conf(ngx_conf_t *cf);
816
static char *ngx_http_apisix_merge_loc_conf(ngx_conf_t *cf, void *parent,
917
void *child);
@@ -409,3 +417,59 @@ ngx_http_apisix_set_gzip(ngx_http_request_t *r, ngx_int_t num, size_t size,
409417
ctx->gzip = gzip;
410418
return NGX_OK;
411419
}
420+
421+
422+
ngx_int_t
423+
ngx_http_apisix_flush_var(ngx_http_request_t *r, ngx_str_t *name)
424+
{
425+
ngx_uint_t hash;
426+
ngx_http_variable_t *v;
427+
ngx_http_variable_value_t *vv;
428+
ngx_http_core_main_conf_t *cmcf;
429+
430+
hash = ngx_hash_key(name->data, name->len);
431+
432+
cmcf = ngx_http_get_module_main_conf(r, ngx_http_core_module);
433+
434+
v = ngx_hash_find(&cmcf->variables_hash, hash, name->data, name->len);
435+
436+
if (v) {
437+
vv = &r->variables[v->index];
438+
vv->valid = 0;
439+
440+
return NGX_OK;
441+
}
442+
443+
return NGX_DECLINED;
444+
}
445+
446+
447+
ngx_int_t
448+
ngx_http_apisix_set_real_ip(ngx_http_request_t *r, const u_char *text, size_t len,
449+
unsigned int port)
450+
{
451+
ngx_int_t rc;
452+
ngx_addr_t addr;
453+
454+
rc = ngx_parse_addr(r->connection->pool, &addr, (u_char *) text, len);
455+
if (rc != NGX_OK) {
456+
return rc;
457+
}
458+
459+
if (port == 0) {
460+
port = ngx_inet_get_port(r->connection->sockaddr);
461+
}
462+
ngx_inet_set_port(addr.sockaddr, (in_port_t) port);
463+
464+
rc = ngx_http_realip_set_real_addr(r, &addr);
465+
if (rc != NGX_DECLINED) {
466+
return rc;
467+
}
468+
469+
ngx_http_apisix_flush_var(r, &remote_addr);
470+
ngx_http_apisix_flush_var(r, &remote_port);
471+
ngx_http_apisix_flush_var(r, &realip_remote_addr);
472+
ngx_http_apisix_flush_var(r, &realip_remote_port);
473+
474+
return NGX_OK;
475+
}
File renamed without changes.

t/real_ip.t

+160
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,160 @@
1+
use t::APISIX_NGINX 'no_plan';
2+
3+
run_tests;
4+
5+
__DATA__
6+
7+
=== TEST 1: set real ip
8+
--- config
9+
location /t {
10+
content_by_lua_block {
11+
local client = require("resty.apisix.client")
12+
assert(client.set_real_ip("127.0.0.2"))
13+
ngx.say(ngx.var.remote_addr)
14+
ngx.say(ngx.var.remote_port == ngx.var.realip_remote_port)
15+
ngx.say(ngx.var.realip_remote_addr)
16+
}
17+
}
18+
--- response_body
19+
127.0.0.2
20+
true
21+
127.0.0.1
22+
23+
24+
25+
=== TEST 2: set real ip & port
26+
--- config
27+
location /t {
28+
content_by_lua_block {
29+
local client = require("resty.apisix.client")
30+
assert(client.set_real_ip("172.1.1.2", 1289))
31+
ngx.say(ngx.var.remote_addr)
32+
ngx.say(ngx.var.remote_port == "1289")
33+
ngx.say(ngx.var.realip_remote_addr)
34+
}
35+
}
36+
--- response_body
37+
172.1.1.2
38+
true
39+
127.0.0.1
40+
41+
42+
43+
=== TEST 3: IPv6
44+
--- config
45+
location /t {
46+
content_by_lua_block {
47+
local client = require("resty.apisix.client")
48+
assert(client.set_real_ip("1::2"))
49+
ngx.say(ngx.var.remote_addr)
50+
ngx.say(ngx.var.remote_port == ngx.var.realip_remote_port)
51+
}
52+
}
53+
--- response_body
54+
1::2
55+
true
56+
57+
58+
59+
=== TEST 4: call twice
60+
--- http_config
61+
log_format log '$realip_remote_addr:$realip_remote_port $remote_addr:$remote_port';
62+
--- config
63+
access_log logs/access.log log;
64+
location /t {
65+
access_by_lua_block {
66+
local client = require("resty.apisix.client")
67+
assert(client.set_real_ip("172.1.2.3", 1234))
68+
}
69+
content_by_lua_block {
70+
local client = require("resty.apisix.client")
71+
ngx.say(ngx.var.remote_addr)
72+
ngx.say(ngx.var.realip_remote_addr)
73+
ngx.say(ngx.var.remote_port)
74+
assert(client.set_real_ip("172.1.1.2", 12890))
75+
ngx.say(ngx.var.remote_addr)
76+
ngx.say(ngx.var.remote_port)
77+
ngx.say(ngx.var.realip_remote_addr)
78+
ngx.say(ngx.var.realip_remote_port)
79+
}
80+
}
81+
--- response_body
82+
172.1.2.3
83+
127.0.0.1
84+
1234
85+
172.1.1.2
86+
12890
87+
172.1.2.3
88+
1234
89+
--- access_log
90+
172.1.2.3:1234 172.1.1.2:12890
91+
92+
93+
94+
=== TEST 5: use with realip module
95+
--- http_config
96+
log_format log '$realip_remote_addr:$realip_remote_port $remote_addr:$remote_port';
97+
--- config
98+
access_log logs/access.log log;
99+
set_real_ip_from 0.0.0.0/0;
100+
real_ip_header X-Forwarded-For;
101+
location /t {
102+
content_by_lua_block {
103+
local client = require("resty.apisix.client")
104+
ngx.say(ngx.var.remote_addr)
105+
ngx.say(ngx.var.realip_remote_addr)
106+
ngx.say(ngx.var.remote_port)
107+
assert(client.set_real_ip("172.1.1.2", 12890))
108+
ngx.say(ngx.var.remote_addr)
109+
ngx.say(ngx.var.remote_port)
110+
ngx.say(ngx.var.realip_remote_addr)
111+
ngx.say(ngx.var.realip_remote_port)
112+
}
113+
}
114+
--- more_headers
115+
X-Forwarded-For: 172.1.2.3:1234
116+
--- response_body
117+
172.1.2.3
118+
127.0.0.1
119+
1234
120+
172.1.1.2
121+
12890
122+
172.1.2.3
123+
1234
124+
--- access_log
125+
172.1.2.3:1234 172.1.1.2:12890
126+
127+
128+
129+
=== TEST 6: use with realip module, no port
130+
--- http_config
131+
log_format log '$realip_remote_addr:$realip_remote_port $remote_addr:$remote_port';
132+
--- config
133+
access_log logs/access.log log;
134+
set_real_ip_from 0.0.0.0/0;
135+
real_ip_header X-Forwarded-For;
136+
location /t {
137+
content_by_lua_block {
138+
local client = require("resty.apisix.client")
139+
ngx.say(ngx.var.remote_addr)
140+
ngx.say(ngx.var.realip_remote_addr)
141+
ngx.say(ngx.var.remote_port)
142+
assert(client.set_real_ip("172.1.1.2", 12890))
143+
ngx.say(ngx.var.remote_addr)
144+
ngx.say(ngx.var.remote_port)
145+
ngx.say(ngx.var.realip_remote_port)
146+
ngx.say(ngx.var.realip_remote_addr)
147+
}
148+
}
149+
--- more_headers
150+
X-Forwarded-For: 172.1.2.3
151+
--- response_body
152+
172.1.2.3
153+
127.0.0.1
154+
155+
172.1.1.2
156+
12890
157+
158+
172.1.2.3
159+
--- access_log
160+
172.1.2.3: 172.1.1.2:12890

0 commit comments

Comments
 (0)