一.proxy_set_header的设置:
1.proxy_set_header Host:
①
proxy_set_header Host $host;
作用是把原http请求的Header中的Host字段也放到转发的请求中,如果没有这一行,nginx转发的请求header里面就不会有Host字段,而服务器是靠这个Host值来区分我们请求的是nage域名资源的
![](https://lcj.ink/wp-content/uploads/2022/05/图片.png)
代理的后端服务器可以通过Host头得知用户访问的真正的域名,如果不设置,则得到代理服务器(nginx)的IP,这样对于动态拼接的url,后端服务器能在页面返回正确的url
注意,$host中仅仅包含域名或ip,不会包含端口,如果此时代码中有重定向路由,那么重定向时就会丢失端口信息,导致404
②
proxy_set_header Host $http_host;
浏览器直接访问访问nginx,获取到的Host包含浏览器请求的IP和端口
![](https://lcj.ink/wp-content/uploads/2022/05/12475671-69ccf4b82a3a35b8.webp)
③
proxy_set_header Host $host:$proxy_port;
浏览器直接访问nginx,获取到的Host是$host:$proxy_port,也就是IP:端口
2.proxy_set_header X-Real-IP:
proxy_set_header X-Real-IP $remote_addr;
使web端获得用户真实的IP地址,
注意:$remote_addr只能获取到与服务器本身直连的上层请求ip,所以设置$remote_addr一般都是设置在第一个代理上面,当一个请求通过多个代理服务器时,用户的IP会被代理服务器的IP覆盖
// 在第一个代理服务器中设置 set x_real_ip = $remote_addr // 最后一个代理服务器中获取 $x_real_ip = IP1
但是问题是,有时候是通过 cdn 访问过来的,那么后面web服务器获取到的永远都是 cdn 的 ip 而非真实用户 ip,这个时候就需要用到X-Forwarded-For——这个变量的意思就像是链路反追踪,从客户的真实ip为起点,穿过多层级的proxy,最终到达web服务器,都会记录下来,所以在获取用户真实ip时,一般就可以设置成:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
这样就能获取所有的代理ip和客户ip。
3.proxy_set_header X-Forwarded-For:
X-Forwarded-For 变量,这是一个squid开发的,用于识别通过HTTP代理或负载平衡器原始IP一个连接到Web服务器的客户机地址的非rfc标准,如果有做X-Forwarded-For设置的话,每次经过proxy转发都会有记录,格式就是 client1,proxy1,proxy2,以逗号隔开各个地址,由于它是非rfc标准,所以默认是没有的,需要强制添加。
在默认情况下经过proxy转发的请求,在后端看来远程地址都是proxy端的ip 。也就是说在默认情况下我们使用request.getAttribute(“X-Forwarded-For”)获取不到用户的ip,如果我们想要通过这个变量获得用户的ip,我们需要自己在nginx添加配置:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
意思是增加一个$proxy_add_x_forwarded_for到X-Forwarded-For里去,注意是增加,而不是覆盖,当然由于默认的X-Forwarded-For值是空的,所以我们总感觉X-Forwarded-For的值就等于$proxy_add_x_forwarded_for的值,实际上当你搭建两台nginx在不同的ip上,并且都使用了这段配置,那你会发现在web服务器端通过request.getAttribute(“X-Forwarded-For”)获得的将会是客户端ip和第一台nginx的ip。
$proxy_add_x_forwarded_for:
$proxy_add_x_forwarded_for
变量包含客户端请求头中的 X-Forwarded-For
与 $remote_addr
两部分,他们之间用逗号分开。
在第一台 nginx 中使用:proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;,现在的$proxy_add_x_forwarded_for变量的X-Forwarded-For部分是空的,所以只有$remote_addr,而$remote_addr的值是用户的ip,于是赋值以后,X-Forwarded-For变量的值就是用户的真实的ip地址了。
到了第二台nginx,使用:proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;,现在的$proxy_add_x_forwarded_for变量,X-Forwarded-For部分包含的是用户的真实ip,$remote_addr部分的值是上一台nginx的ip地址,于是通过这个赋值以后现在的X-Forwarded-For的值就变成了“用户的真实ip,第一台nginx的ip”。
获取客户端的IP地址不仅可以通过proxy_set_header X-real-ip $remote_addr;获取到,也可以通过proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
4.proxy_set_header Upgrade:
Upgrade $http_upgrade 和 Connection “upgrade” -如果你的应用程序使用Websockets,则这些header字段是必填字段:
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
WebSocket是HTML5开始提供的一种浏览器与服务器间进行全双工通讯的网络技术。 依靠这种技术可以实现客户端和服务器端的长连接,双向实时通信。
它的最大特点就是,服务器可以主动向客户端推送信息,客户端也可以主动向服务器发送信息, 是真正的双向平等对话,属于服务器推送技术的一种。
其他特点包括
- 建立在 TCP 协议之上,服务器端的实现比较容易。
- 与 HTTP 协议有着良好的兼容性。默认端口也是80和443,并且握手阶段采用 HTTP 协议,因此握手时不容易屏蔽,能通过各种 HTTP 代理服务器。
- 数据格式比较轻量,性能开销小,通信高效。
- 可以发送文本,也可以发送二进制数据。
- 没有同源限制,客户端可以与任意服务器通信。
- 协议标识符是ws(如果加密,则为wss),服务器网址就是 URL。
协议标识符是ws(如果加密,则为wss),服务器网址就是 URL
ws://lcj.ink:80/path
另外客户端不只是浏览器,只要实现了ws或者wss协议的客户端socket都可以和服务器进行通信。
一个典型的Websocket握手:
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
其中的
Upgrade: websocket
Connection: Upgrade
这个就是Websocket的核心了,用来告诉Apache、Nginx等服务器,发起的是Websocket协议,而不是HTTP协议
服务器返回:
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
至此,HTTP已经完成它所有工作了,接下来就是完全按照Websocket协议进行了。
WebSocket协议相比较于HTTP协议,WebSocket成功握手后还可以多次进行通讯,直到连接被关闭。
从上面我们可以看出,websocket的请求头需要有:
Upgrade: websocket
Connection: Upgrade
因此,我们的nginx反向代理时就需要设置成:
proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade";
5.proxy_set_header Accept-Encoding:
![](https://lcj.ink/wp-content/uploads/2022/05/image-7.png)
proxy_set_header Accept-Encoding gzip;
gzip压缩是否启用,除了服务器支持外,客户端也要支持。
当客户端发送Accept-Encoding:gzip这个request header,服务器即认为其能接受gzip压缩,就响应一个Content-Encoding:gzip,并发送压缩内容;
假如客户端没有发送 Accept-Encoding,那么服务器就把源代码原样输出。
二、proxy_http_version:
proxy_http_version 1 – 定义用于代理的HTTP协议版本,默认情况下将其设置为1.0。对于Websocket和 keepalive 连接,你需要使用1.1版。
proxy_http_version 1.1;
三、proxy_redirect:
重定向:
①不进行重定向(禁止重定向):
proxy_redirect off;
参数off将在这个字段中禁止所有的proxy_redirect指令: proxy_redirect off;
②除了off之外,其余暂时用不到,暂时留空
四、proxy_read_timeout:
proxy_read_timeout 300s; #连接成功后,后端服务器响应时间(代理接收超时)
五、proxy_connect_timeout:
proxy_connect_timeout 300s; #nginx和后端服务器连接超时时间(代理连接超时)
六、proxy_pass:
指定反向代理的web服务器,用户发出的请求会被nginx反向代理发送给这个web服务器,这个web服务器发出的信息则又会通过nginx发送给用户
proxy_pass http://127.0.0.1:8080; #反向代理 http://127.0.0.1:8080
举例:
server { listen 80; listen [::]:80; server_name lcj.ink; root /var/www/html; index index.html; location / { proxy_pass http://127.0.0.1:8080; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; } location ^~ /test { proxy_pass http://127.0.0.1:1234; 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; proxy_http_version 1.1; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; proxy_redirect off; proxy_read_timeout 300s; } }
Nginx反向代理grpc:
gRPC必须使用HTTP/2传输数据,支持明文和TLS加密数据,支持流数据的交互。
因为反向代理的是grpc,
proxy_pass 变成了 grpc_pass
proxy_read_timeout 变成了 grpc_read_timeout
proxy_setd_timeout 变成了 grpc_send_timeout
grpc应用的主要就是这三个
①Nginx以不加密的方式代理不加密的grpc服务:
server { listen 80 http2; location / { grpc_pass grpc://localhost:8200; } }
指令grpc_pass用来指定代理的gRPC服务器地址,前缀协议有两种:
grpc://:与gRPC服务器端交互式以明文的方式
grpcs://:与gRPC服务器端交互是以TLS加密的方式
②Nginx与加密方式代理不加密GRPC服务:
server { listen 443 ssl http2; ssl_certificate ssl/server.crt; ssl_certificate_key ssl/server.key; location / { grpc_pass grpc://localhost:8200; } }
Nginx根据路径代理到不同的GRPC服务:
server { listen 80 http2; location /helloworld.Greenter { grpc_pass grpc://192.168.1.11:8200; } location /helloworld.Dispatcher { grpc_pass grpc://192.168.1.12:8200; } }
实例,哪吒探针,用nginx反向代理gRPC端口(支持Cloudflare CDN):
server { listen 443 ssl http2; listen [::]:443 ssl http2; server_name data.example.com; ssl_certificate /data/letsencrypt/fullchain.pem; ssl_certificate /data/letsencrypt/privkey.pem; underscores_in_headers on; location / { grpc_read_timeout 300s; grpc_send_timeout 300s; grpc_pass grpc://localhost:5555; } }
注:
underscores_in_headers默认为off,即默认忽略带下划线的header
underscores_in_headers on;也就是不忽略带下划线的header