Nginx之Nginx反代

1 反向代理相关概念

什么是反向代理?
        根据上图我们看出,反向代理服务器是位于client与真实server之间的一台代理服务,对于用户而言,proxy server就是真实的server服务器,用户获取的是proxy server的ip,而不是后端server的服务器ip。

过程:
       例如:www.test.com就是上图的架构,我要访问www.test.com/test.html
       1. client发起请求访问www.test.com/test.html,通过解析得到proxy server的ip,向proxy server发起http请求
       2.proxy server收到client请求(假设proxy server没有缓存你的数据),发现本地没有缓存test.html,向后端server发起请求转发
       3.后端server收到请求并且响应请求,将数据返回给proxy server
       4.proxy server(假设做了缓存配置)返回响应给client,并且自己缓存一份。
       注:在整个过程中,proxy server自己不生产数据,只缓存数据和转发请求,所以可以支持很高的并发,因为处理请求是消耗系统性能的,专业的事,给专业服务器去做即可。但是proxy server一定得有公网ip,支持http及https,后端server建议不要给公网ip,降低风险,就算有攻击也是代理在扛着。并且proxy server 及后端server 可以是一台,也可以是多台,主要看需求了。

 2 实现反向代理功能需要的模块(是基于Nginx的反向代理)

有2个模块:ngx_stream_proxy_module 及 ngx_http_proxy_module  都是Nginx内置模块,不需要额外进行编译,下面介绍下一些需要用到的功能,详细的功能请参考官网(简单介绍一下)。

ngx_stream_proxy_module 用于定义可由proxy_pass、fastcgi_pass、uwsgi_pass、scgi_pass和memcached_pass指令引用部署服务器群,一般在负载均衡方面用的多。下面功能的话主要强调在代理这一方面,一般应用于server段:

官方链接:http://nginx.org/en/docs/stream/ngx_stream_proxy_module.html

例如:

server {
    listen 127.0.0.1:12345;
    proxy_pass 127.0.0.1:8080;
}

ngx_http_proxy_module 也是提供代理功能的,提供允许将请求传递到另外一台服务,也就是请求转发。一般做代理是基本应用于此模块。一般应用于location段。

官方链接:http://nginx.org/en/docs/http/ngx_http_proxy_module.html

示例:

location / {
    proxy_pass       http://localhost:8000;
    proxy_set_header Host      $host;
    proxy_set_header X-Real-IP $remote_addr;
}

3 配置反向代理

当前架构:1台client 1台proxy server 1台后端server   注:默认是安装好了Nginx,申请了证书,关闭防火墙及关闭selinux。

3.1 配置后端主机(默认是已经安装好了Nginx服务的)

日志格式(查看下文日志的时候请参考我的日志格式,不然会看出问题的):

log_format jflog '$remote_addr | $remote_user | $time_local | $request | $status | '
    '$bytes_sent | $body_bytes_sent | $host | $http_referer | $http_user_agent | '
    '$upstream_addr | $scheme | $http_x_forwarded_for | $request_time | $upstream_response_time';

注:配置后端server,使你的后端服务器支持http及https

3.11 配置10.28.88.188 nginx 虚拟主机

#配置后端虚拟机主机
$ vim /usr/local/nginx/conf/vhost/test.conf
server {
    listen 80;
    listen 443 ssl;             #你的域名得有https证书才能开启443端口,没有的话则不配置https
    server_name www.test.com;   #域名(选择你有证书的域名)
    root   /data/www/;            #然后其他配置就是常规的https配置
    index  index.html index.php;

    ssl_certificate       /usr/local/nginx/conf/cert/www.test.com.crt;
    ssl_certificate_key   /usr/local/nginx/conf/cert/www.test.com.key;
    ssl_ciphers "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;

    access_log /data/logs/www/test_ssl.log jflog;
}

#重新加载nginx
$ /usr/local/nginx/sbin/nginx -t
$ /usr/local/nginx/sbin/nginx -s reload

