1. 编译

对于client -> nginx reverse proxy -> apache,

要想在程序中取得真实的IP,在执行nginx的configure时,必须指定参数“--with-http_realip_module”,示例:

./configure --prefix=/data/nginx --with-http_realip_module --with-stream --with-pcre=/tmp/X/pcre-8.32 --with-openssl=/tmp/X/openssl-1.0.2a

参数说明:

--prefix= 指定安装目录,也就是make install后程序文件等的存放目录

--with-http_realip_module 使得程序可以通过环境变量HTTP_X_REAL_IP取得真实的客户端IP地址

--with-stream 表示启用TCP代理

--with-pcre= 指定依赖的pcre,注意为pcre源代码解压后的目录路径,而不是安装路径

--with-openssl= 指定依赖的openssl,注意为openssl源代码解压后的目录路径,而不是安装路径

另外,最简单的确认方法是使用nm命令查看nginx程序文件,看看是否有包含real相关的符号,对于版本nginx-1.9.4 ,可以发现存在“0809c54b t ngx_http_realip”。

2. 程序代码

测试程序代码(后续测试基于它):

// g++ -g -o hello.cgi hello.cpp

#include <stdio.h>

#include <stdlib.h>

int main()

{

printf("Content-Type: text/html; charset=utf-8\r\n\r\n");

printf("<p>HTTP_X_FORWARDED_FOR: %s\n", getenv("HTTP_X_FORWARDED_FOR"));

printf("<p>HTTP_X_REAL_IP: %s\n", getenv("HTTP_X_REAL_IP"));

printf("<p>REMOTE_ADDR: %s\n", getenv("REMOTE_ADDR"));

printf("<p>");

return 0;

}

测试是在nginx自带配置文件nginx.conf上进行的修改:

proxy_set_header可以添加在nginx.conf的http段,也可以是server段,还可以是location段,一级一级间是继承和覆盖关系。

3. 相关配置

示例:

location / {

#    root   html;

#    index  index.html index.htm;

proxy_pass http://20.61.28.11:80;

proxy_redirect off;

proxy_set_header   Host    $host;

proxy_set_header   X-Real-IP   $remote_addr;  # 这个是必须的

proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;

}

X-Forwarded-For和X-Real-IP的区别是,如果请求时已带了X-Forwarded-For,则nginx追加方式,这样可以通过它显示转发的轨迹。

当然请求时完全可以构造假的X-Forwarded-For,在配置文件打开了X-Real-IP及编译指定了--with-http_realip_module时,环境变量HTTP_X_REAL_IP总是为真实的客户端IP。

如果是:

client -> nginx reverse proxy (A) -> nginx reverse proxy (B) -> apache

HTTP_X_REAL_IP又会是什么了?

4. 测试1

假设如下部署:

client(10.6.81.39) -> nginx(10.6.223.44:8080) -> nginx(10.6.208.101:8080) -> apache(10.6.208.101:80)

Ø A

假设nginx(10.6.223.44:8080)的配置均为(在nginx默认配置上的修改部分):

