专栏首页MyPanda的学习笔记nginx反向代理中的相关IP

nginx反向代理中的相关IP

场景一: 没有使用反向代理 配置nginx.conf,添加/修改 log 相关配置如下:

http {
......
    log_format  main  'Parameter remote_addr : $remote_addr\n'
                      'Parameter http_x_forwarded_for: $http_x_forwarded_for\n'
                      'Parameter http_x_real_ip : $http_x_real_ip';
    access_log  /var/log/nginx/access.log  main;
......
}

启动nginx服务,并通过浏览器访问,查看访问日志结果如下: 其中http_x_forwarded_for 的值是“空”,因为server端没有reverse proxy,所以该变量就不存在,该变量仅仅在proxy中才有效. 而http_x_real_ip的值同样为"空“, 也和http_x_forwarded_for是一样的原因,但是remote_addr的值就是client端的IP,remote_addr的值不能进行修改,由系统控制,直接访问就可以引用,如果启用的是nginx容器,那么结果也是一样,对于没有配置反向代理的情况,基于host的Nginx和基于container的nginx,对于上述的验证结果是一致的

[root@instance-6p8qz002 log]# tail -n0 -f access.log
Parameter remote_addr : 119.123.134.165
Parameter http_x_forwarded_for: -
Parameter http_x_real_ip : -

.

场景二:只有一个reverse proxy 在此测试场景中,使用docker 启动一个nginx 容器作为 service provider(映射host主机的8080端口到容器的80端口). 而在host主机上运行的nginx配置反向代理功能,同时在host上创建一个虚拟IP:192.168.0.110,这样在配置反向代理的时候就可以使用 192.168.0.110 来代替localhost 具体步骤如下:

  1. 在server上,创建一个虚拟IP:192.168.0.110/24 .
[root@instance-6p8qz002 ~]# ifconfig eth0:0 192.168.0.110  netmask 255.255.255.0 up
[root@instance-6p8qz002 ~]# ping -c 2 192.168.0.110
PING 192.168.0.110 (192.168.0.110) 56(84) bytes of data.
64 bytes from 192.168.0.110: icmp_seq=1 ttl=64 time=0.048 ms
64 bytes from 192.168.0.110: icmp_seq=2 ttl=64 time=0.066 ms

--- 192.168.0.110 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.048/0.057/0.066/0.009 ms
[root@instance-6p8qz002 ~]#
  1. 配置host主机上的Nginx,开启反向代理功能, 修改/etc/nginx.conf 文件,内容如下:
......
      location / {
      proxy_pass                          http://192.168.0.110:8080/;
      proxy_set_header  X-Real-IP         $remote_addr;
      proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
        }
......
#启动host上的nginx服务
[root@instance-6p8qz002 ~]# systemctl start nginx.service
[root@instance-6p8qz002 ~]#
  1. 对于nginx容器,不需要反向代理的配置,但是要保持log 记录的相关配置,和上面 ”场景一“ 的配置一致:
http {
......
    log_format  main  'Parameter remote_addr : $remote_addr\n'
                      'Parameter http_x_forwarded_for: $http_x_forwarded_for\n'
                      'Parameter http_x_real_ip : $http_x_real_ip';
    access_log  /var/log/nginx/access.log  main;
......
}
#启动nginx 容器
[root@instance-6p8qz002 my_project]# docker run -d --rm   -p 8080:8080  -v /root/my_project/nginx/:/etc/nginx -v /tmp/nginx/log:/var/log/nginx/   --name my_nginx  nginx
56a543b71e7c157d9dc736f8c1d3481d31e21db03575d51eadd6ebe980de282d
[root@instance-6p8qz002 my_project]# 
  1. 通过浏览器访问,查看log记录,内容如下:
[root@instance-6p8qz002 log]# tail -n0 -f access.log
Parameter remote_addr: 192.168.0.110
Parameter http_x_forwarded_for: 119.123.134.165
Parameter http_x_real_ip: 119.123.134.165