3.12 在 10.28.88.188 创建测试文件并测试

#编辑hosts,让当前主机可以识别你刚才配置的内容
$ vim /etc/hosts
127.0.0.1   www.test.com

#创建测试文件并且授权
$ vim /data/www/test.html
test
$ chown www.www /data/www/ -R

#测试  
$ curl www.test.com/test.html
test
$ curl https://www.test.com/test.html
test
注:测试没有问题,那么当前后端既支持http也支持https.

3.2 配置proxy server,使其支持HTTP及HTTPS转发

3.21 在10.28.88.199配置代理文件

#创建proxy.conf文件(把代理相关选项,参数都放到这里面,好方面其他文件调用)
$ vim /usr/local/nginx/conf/proxy.conf

proxy_connect_timeout 300s;
proxy_send_timeout   900;
proxy_read_timeout   900;
proxy_buffer_size    32k;
proxy_buffers     4 32k;
proxy_busy_buffers_size 64k;
proxy_redirect     off;
proxy_hide_header  Vary;
proxy_set_header   Accept-Encoding '';
proxy_set_header   Host   $host;
proxy_set_header   Referer $http_referer;
proxy_set_header   Cookie $http_cookie;
proxy_set_header   X-Real-IP  $remote_addr;
proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_next_upstream http_500 http_502 http_503 http_504 error timeout invalid_header;
#proxy_next_upstream http_502 http_503 http_504 error timeout invalid_header;
proxy_intercept_errors on;
proxy_redirect default;
#proxy_hide_header "Cache-Control";
#proxy_hide_header "Set-Cookie";
#proxy_hide_header "Pragma";
#proxy_hide_header "X-Powered-By";

3.22 在10.28.88.199配置代理转发 

#配置代理转发
$ vim  /usr/local/nginx/conf/vhost/test.conf
upstream test.com {
    #如果有多个后端则在这里定义多个server,可以通过权重,ip哈希等算法实现负载均衡。
    server   10.28.88.106;     
}

server {
    listen 80;
    listen 443;
    server_name www.test.com;

    include proxy.conf;

    ssl_certificate         /usr/local/nginx/conf/cert/www.test.com.crt;
    ssl_certificate_key     /usr/local/nginx/conf/cert/www.test.com.key;
    ssl_protocols           TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers             "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";

    #这里就是实现代理的关键部分
    location / {                
         inlcude proxy.conf;      #如果你不想传太多的header信息,可在这通过set自定义header信息
         proxy_pass  http://test.com;
    }

     access_log /data/logs/www/test.ssl.log jflog;
}  

#重新加载nginx
$ /usr/local/nginx/sbin/nginx -t
$ /usr/local/nginx/sbin/nginx -s reload

3.23 在10.28.88.199 进行测试

#绑host
$ vim /etc/hosts
127.0.0.1    www.test.com

#测试
$ ip a | grep inet | grep -v inet6 | grep -w enp0s3 | awk '{print $2}' 
10.28.88.199/24
$ curl www.test.com/test.html
test
$ curl https://www.test.com/test.html
test

#查看日志
##在proxy server查看
$ ip a | grep inet | grep -v inet6 | grep -w enp0s3 | awk '{print $2}' 
10.28.88.199/24

$ tail -2  /data/logs/www/test.com.ssl.log
127.0.0.1 | - | 10/Dec/2019:03:05:57 -0500 | GET /test.html HTTP/1.1 | 200 | 232 | 5 | www.test.com | - | curl/7.29.0 | 10.28.88.106:443 | http | - | 0.014 | 0.014
127.0.0.1 | - | 10/Dec/2019:03:06:11 -0500 | GET /test.html HTTP/1.1 | 200 | 232 | 5 | www.test.com | - | curl/7.29.0 | 10.28.88.106:443 | https | - | 0.003 | 0.004
注:此时,当前代理作为client总共发起2次请求,一次是http,一次是https,通过日志发现是通过10.28.88.106:443端口转发给后端server,完全符合我们的proxy_pass设置


