个人随笔
目录
nginx反向代理中proxy_set_header 运维笔记(转)
2021-01-04 11:38:55

proxy_set_header

即允许重新定义或添加字段传递给代理服务器的请求头。该值可以包含文本、变量和它们的组合。在没有定义proxy_set_header时会继承之前定义的值。默认情况下,只有两个字段被重定义:

  1. proxy_set_header Host $proxy_host;
  2. proxy_set_header Connection close;

如果启用缓存,来自之前请求的头字段“If-Modified-Since”, “If-Unmodified-Since”, “If-None-Match”, “If-Match”, “Range”, 和 “If-Range” 将不会被代理服务器传递。
一个不会变化的“Host”头请求字段可通过如下方式被传递:

  1. proxy_set_header Host $http_host;

然后,当字段不在请求头中就无法传递了,在这种情况下,可通过设置Host变量,将需传递值赋给Host变量

  1. proxy_set_header Host $host;

此外,服务器名称和端口一起通过代理服务器传递

  1. proxy_set_header Host $host:$proxy_port;

如果请求头的存在空的字段将不会通过代理服务器传递出去

  1. proxy_set_header Accept-Encoding "";

简而言之,proxy_set_header 就是可设置请求头-并将头信息传递到服务器端,不属于请求头的参数中也需要传递时,重定义下即可!

测试案例

1)如下测试:不设置 proxy_set_header