server {

listen       8080;

server_name  10.6.223.44;

location / {

#    root   html;

#    index  index.html index.htm;

proxy_pass http://10.6.208.101:8080;

proxy_redirect off;

proxy_set_header   Host    $host;

proxy_set_header   X-Real-IP   $remote_addr;

proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;

}

假设nginx(10.6.208.101:8080)的配置均为(在nginx默认配置上的修改部分):

server {

listen       8080;

server_name  10.6.208.101;

location / {

#    root   html;

#    index  index.html index.htm;

proxy_pass http://10.6.208.101:80;

proxy_redirect off;

proxy_set_header   Host    $host;

proxy_set_header   X-Real-IP   $remote_addr;

proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;

}

上述测试程序输出的结果为:

<p>HTTP_X_FORWARDED_FOR: 10.6.81.39, 10.6.223.44

<p>HTTP_X_REAL_IP: 10.6.223.44

<p>REMOTE_ADDR: 10.6.81.39

Ø B

但如果client在HTTP请求头中加入:

X-FORWARDED-FOR:8.8.8.7

CLIENT-IP:8.8.8.8

X-REAL-IP:8.8.8.10

后输出结果变成:

<p>HTTP_X_FORWARDED_FOR: 8.8.8.7, 10.6.81.39, 10.6.223.44

<p>HTTP_X_REAL_IP: 10.6.223.44

<p>REMOTE_ADDR: 8.8.8.7

Ø C

基于A,如果只nginx(10.6.223.44:8080)配置注释掉“X-Forwarded-For”,输出结果变成:

<p>HTTP_X_FORWARDED_FOR: 10.6.223.44

<p>HTTP_X_REAL_IP: 10.6.223.44

<p>REMOTE_ADDR: 10.6.223.44

Ø D

基于A,如果只nginx(10.6.208.101:8080)配置注释掉“X-Forwarded-For”,输出结果变成:

<p>HTTP_X_FORWARDED_FOR: 10.6.81.39

<p>HTTP_X_REAL_IP: 10.6.223.44

<p>REMOTE_ADDR: 10.6.81.39

5. 测试2

基于测试1的配置,

当访问路径变成:client(10.6.81.39) -> nginx(10.6.208.101:8080) -> apache(10.6.208.101:80)时,程序输出结果为:

<p>HTTP_X_FORWARDED_FOR: 10.6.81.39

<p>HTTP_X_REAL_IP: 10.6.81.39

<p>REMOTE_ADDR: 10.6.81.39

但如果client在HTTP请求头中加入:

X-FORWARDED-FOR:8.8.8.7

CLIENT-IP:8.8.8.8

X-REAL-IP:8.8.8.10

后输出结果变成:

<p>HTTP_X_FORWARDED_FOR: 8.8.8.7, 10.6.81.39

<p>HTTP_X_REAL_IP: 10.6.81.39

<p>REMOTE_ADDR: 8.8.8.7

从上可以看出,只配置正确使用了real-ip功能,除HTTP_X_REAL_IP外,其它内容可以被干扰,client可以篡改它们。

6. 结论

如果正确编译和配置了nginx反向代理,当只有一层nginx反向代理时,可以通过“HTTP_X_REAL_IP”取得client的真实IP。

如果有二层nginx反向代理,则client的真实IP被包含在“HTTP_X_FORWARDED_FOR”中。

最不可信的是“REMOTE_ADDR”,它的内容完全可以被client指定!总之只要编译和配置正确,“HTTP_X_FORWARDED_FOR”总是包含了client的真实IP。

如何取得nginx做反向代理时的真实IP?的更多相关文章

  1. nginx做反向代理时获取真实IP

    原文:http://blog.csdn.net/aquester/article/details/48657395 1. 编译 对于client -> nginx reverse proxy - ...

  2. 【Nginx】使用Nginx做反向代理时,关于被代理服务器相应的超时设置

    > 参考的优秀文章 Module ngx_http_proxy_module > 设置等待被代理服务器的最大响应时间 使用Nginx做反向代理时,因被代理服务器因业务确实复杂,需时较久,往 ...

  3. nginx做反向代理时出现302错误

    现象:nginx在使用非80端口做反向代理时,浏览器访问发现返回302错误 详细现象如下: 浏览器请求登录页: 输入账号密码点击登录: 很明显登录后跳转的地址少了端口号. 原因:proxy.conf文 ...

  4. nginx做反向代理时出现302错误(转载)

    现象:nginx在使用非80端口做反向代理时,浏览器访问发现返回302错误 详细现象如下: 浏览器请求登录页: 输入账号密码点击登录: 很明显登录后跳转的地址少了端口号. 原因:proxy.conf文 ...

  5. Nginx作为反向代理时传递客户端IP的设置方法

    因为nginx的优越性,现在越来越多的用户在生产环境中使用nginx作为前端,不管nginx在前端是做负载均衡还是只做简单的反向代理,都需要把日志转发到后端real server,以方便我们检查程序的 ...

  6. nginx多层反向代理获取客户端真实ip

    访问路径: 用户 --> www.chinasoft.cn(nginx反向代理) --> www.chinasoft.com(nginx反向代理) --> python服务端程序 经 ...

  7. Nginx做反向代理时访问端口被自动去除

    使用的Nginx版本 : nginx/1.13.10 出现问题的配置文件如下 upstream http-web { server 0.0.0.0:9000; } server { listen 80 ...

  8. nginx 多级反向代理获取客户端真实IP

    set_real_ip_from ; set_real_ip_from ; set_real_ip_from ; set_real_ip_from ; set_real_ip_from 127.0.0 ...

  9. nginx反向代理获取用户真实ip

    nginx做反向代理时,默认的配置后端获取到的ip都是来自于nginx,如何转发用户的真实ip到后端程序呢?如是是java后端,用request.getRemoteAddr();获取到的是nginx的 ...

随机推荐

  1. Java-Web 用html和css写一个EasyMall注册界面

    要求: html代码: <!DOCTYPE html> <html> <head> <title>EasyMall注册页面</title> ...

  2. Git 安装部署

    CentOS6的yum源中已经有git的版本了,可以直接使用yum源进行安装. yum install/remove git 但是yum源中安装的git版本是1.7.1,太老了,Github等需要的G ...

  3. Go语言优势与劣势

    Go语言的优势: 1.脚本化的语法:开发效率高,容易上手 2.静态类型+编译型,程序运行速度有保障:静态类型+编译型语言相对于动态类型+解释型语言的效率高 3.原生的支持并发编程:降低开发.维护成本/ ...

  4. Numpy的ndarry:一种多维数组对象

    Numpy的ndarry:一种多维数组对象 Numpy最重要的一个特点就是其N维数组对象(即ndarry),该对象是一个快速而灵活的大数据集容器.你可以利用这种数组对整块数据执行一些数学运算,其语法跟 ...

  5. notepad++正则表达式例子

    1.匹配create table USR.APP (  这样的字符串: create.*USR.APP\s+\(

  6. 7.25 6figting!

    TEXT 82 Proton 马来西亚宝腾汽车 A fork in the road 何去何从?(陈继龙编译) Nov 30th 2006 | HONG KONG From The Economist ...

  7. 实现HBase增量入库(HBase删除自定义时间戳行数据)

    目录 1. 背景描述 2. 问题描述 3. 解决方案 1. 背景描述 目前在做音乐推荐项目,前期做排序模型优化,任务是使用模型对用户的历史音乐进行排序,有6800多万个用户,约40G的用户数据,使用H ...

  8. 在 springboot 中如何整合 shiro 应用 ?

     Shiro是Apache下的一个开源项目,我们称之为Apache Shiro. 它是一个很易用与Java项目的的安全框架,提供了认证.授权.加密.会话管理,与spring Security 一样都是 ...

  9. 解决MongoDB分页查询之count查询慢的问题

    一.概述 问题描述:在项目中优化动态查询分页接口时,发现count查询很慢(数据量大概30万),那如何解决这个问题呢? 解决方法:添加索引,多个查询条件可以添加复合索引 二.测试对比 1. 未加索引时 ...

  10. myeclipse10安装了activiti插件后创建BPMN 文件时报错,

    以上错误需要,下载一个补丁. 补丁地址:http://www.shareyx.com/blog/2 补丁的安装可以参考: http://jingyan.baidu.com/article/dca1fa ...