##在后端server查看
$ ip a | grep inet | grep -v inet6 | grep -w enp0s3 | awk '{print $2}'
10.28.88.106/21

$ tail -2 /data/logs/www/test.com.ssl.log
10.28.88.199 | - | 10/Dec/2019:03:06:13 -0500 | GET /test.html HTTP/1.0 | 200 | 227 | 5 | www.test.com | - | curl/7.29.0 | - | https | 127.0.0.1 | 0.000 | -
10.28.88.199 | - | 10/Dec/2019:03:10:03 -0500 | GET /test.html HTTP/1.0 | 200 | 227 | 5 | www.test.com | - | curl/7.29.0 | - | https | 127.0.0.1 | 0.000 | -
注:当前机器为后端server,通过日志显示是由proxy server通过https协议发起了2次请求,并且返回响应


总结:当你proxy server设置proxy_pass指定以啥协议转发请求时,无论你请求的内容是https还是http,都会以固定的方式转发。

3.3 client 操作

#本机mac作为纯粹的client,只要做一个操作即可测试,那就绑定hosts
#绑hosts
ytsdeMacBook-Air:~$vim /etc/hosts 
10.28.88.199 www.test.com

#测试
ytsdeMacBook-Air:~$curl www.test.com/test.html
test
ytsdeMacBook-Air:~$curl https://www.test.com/test.html
test

#查看日志:
#proxy server 
$ tail -2  /data/logs/www/test.com.ssl.log
10.28.89.104 | - | 10/Dec/2019:03:30:52 -0500 | GET /test.html HTTP/1.1 | 200 | 232 | 5 | www.test.com | - | curl/7.54.0 | 10.28.88.106:443 | http | - | 0.006 | 0.007
10.28.89.104 | - | 10/Dec/2019:03:30:58 -0500 | GET /test.html HTTP/1.1 | 200 | 232 | 5 | www.test.com | - | curl/7.54.0 | 10.28.88.106:443 | https | - | 0.003 | 0.003
注:客户ip 为10.28.89.104 是我mac的ip,后端服务器地址为10.28.88.106 也没有任何问题
远程客户ip是由$remote_addr获取
后端服务器地址是由$upstream_addr获取


#后端server
$ tail -2 /data/logs/www/test.com.ssl.log
10.28.88.199 | - | 10/Dec/2019:03:30:53 -0500 | GET /test.html HTTP/1.0 | 200 | 227 | 5 | www.test.com | - | curl/7.54.0 | - | https | 10.28.89.104 | 0.000 | -
10.28.88.199 | - | 10/Dec/2019:03:31:00 -0500 | GET /test.html HTTP/1.0 | 200 | 227 | 5 | www.test.com | - | curl/7.54.0 | - | https | 10.28.89.104 | 0.000 | -
注:客户ip 为10.28.88.199, 获取客户端真实ip 10.28.89.104 是我的mac ip 没有任何问题
客户ip是由$remote_addr获取
客户真实ip是由$http_x_forwarded_for获取

总结:根据客户端测试的结果完全符合我们的预期,至于ip获取不同,请看我的日志格式

4.相关配置文件及参数介绍

4.1 日志格式

日志格式请参考我的另一章节专门关于日志的介绍:https://blog.csdn.net/yts1115084429/article/details/102327761

4.2 proxy.conf

$ vim /usr/local/nginx/conf/proxy.conf

#设置proxy server与后端的连接超时时间
proxy_connect_timeout 300s;      #设置跟后端连接的超时时间
proxy_send_timeout   900;        #设置跟后端进行请求传输的超时时间,仅用于2次连续写操作
proxy_read_timeout   900         #设置跟后端进行响应读取的超时时间,仅用于2次连续读操作