Nginx 配置:

  1. upstream test {
  2. server 192.168.1.123:9099;
  3. server 192.168.1.123:58080;
  4. }
  5. server {
  6. listen 5800;
  7. server_name 192.168.1.123;
  8. root /usr/share/nginx/html;
  9. include /etc/nginx/default.d/*.conf;
  10. location / {
  11. proxy_pass http://test;
  12. }
  13. ...

测试jsp 想获取客户端IP、客户端port、代理服务器IP、代理服务器port

  1. <%@page contentType="text/html; charset=UTF-8" trimDirectiveWhitespaces="true"%>
  2. <%
  3. String scheme = request.getScheme();
  4. String serverName = request.getServerName();
  5. String remoteName = request.getRemoteAddr();
  6. String realIP = request.getHeader("X-Forwarded-For");
  7. String realIP2 = request.getHeader("X-Real-IP");
  8. String Host = request.getHeader("Host");
  9. int port = request.getServerPort();
  10. int portR = request.getRemotePort();
  11. String requestURIC1 = scheme+"://"+realIP+":"+portR;
  12. String requestURIC2 = scheme+"://"+realIP2+":"+portR;
  13. String requestURIC3 = scheme+"://"+remoteName+":"+portR;
  14. String requestURI = scheme+"://"+serverName+":"+port;
  15. %>
  16. 其中:
  17. 客户端地址1:<%=requestURIC1 %>
  18. 客户端地址2:<%=requestURIC2 %>
  19. 客户端地址3:<%=requestURIC3%>
  20. 服务器地址1:<%=requestURI%>
  21. 服务器地址2:<%=Host%>
  22. 测试结果
  23. 客户端地址1:http://null:58828
  24. 客户端地址2:http://null:58828
  25. 客户端地址3:http://192.168.1.123:58828
  26. 服务器地址1:http://test:80
  27. 服务器地址2:test

Nginx日志

  1. 192.168.1.177 -20508---5800 [25/Aug/2016:16:34:13 +0800] "GET /docs/test.jsp HTTP/1.1" 200 223 "

其中客户端IP不能获取到,而通过request.getRemoteAddr();

获取的IP是代理服务器IP,而不是客户端IP,而在nginx中$remote_addr变量的值是客户端的IP,可见remoteaddr没有传递。

而server_port值也不对,当前值为5800,当前打印出的是80。

而当前代理为http://test 所有通过host得到的是test。

客户端port也获取不到值为20508,可传给应用的是58828

2)如下测试,设置 proxy_set_header

Nginx 配置:

  1. upstream test {
  2. server 192.168.1.123:9099;
  3. server 192.168.1.123:58080;
  4. }
  5. server {
  6. listen 5800;
  7. server_name 192.168.1.123;
  8. root /usr/share/nginx/html;
  9. include /etc/nginx/default.d/*.conf;
  10. location / {
  11. proxy_pass http://test;
  12. proxy_set_header Host $host:$server_port;
  13. proxy_set_header X-Real-IP $remote_addr;
  14. proxy_set_header X-Real-PORT $remote_port;
  15. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  16. }
  17. ...

测试页面改成:

  1. <%@page contentType="text/html; charset=UTF-8" trimDirectiveWhitespaces="true"%>
  2. <%
  3. String scheme = request.getScheme();
  4. String serverName = request.getServerName();
  5. String remoteName = request.getRemoteAddr();
  6. String realIP = request.getHeader("X-Forwarded-For");
  7. String realIP2 = request.getHeader("X-Real-IP");
  8. String Host = request.getHeader("Host");
  9. int port = request.getServerPort();
  10. int portR = request.getRemotePort();
  11. String portR2 = request.getHeader("X-Real-Port");
  12. String requestURIC1 = scheme+"://"+realIP+":"+portR;
  13. String requestURIC2 = scheme+"://"+realIP2+":"+portR;
  14. String requestURIC3 = scheme+"://"+remoteName+":"+portR;
  15. String requestURI = scheme+"://"+serverName+":"+port;
  16. %>
  17. 其中:
  18. 客户端地址1:<%=requestURIC1 %>
  19. 客户端地址2:<%=requestURIC2 %>
  20. 客户端地址3:<%=requestURIC3%>
  21. 服务器地址1:<%=requestURI%>
  22. 服务器地址2:<%=Host%>
  23. 客户端port2:<%=portR2%>
  24. 客户端地址1:http://192.168.1.177:21548
  25. 客户端地址2:http://192.168.1.177:21548
  26. 客户端地址3:http://192.168.1.123:21548
  27. 服务器地址1:http://192.168.1.123:5800
  28. 服务器地址2:192.168.1.123:5800
  29. 客户端port2:20604

nginx日志:

  1. 192.168.1.177 -20604---5800 [25/Aug/2016:16:38:42 +0800] "GET /docs/test.jsp HTTP/1.1" 200 275 "-" "Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.106 Safari/537.36" "-"

除request.getRemoteAddr();获取的值不对外,其他值都是对的。

getRemoteAddr获取的是代理的请求地址。

因重定义了host,所以test值被改写成代理服务器IP。

因重定义了 X-Real-PORT-并传递$remote_port,客户端port也获取正确了。

proxy_set_header自定义header头无效的问题

nginx反向代理中经常碰过的一个”坑”:proxy_set_header自定义header头无效的问题

解决办法:

nginx underscores_in_headers默认off

可以用减号-替代下划线符号_,避免这种变态问题。nginx默认忽略掉下划线可能有些原因。

  1. upstream os-8080 {
  2. ip_hash;
  3. server 192.168.1.20:8080 max_fails=3 fail_timeout=15s;
  4. server 192.168.1.21:8080 max_fails=3 fail_timeout=15s;
  5. }
  6. server {
  7. listen 80;
  8. server_name bpm.wangshibo.com;
  9. access_log /data/nginx/logs/bpm.wangshibo.com-access.log main;
  10. error_log /data/nginx/logs/bpm.wangshibo.com-error.log;
  11. nginx underscores_in_headers on;
  12. location / {
  13. proxy_pass http://os-8080;
  14. proxy_redirect off ;
  15. proxy_set_header Host $host;
  16. proxy_set_header X-Real-IP $remote_addr;
  17. proxy_set_header REMOTE-HOST $remote_addr;
  18. proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  19. proxy_connect_timeout 300;
  20. proxy_send_timeout 300;
  21. proxy_read_timeout 600;
  22. proxy_buffer_size 512k;
  23. proxy_buffers 8 512k;
  24. proxy_busy_buffers_size 512k;
  25. proxy_temp_file_write_size 512k;
  26. proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504 http_404;
  27. proxy_max_temp_file_size 128m;
  28. }
  29. error_page 500 502 503 504 /50x.html;
  30. location = /50x.html {
  31. root html;
  32. }
  33. }

proxy_set_header中$proxy_host,$host,$http_host的区别

在使用Nginx做反向代理的时候,proxy_set_header功能可以设置反向代理后的http header中的host,$http_host,$proxy_host,那么这几个有什么区别呢?

Nginx的官网文档中说下面这两条是做反代时默认的,所以$proxy_host 自然是 proxy_pass后面跟着的host了

  1. proxy_set_header Host $proxy_host;
  2. proxy_set_header Connection close;

如果客户端发过来的请求的header中有’HOST’这个字段时,

$http_host和$host都是原始的’HOST’字段

比如请求的时候HOST的值是www.csdn.net 那么反代后还是www.csdn.net

如果客户端发过来的请求的header中没有有’HOST’这个字段时,

建议使用$host,这表示请求中的server name

更多来自:http://www.360doc.com/content/18/0207/17/16915_728405877.shtml

 6055

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2