当前位置:首页 > 技术文章 > 正文内容

nginx实战之反向代理

arlanguage4个月前 (01-05)技术文章25

1、反向代理

所谓反向代理就是nginx接受到请求后,将请求转发给内部的一台服务器处理,比如我们启动了一个tomcat是8081端口,但是我们防火墙不会开放8081端口,只会开放nginx的80端口,那么我们需要再nginx上进行反向代理配置,让到80端口的请求转发给8081端口处理,这样安全性也有很大的提高,并且后续可以进行负载均衡:80端口进来,从代理的多台服务器按策略选一台处理。

1.1、8081端口服务搭建

我们这里就不启动tomcat来模拟服务了,直接在nginx上配置个8081端口的server即可,nginx配置文件做如下处理

server {
        listen       8081;
        server_name  localhost;
        location / {
            root   html;
            index  index8081.html index.htm;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

这里的意思是,请求从8081进来,会返回index8081.html的页面,这个页面会在nginx目录下面的html里面,内容如下

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
    html { color-scheme: light dark; }
    body { width: 35em; margin: 0 auto;
    font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
    <h1>Welcome to 8081!</h1>
</body>
</html>

到这里就相当于有一个新的服务了。

1.2、nginx反向代理配置

下面我们来配置负载均衡,我们在nginx.conf的http配置里面新增upstream.

 upstream first { 
   server  localhost:8081; 
}

然后,在80的server进行代理配置

server {
        listen       80;
        server_name  localhost;
        location / {
        #反向代理配置
            proxy_pass         http://first; 
            proxy_set_header   Host             $host; 
            proxy_set_header   X-Real-IP        $remote_addr; 
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        }
    }

1.3、重新启动nginx

我们可以先用-t命令校验下配置文件是否正确

./nginx -t

检查正确后,进行重新加载

./nginx -s reload

1.4、访问测试

我们访问80端口,然后可以看到返回了index8081.html的页面内容,表面反向代理成功。

1.5、proxy_set_header

我们看到,反向代理设置的时候,有进行proxy_set_header设置,那这个的作用是什么呢?

即允许重新定义或添加字段传递给代理服务器的请求头,简而言之,proxy_set_header 就是可设置请求头-并将头信息传递到服务器端,不属于请求头的参数中也需要传递时,重定义下即可!

主要有三个参数需要设置

Host

若客户端发过来的请求header中有HOST这个字段,$http_host和$host表示的就是原始请求

X-Real-IP

是指客户端的真实IP,如果设置了$remote_addr这个值,后端服务器就能获取到客户端的真实IP

X-Forwarded-For

这个变量的值有$proxy_add_x_forwarded_for,可以真实的显示出客户端原始ip。

我们这里来测试下

环境搭建

在本机搭建一个springboot应用,springboot应用搭建方法参考:从官网开始用IDEA在JDK1.8环境搭建springboot2.7.14项目,然后代码如下

@RestController
public class DemoController {
    @GetMapping("/hello")
    public Map<String,Object> hello(HttpServletRequest request){
        Map<String,Object> result = new TreeMap<String,Object>();
        result.put("hello","Hello World");
        String scheme = request.getScheme();
        String xForwardedFor = request.getHeader("X-Forwarded-For");
        String xRealIp = request.getHeader("X-Real-IP");
        String host = request.getHeader("Host");
        String serverName = request.getServerName();
        int serverPort = request.getServerPort();
        String remoteName = request.getRemoteAddr();
        int remotePort = request.getRemotePort();
        result.put("scheme",scheme);
        result.put("serverName",serverName);
        result.put("serverPort",serverPort);
        result.put("remoteName",remoteName);
        result.put("remotePort",remotePort);
        result.put("xForwardedFor",xForwardedFor);
        result.put("xRealIp",xRealIp);
        result.put("host",host);
        return result;
    }
}

我本机的ip为:192.168.192.1
nginx所在的ip:192.168.192.11

nginx的反向代理的配置为

upstream first { 
   server  192.168.192.1:8080; 
}
server {
        listen       80;
        server_name  localhost;
        location / {
            proxy_pass         http://first; 
            #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暴露的80服务就是反向代理到我本机启动的springboot应用。下面我们来测试proxy_set_header的作用

不配置proxy_set_header的测试

我们上面是把proxy_set_header都注释了,此时在浏览器上访问
http://192.168.192.11/hello
返回了

{"hello":"Hello World","host":"first","remoteName":"192.168.192.11","remotePort":35058,"scheme":"http","serverName":"first","serverPort":80,"xForwardedFor":null,"xRealIp":null}

可以看到完全没有拿到任何客户端的信息.

配置proxy_set_header的测试

server {
        listen       80;
        server_name  localhost;
        location / {
            proxy_pass         http://first; 
            proxy_set_header   Host             $host; 
            proxy_set_header   X-Real-IP        $remote_addr; 
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}

在浏览器上访问
http://192.168.192.11/hello
返回了

{"hello":"Hello World","host":"192.168.192.11","remoteName":"192.168.192.11","remotePort":35060,"scheme":"http","serverName":"192.168.192.11","serverPort":80,"xForwardedFor":"192.168.192.1","xRealIp":"192.168.192.1"}

request.getRemoteAddr():获取的永远都是代理对象的IP
X-Forwarded-For和X-Real-IP:都获取了客户端的真实IP

X-Forwarded-For和X-Real-IP有什么区别呢

我们上面的例子发现,这两个获取的都是客户端的真实IP地址,其实如果只有一个反向代理服务器,那结果都是一样的,但是如果有多个,这里可以就用一个nginx来模拟一下。配置如下

我们首先在nginx配置一个服务,代理到我们的springboot应用.

upstream second { 
   server  192.168.192.1:8080; 
}
server {
        listen       8081;
        server_name  localhost;
        location / {
            proxy_pass         http://second; 
            proxy_set_header   Host             $http_host; 
            proxy_set_header   X-Real-IP        $remote_addr; 
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        }
        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }

这里相当于我们的应用被一个nginx服务器代理了,端口是8081,我们再配置一个80端口代理到8081,就模拟了两台代理服务器的情况

upstream first { 
   server  localhost:8081; 
}
server {
        listen       80;
        server_name  localhost;
        location / {
            proxy_pass         http://first; 
            proxy_set_header   Host             $host; 
            proxy_set_header   X-Real-IP        $remote_addr; 
            proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        }
}

我们再尝试在本机的浏览器请求:http://192.168.192.11/hello,返回了

{"hello":"Hello World","host":"192.168.192.11","remoteName":"192.168.192.11","remotePort":35086,"scheme":"http","serverName":"192.168.192.11","serverPort":80,"xForwardedFor":"192.168.192.1, 127.0.0.1","xRealIp":"127.0.0.1"}

可以看到X-Real-IP获取的就不是客户端的地址了,而是第一次代理发起的地址,但是我们的X-Forwarded-For却有全部的客户端IP地址,我们想要获取真实客户端,只需要获取X-Forwarded-For第一个即可。

总结:X-Forwarded-For记录服务器的地址,会把记录添加到结尾,X-Real-IP用来记录服务器的地址,它不把记录添加到结尾,而是直接替换。所以用X-Forwarded-For就不会错。

扫描二维码推送至手机访问。

版权声明:本文由AR编程网发布,如需转载请注明出处。

本文链接:http://www.arlanguage.com/post/612.html

分享给朋友:

“nginx实战之反向代理” 的相关文章

蓝易云 - Nginx 设置禁用 OPTIONS 请求以及允许跨域教程!

在Nginx中禁用OPTIONS请求并允许跨域的教程在现代Web开发中,跨域资源共享(CORS)和处理HTTP请求方法(如OPTIONS)是常见需求。本文将详细介绍如何在Nginx中配置以禁用OPTIONS请求并允许跨域请求。云服务器,高防服务器就选蓝易云,头条搜索:蓝易云云服务器,高防服务器就选蓝...

Linux中内网或者没网时安装软件的两种方式

写在前面对于可以连接外网的服务器装软件,只要配置yum源就可以随便使用了但是对于内网来说,不能连接外网,一般情况下,管控平台只有上传的权限。尤其是一些涉密的岗位,比如电力,电信,军工之类的。今天和小伙伴聊聊内网服务器如何安装软件的问题。可事实是,唯恐暴露才华不足的卑怯的畏惧,和厌恶钻研刻苦的惰怠,就...

logstash+ES+kibana搭建日志收集分析系统

日志监控和分析在保障业务稳定运行时,起到了很重要的作用,不过一般情况下日志都分散在各个生产服务器,且开发人员无法登陆生产服务器,这时候就需要一个集中式的日志收集装置,对日志中的关键字进行监控,触发异常时进行报警,并且开发人员能够查看相关日志。logstash+elasticsearch+kibana...

解决Apache 2.4+PHP5.6不支持CURL

跑一个demo,突然发现,服务器上最普通的Apache 2.4+PHP5.6组合,不支持curl,报告没有curl_init函数;而php.ini里面已经打开了php_curl.dll,而且php -i的输出是正常的,说明curl是可以执行的。折腾了半天百思不得其解,最后索性把php5.6、apac...

php培训都学什么?有哪些课程?

PHP入门虽然比较容易简单,但是对于零基础学员来讲,想要学到精髓,并不是一件容易的事情,越到后面学起来越累,因此,最快最便捷的方法就是参加培训,不仅可以快速掌握入门,还能够学到精髓之处,那么PHP培训都有哪些课程?下面我们以六星教育的php培训课程为例来为大家讲解:第一阶段:动态网站开发的三个方面1...

网页上出现503 Service Unavailable Error应该如何处理?

本头条号每天坚持更新原创干货技术文章,欢迎关注本头条号"Linux学习教程",公众号名称“Linux入门学习教程"。如需学习视频,请复制以下信息到手机浏览器或电脑浏览器上:zcwyou.com1. 前言在浏览网页时,最常见的错误之一是“503 Service Unavaila...