如果Nginx工作在某些7层负载均衡代理后面,这个功能对于Nginx服务器非常有用,由于客户端请求的本地IP(就是客户端的请求地址)在通过7层代理时被添加了客户端IP地址头,因此才使得后端的Nginx能够取得震慑客户端的IP地址值。该模块在默认安装是并没有安装,因此如果要使用该模块,那么在编译安装是需要添加--with-http_realip_module选项。

为什么使用该模块,它的意义在于能够使得后台服务器记录原始客户端的IP地址。

指 令

该模块仅提供了两条指令。

指令名称:set_real_ip_from

功 能:通过该指令指定信任的地址,将会被替代为精确的IP地址。从0.8.22版本后也可以使用信任的Unix套接字。这里设置的IP就是指前端Nginx 、Varnish或者 Squid 的 IP地址。

语 法: set_real_ip_from [the address|CIDR|"unix:"]

默 认 值: none

使用环境: http, server, location

指令名称:real_ip_header

功 能:这个指令用于设置使用哪个头来替换IP地址。如果使用了X-Forwarded-For,那么该模块将会使用X-Forwarded-For头中的最后一个IP地址来替换前端代理的IP地址。

语 法: real_ip_header [X-Real-IP|X-Forwarded-For]

默 认 值: real_ip_header X-Real-IP

使用环境: http, server, location

使用实例

在下面的实例中,我们环境是这样的有两台Nginx服务器,一台是前端,另一台是后端,前端的Nginx被用作代理,而后台的Nginx用于提供页面访问,还有一台客户端,IP地址如下:



前端Nginx:192.168.7.10

后端Nginx:192.168.1.15

客户端主机:218.239.201.36





前端的Nginx配置是这样的:
server { listen 80; server_name www.xx.com;location / { root html; index index.html index.htm;charset utf-8; }location /865 { proxy_pass http://192.168.3.139:80/; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header Host $host; proxy_redirect off; }……}

后端的Nginx配置如下:

server { listen 80; server_name localhost; location / { root /var/www/html; index index.html index.htm; }

访问测试

如果我们访问http://www.xx.com/865,没问题,可以是正常访问,访问日志如下:



前端Nginx的日志:
218.239.201.36 - - [30/Aug/2011:16:09:56 +0800] "GET /865/ HTTP/1.1" 200 151 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12 GTB7.1"
后端Nginx的日志:
192.168.7.10 - - [30/Aug/2011:16:09:56 +0800] "GET // HTTP/1.0" 200 151 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12 GTB7.1"
我们看到在后端Nginx的日志中并没有记录原始客户端的IP地址,而是记录了前端Nginx的IP地址。



如果将后台Nginx服务器的配置修改为:
server { listen 80; server_name localhost; set_real_ip_from 192.168.3.0/24; set_real_ip_from 100.100.0.0/16; real_ip_header X-Real-IP; location / { root html; index index.html index.htm; } ……}

然后我们再次进行访问测试:

前端Nginx的日志:
218.239.201.36 - - [30/Aug/2011:16:10:28 +0800 "GET /865/ HTTP/1.1" 304 0 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12 GTB7.1"
后端Nginx的日志:
218.239.201.36 - - [30/Aug/2011:16:10:28 +0800] "GET // HTTP/1.0" 304 0 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12 GTB7.1"
可见,这次后台记录的是客户端的IP地址。

其它:

 但是在有些场景下,希望在使用with-http_realipmodule模块之前,需要获得原始的remote\__addr, 并且保存下来,怎样获得第一层的remote\_addr 并且保存下来。

  查看该模块的源代码 \src\http\modules\ngx\_http\_realip\_module.c  line:113
static ngx_http_variable_t  ngx_http_realip_vars[] = {

    { ngx_string("realip_remote_addr"), NULL,
      ngx_http_realip_remote_addr_variable, 0, 0, 0 },

    { ngx_null_string, NULL, NULL, 0, 0, 0 }
};

最终代码在 line:478行 最终将原始的remote_addr 存入nginx 内置环境变量 realip_remote_addr 中

static ngx_int_t
ngx_http_realip_remote_addr_variable(ngx_http_request_t *r,
    ngx_http_variable_value_t *v, uintptr_t data)
{
  .....
   addr_text = ctx ? &ctx->addr_text : &r->connection->addr_text;

    v->len = addr_text->len;
    v->valid = 1;
    v->no_cacheable = 0;
    v->not_found = 0;
    v->data = addr_text->data;
    ...
    }

实际测试 在 nginx.conf的日志配置中 添加$realip_remote_addr变量,

log_format  main  '$realip_remote_addr $remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    set_real_ip_from   0.0.0.0/0;
    real_ip_header    X-Forwarded-For;
    real_ip_recursive on;

发送请求:

GET / HTTP/1.1
Host: 192.168.109.181
X-Forwarded-For: 1.1.1.4,1.1.1.1,2.2.2.2

服务器日志信息:

192.168.109.130 1.1.1.4 - - [10/Jan/2018:08:51:27 -0800] "GET / HTTP/1.1" 403 169 "-" "Mozilla/5.0 (X11; Linux i686; rv:14.0) Gecko/20100101 Firefox/14.0.1" "1.1.1.4,1.1.1.1,2.2.2.2"

可以看到realip_remote_addr 确实是获得的真实ip地址。

参考文献:

http://blog.csdn.net/cscrazybing/article/details/50789234

results matching ""

    No results matching ""