#设置缓冲功能
proxy_buffer_size    32k;        #设置单个缓冲区大小
proxy_buffers     4 32k;         #最多用几个缓冲区快及缓冲区来处理单一请求
proxy_busy_buffers_size 64k;    #设置最大单个缓冲区大下 (用于请求繁忙时) 
proxy_buffering on

#设置代理缓存功能(源配置文件没有的,可以加可以不加)
proxy_cache cache-v;        #定义名字缓存系统
proxy_cache_path /data/nginx/cache levels=1:2 keys_zone=one:10m;
proxy_cache_valid  200 304 10m; #将http code为200,304缓存10天
proxy_cache_key $uri; #指定缓存唯一key,缓存通过此keyJinxhash存取

#proxy_set_header 主要用于设置proxy server要传递的header信息
proxy_set_header   Accept-Encoding ' ';  #字段值为 ' ' 代表此header信息将不会被proxy server传递出去
proxy_set_header   Host   $host;  #
proxy_set_header   Referer $http_referer;
proxy_set_header   Cookie $http_cookie;
proxy_set_header   X-Real-IP  $remote_addr;
proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;

#其它设置
proxy_redirect     off;          #主要用于内容替换,类似于rewrite
proxy_hide_header  Vary;         #隐藏vary头部信息 
proxy_next_upstream http_500 http_502 http_503 http_504 error timeout invalid_header;  #当出现这些错误时,会将请求自动发给下一个服务器,可以提升容错率。
proxy_intercept_errors on; ; #获得后端服务器响应后,可以根据响应状态码的值进行拦截错误处理,与error_page 指令相互结合。用在访问上游服务器出现错误的情况下。

4.3 proxy server的test.conf

$ vim  /usr/local/nginx/conf/vhost/test.conf
server {
    listen 80;
    listen 443;
    server_name www.test.com;

    #这个文件就是单独写的存放代理参数的文件,你可以放在server,也可以放在location中
    include proxy.conf;    #这样写的话,你的文件得放在conf目录下

    #ssl证书配置
    ssl_certificate         /usr/local/nginx/conf/cert/www.test.com.crt;
    ssl_certificate_key     /usr/local/nginx/conf/cert/www.test.com.key;
    ssl_protocols           TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers             "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";

    #代理转发
    location / {
         proxy_pass              https://10.28.88.106;
    }

    #日志,建议加上,方便查看
     access_log /data/logs/www/test.ssl.log jflog;
}  

注:上面proxy server虚拟机主机的配置是不是跟后端server的test.conf配置文件很像,但是还是有点区别滴。

证书:证书看起来不是一模一样么,的确是一模一样,但是与后端的证书的没有任何关系,你可以把它看成一个单独的证书配置,当前ssl配置只对当前虚拟主机负责,相当于重新配置了一个https。

当用户发起https请求,是请求到proxy server,不是请求到后端,如果你的proxy server不支持https,则无法响应用户https请求,对于后端而言,你的proxy server就是client,只需要响应proxy server的请求即可。

根据上诉所说,后端配不配制https都无所谓了,大致意思是这样的,但是在生产环境,能配置https就配置https,从安全系数方面来说,对信息进行加密,提升安全等级,万一哪天你的内网被入侵了,最关键是不需要加成本,何乐而不为了。

location模块:在后端server的location是具体定义某个处理请求功能,然而这里的location就只提供请求转发的功能。

proxy.conf在后端是不需要添加的,但是这里必须添加,因为那些参数只对当前代理生效。 

proxy_pass,提供转发功能,支持http及https,proxy server获取的数据都是通过此模块提供的,获取原始数据。 

有proxy server,返回给用户数据的协议类型是取决于proxy server支持协议类型而不是后端server支持类型,反向代理支持https,那么就可以响应client https请求。

简单流程:client请求数据—>proxy server返回用户响应<—后端 server提供数据。

至于后端server的配置就不讲述了,配置过Nginx的基本都看的明白

如果想对反代了解更深入,那就得去看各个指令的具体用法及适用场景,也比较复杂,大家可以找博文或者去官网进行查看。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值