上次说了,有个需求,是使用nginx做反向代理用的。可以看看具体的nginx的安装。另外还有一篇介绍Squid的正向代理

基本的nginx反向代理设置

要配置一下nginx,进入到${nginx}/conf/nginx.conf,增加一个服务器。

增加一条server记录

server {
        listen 80;  # 端口
        server_name testproxy; # 域名

        location / {
                proxy_pass http://www.chenyudong.com/;  # 需要访问的网站
                proxy_redirect off;                 # 重定向关闭
                proxy_set_header Host $host;        # 设置一下访问头
        }
    }

注意:通过上面的方法,只是服务器简单的将文件下载下来,然后就未加工的提交给用户了。也就是里面的链接是不会出现替换的,原来是什么就该是什么。

那么要替换某些URL要怎么做的?

替换网页里某些关键字或链接

如果需要替换关键字或者链接,该怎么办呢?

我们需要重新编译一下nginx,对,重新编译。在编译的时候添加参数--with-http_sub_module。也就是编译的命令./configure --with-http_sub_module。然后的安装过程见这篇文章。

接下来需要修改一下${nginx}/conf/nginx.conf配置。

server {
        listen 80;  # 端口
        server_name testproxy; # 域名

        ##将页面出现的www.baidu.com改成google.com
        sub_filter 'www.baidu.com' 'google.com';

        ## off:在符合的地方,替换所有出现的地方。默认为on:只替换第一个出现的地方
        sub_filter_once off;

        location / {
                proxy_pass http://www.google.com/;  # 需要访问的网站
                proxy_redirect off;                 # 重定向关闭
                proxy_set_header Host $host;        # 设置一下访问头
        }
    }

需要关心用于的真实IP了

说明:这个用户的真实IP指的是,直接和我们服务器连接的那个IP,用户可以躲在代理后面,这种情况获取不到用户真实IP,想要获得,成本很高,还不一定能获得到。下文说的都是基于这个前提条件的。

以上配置,是多么美好啊,应该能正常工作了。但是还是有些不足,就是我们对用户真实IP的获取上,已经无法通过_SERVER['REMOTE_ADDR']获取,因为这个获取的值是前台的nginx的IP。

nginx反向代理

nginx反向代理

对于我们backend nginx代理,只能看到所有的请求是来自front nginx的,所以PHP程序想要获得用户的真实IP,需要做一些设置。

## front nginx 设置
server {
    listen          80;
    server_name     server.com;
    #access_log      /data/home/log/server.access.log main;

    location / {
        proxy_pass http://www.chenyudong.com/;
        proxy_redirect off;
        proxy_set_header X-real-ip $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

从HTTP_X_REAL_IP获取

通过增加HTTP_X_REAL_IPHTTP_X_FORWARDED_FOR这两个变量,让后端的backend nginx从这里获取用户的真实IP。

设置用户真实IP头的结果

设置用户真实IP头的结果

我们可以看到,PHP中的HTTP_X_REAL_IPHTTP_X_FORWARDED_FOR已经获取到用户的真实IP了。

这还不够完美,这需要我们的程序重新使用_SERVER["HTTP_X_REAL_IP"]这样来取值。但是程序不是从头写起的,大家都在使用_SERVER['REMOTE_ADDR']获取,要替换,工程浩大,不适宜。那么就只能在程序的入口做个变量的替换了。

<?php
    _SERVER['REMOTE_ADDR'] = _SERVER["HTTP_X_REAL_IP"];
....
?>

来个狠的,就要从REMOTE_ADDR获取

如果你觉得上面还是不太爽,我就是从那里取值。

在上面front nginx的配置基础上不变。这次我们对backend nginx做配置:

 location ~ ^.+\.php {
          fastcgi_pass 127.0.0.1:9000;
          fastcgi_index index.php;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          include fastcgi_params;
          fastcgi_param REMOTE_ADDR $HTTP_X_REAL_IP;
  }

就是高亮的第六行,添加fastcgi_param REMOTE_ADDR $HTTP_X_REAL_IP;,把REMOTE_ADDR这个变量在这里就给他替换了。看看替换的结果:

替换REMOTE_ADDR变量

替换REMOTE_ADDR变量

经过这么一折腾,我们的PHP就可以和以前一样工作了。

这样就好了吗?

如果你觉得这样,就可以了,那就错了。虽然我们的PHP正确获得了用户的IP,但是nginx要打access的log,看看他的log,你会发现请求的IP还是front nginx的那个IP。

要解决这个问题,我们就要再修改一把。并且这个解决方案比上一步来的更好一些。完全可以替换上一部的方案。

前端的front nginx的配置和前面一样。

## front nginx 设置
server {
    listen          80;
    server_name     server.com;
    #access_log      /data/home/log/server.access.log main;

    location / {
        proxy_pass http://www.chenyudong.com/;
        proxy_redirect off;
        proxy_set_header X-real-ip $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    }
}

后台的backend nginx要使用set_real_ip_fromreal_ip_header这两个指令,这两个是在nginx的HttpRealipModule中,这个模块默认不被编译,因此需要在编译是添加--with-http_realip_module参数

## 源码编译增加参数
./configure --with-http_realip_module

## yum 安装默认是有安装的,可以
nginx -V ##查看一下编译的参数

后端的backend nginx配置

## backend nginx
location ~ ^.+\.php {
          fastcgi_pass 127.0.0.1:9000;
          fastcgi_index index.php;
          fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
          include fastcgi_params;
          set_real_ip_from   10.221.0.197;
          #set_real_ip_from   100.100.0.0/16;
          #set_real_ip_from  2001:0db8::/32;
          real_ip_header     X-Real-IP;
}

第7行,set_real_ip_from定义了一个信任的IP地址,从这个信任的IP发送的可以替换用户的IP地址。如果值是unix,所有来自UNIX域的sockets都被信任。

IPv6 addresses are supported starting from versions 1.3.0 and 1.2.1.

第10行,real_ip_header定义了一个请求头,用于替换用户的真实IP。

这样的配置,我们的_SERVER['REMOTE_ADDR']还是用户的真实IP,而不是front nginx的IP。并且log里面的IP也是用户的真实IP。还等什么,赶快试一试吧。

参考资料:

声明:未经允许禁止转载 东东东 陈煜东的博客 文章,谢谢。如经授权,转载请注明: 转载自东东东 陈煜东的博客

本文链接地址: nginx 反向代理 proxy – https://www.chenyudong.com/archives/nginx-reverse-proxy.html