根据我们前面的理解,remote_addr的值应该是:client的public IP才对,也就是119.123.134.165, 因为我们这里只有这一个reverse proxy. 那为什么实际是 : 192.168.0.110 呢? 因为在docker map host端口到container的端口的时候,其实是一个http请求的转发,所以host_ip:port ---- container: port 之间的关系,就相当于client--server 的直连关系。 http_x_forwarded_for,http_x_real_ip 的值和前面的理论值是一致的,这里不做过多解释; .

场景三:多个reverse proxy的讨论 这里采用三个reverse proxy来作代表多个proxy的情况,其部署环境如下:

  1. 在本地的centos(192.168.0.110) 中安装Nginx,并配置反向代理功能,转发http请求到远端的服务器 remote_host 的8080端口. 对应后面的配置步骤A.
  2. 在远端的服务器remote_host上安装Nginx, 并配置反向代理功能,从8080端口接收请求并转发到该host的Nginx 容器A的8080端口; 在下面的配置中,从8080端口接收到请求后,转发到该host的8088端口,而并不是直接转发到Nginx容器A的8080端口,这是因为:host的8088端口mapping 到了容器A的8080端口, 对应的配置为后面的步骤B.
  3. 在服务器remote_host的容器A(Nginx容器: 172.26.16.8) 上配置反向代理功能,转发请求到另一个Nginx容器B(172.26.16.4). 容器A和B处于同一个子网中,所以可以直接转发,对应后面的配置步骤C.
  4. 服务器remote_host的容器B提供真正的http 服务,该容器不进行端口映射,也没有反向代理的配置,但是需要日志配置 ,我们需要通过日志来验证结果。配置步骤为D.

关键的配置过程如下: A. 在本地的centos中,对nginx做如下的配置:

#监听端口采用默认的80端口;
......
#remotee_host 对应的IP写在/etc/hosts中
    location / {
      proxy_pass                          http://remote_host:8080/;
      proxy_set_header  X-Real-IP         $remote_addr;
      proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
    }
......
[root@localhost conf.d]# systemctl restart nginx.service
[root@localhost conf.d]#

B. 在remote_host中,做如下的配置:

   server {
       listen       8080 default_server;
......
  location / {
  proxy_pass                          http://localhost:8088/;
  proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
       }
...
}
......
[root@instance-6p8qz002 nginx]# systemctl restart nginx.service
[root@instance-6p8qz002 nginx]#

C. 在容器A(172.26.16.8) 中配置 nginx反向代理,转发请求到容器B(172.26.16.4)中. 并启动容器A. 这里要注意以下的几点: 1). 在nginx容器中,upstream不能使用ip地址,必须使用name,为了能够实现name到地址的解析,所以把host主机的/etc/hosts mapping为container A中相应文件, 如下的配置中,主机的/etc/hosts中有:"172.26.16.4 container_b" 之间的映射关系 2). 要使用自定义IP,必须要使用自定义的docker 网络

......
    server {
    listen 8080;
......
   location / {
   proxy_pass                          http://container_b:8080/;
   proxy_set_header  X-Forwarded-For   $proxy_add_x_forwarded_for;
        }
......
}
......
#启动容器A的步骤如下,命令如下:
[root@instance-6p8qz002 nginx_b]# docker network create -d bridge --subnet=172.26.0.0/16 --ip-range=172.26.16.0/24    mynetwork
[root@instance-6p8qz002 nginx_b]# docker run -d --rm --network="mynetwork" --ip 172.26.16.8  -p 8088:8080 -v /root/my_project/nginx_a/:/etc/nginx -v /etc/hosts:/etc/hosts   --name nginx_a   nginx

D. 通过容器B提供http服务,这里没有反向代理的配置,其监听端口为8080,不做host到容器B的端口映射. 虽然这里没有反向代理的配置,但是需要配置log记录,同时需要把容器中的log目录 mapping 到host主机的特定目录 ;

#配置监听端口为8080. 配置参数忽略
access_log  /var/log/nginx/access.log  main;  #配置log. 
......
    log_format  main  'Parameter remote_addr : $remote_addr\n'
                      'Parameter http_x_forwarded_for: $http_x_forwarded_for\n'
                      'Parameter http_x_real_ip : $http_x_real_ip';
......
#启动容器B
[root@instance-6p8qz002 my_project]# docker run -d --rm  --network="mynetwork" --ip 172.26.16.4   -v /root/my_project/nginx/:/etc/nginx -v /tmp/nginx/log:/var/log/nginx/   --name nginx_b  nginx

在这个过程中用到的端口如下: 1.centos 主机192.168.0.110的80端口,提供用户访问接口; 2.remote_host的8080端口,用于接收centos转发过来的请求; 3.remote_host的8088端口,用于接收remote_host的8080端口转发过来的请求; 4.启动容器A(172.26.16.8)时,要mapping port 8088:8080,也就是指定-p 参数; 5.容器A的8080端口转发到容器B(172.26.16.4)的8080端口, 容器; 验证结果: 首先在remote_host上用命令: tail -n0 -f /tmp/nginx/log/access.log, 然后使用浏览器访问192.168.0.110, tail的结果如下:

[root@instance-6p8qz002 nginx]# tail -n0 -f /tmp/nginx/log/access.log
Parameter remote_addr: 172.26.16.8
Parameter http_x_forwarded_for: 192.168.0.101, 119.123.132.73, 172.26.16.0
Parameter http_x_real_ip: 192.168.0.101

对于结果的分析如下: remote_addr: log 是在172.26.16.4上产生的,其前一级为容器A(172.26.16.8), 所以remote_addr的地址是 172.26.16.8 http_x_real_ip: 就是浏览器设备对应的地址,在本实验中,就是本机的IP地址:192.168.0.101 ,与理论值一致; http_x_forwarded_for: 第一次反向代理是发生在访问192.168.0.110时候,被代理的客户端为192.168.0.101; 第二次反向代理是remote_host上发生的,被代理的请求来自Public的IP:119.123.132.73 第三次反向代理是容器A(172.26.16.8)上配置的,其直接请求docker 中的网桥转发的,但是为什么会是 172.26.16.0 呢?小弟不才,不是很明白这里的原因,希望读者你能够帮忙解答一二 .

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Linux中find命令的点滴积累

    find 命令在Linux中的作用非常强大,对于初学者来说,可能有很多的参数并不能很熟练的使用,导致无法充分发挥find的强大作用;本文对部分参数做初步的探索:

    qsjs
  • nginx反向代理+http user 认证访问 私有registry

    利用nginx做反向代理,从而实现对registry的访问;而nginx作为反向代理来使用在实际情况中非常多见,并且还支持基本的用户权限认证。 本节讲述如何用...

    qsjs
  • awk数组的两条实用技巧(去重,统计)

    说到数组,一般下标都是从0开始,然后递增;而awk的数组的下标可以是 任意内容,比如下面的例子:

    qsjs
  • nginx 日志切割

    1.nginx_log_rotate.sh文件 #nginx日志切割脚本 #author: joshau317 #!/bin/bash #1.设置日志文件存放...

    joshua317
  • 三、实现第一个HelloWorld

    1、新建一个Controller类,并按照如下格式进行编写即可通过http://localhost:8080/进行访问到。

    cn華少
  • 013.Nginx动静分离

    为了提高网站的响应速度,减轻程序服务器(Tomcat,Jboss等)的负载,对于静态资源,如图片、js、css等文件,可以在反向代理服务器中进行缓存,这样浏览器...

    木二
  • 面试算法:在循环排序数组中快速查找第k小的值d

    望月从良
  • 走进Java接口测试之读取配置文件

    但在大部分用例开发环境下,添加额外配置是无所避免的,比如自定义应用端口号、服务地址、数据库的配置等,都或多或少的需要一些外部的配置项等。

    高楼Zee
  • python笔记:反射

    超级大猪
  • 动态 | 滴滴成立美国研究院,发力大数据安全与智能驾驶

    AI科技评论消息,滴滴出行于3月9日正式宣布在加利福尼亚硅谷成立滴滴美国研究院,以吸引全球优秀的科研人才,致力于交通产业相关创新技术的研究。 研究院位于加利福尼...

    AI科技评论

扫码关注云+社区

领取腾讯云代金券