HTTP的X-Forwarded-*系列header在nginx,弹性负载均衡中的应用 - Go语言中文社区

HTTP的X-Forwarded-*系列header在nginx,弹性负载均衡中的应用


目录

问题概述

Forwarded

问题分析

解决方法

参考文档


问题概述

近期开发因为一个请求的端口号问题找上了我,先贴代码

这个应用的链路是流量到nginx后进行一次转发,转发到slb上,再负载到后端两台服务器。

可以看到,代码中直接从请求获取到的server port,本来应该是获取到源客户端做请求使用的端口号,也就是当浏览器使用https协议并且路由到nginx时,nginx通过该部分配置加入了server_port的值为443

    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_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Port $server_port;
    proxy_set_header X-Forwarded-Host $http_host;
    proxy_set_header Accept-Encoding "";
    proxy_connect_timeout      600;
    proxy_send_timeout         600;
    proxy_read_timeout         600;
    log_not_found off;

但是实际上经过一层slb后,代码里获取到的端口并不是443,而是8080。

这是怎么回事?

 因为这个服务启的端口监听是8080,那么对应的slb的前端端口监听也是8080。是不是slb在做请求的转发时重写了请求头的server_port参数?

Forwarded

来看下Mozilla基金会的mdn项目对Forwarded的描述:

X-Forwarded-ForXFF)是用来识别通过HTTP代理负载均衡方式连接到Web服务器的客户端最原始的IP地址的HTTP请求头字段。 Squid 缓存代理服务器的开发人员最早引入了这一HTTP头字段,并由IETF在HTTP头字段标准化草案中正式提出。

Forwarded 首部中包含了代理服务器的客户端的信息,即由于代理服务器在请求路径中的介入而被修改或丢失的信息。

其他可用来替换的,已经成为既成标准的首部是 X-Forwarded-For 、 X-Forwarded-Host 以及X-Forwarded-Proto 。

这个消息首部会被用来进行调试和统计,以及生成基于位置的定制化内容,按照设计的目的,它会暴露一定的隐私和敏感信息,比如客户端的IP地址。所以在应用此消息首部的时候,需要将用户的隐私问题考虑在内。

HTTP/1.1(RFC 2616)协议并没有对它的定义。如今它已经成为事实上的标准,被各大 HTTP 代理、负载均衡等转发服务广泛使用,并被写入 RFC 7239(Forwarded HTTP Extension)标准之中。

问题分析

虽然已经成为事实上的标准,但是不同云厂商在实现负载均衡时对它的时候也不完全一样。

因为我们的这块服务是从阿里云平移到aws的,那么在阿里云上的负载均衡不会重写这个请求头扩展,为什么aws上就会有这个问题呢?

为此,我专门查阅了aws官方文档,但是对其描述也比较少。

X-Forwarded-Port

The X-Forwarded-Port request header helps you identify the destination port that the client used to connect to the load balancer.

我还在华为云的弹性负载均衡文档中找到了这个请求头扩展的相关描述。其中,对于独享型负载均衡的listener监听器,有这么一段描述:

 虽然上面写了只支持X-Forwarded-Host的重写,但是,我们应该不难推测出,应该是在nginx访问到aws上的alb时,默认开启了X-Forwarded-Port的重写。因为,nginx作为客户端去请求alb,通过的端口号正是我们代码里最后获取到的8080端口!

解决方法

因为代码的逻辑是获取到端口后拼装url返回给浏览器客户端进行跳转,因为最后跳转的host依旧解析到的是nginx,作为最终结果,我们肯定希望其获取到的端口为跳转前使用的80/443,也就是通过透传获取到真实的客户端访问端口。

在尝试在控制台上去对弹性负载均衡操作配置时,发现华为云不支持开启透传X-Forwarded-Port,并且作为高级特性的一部分,重写X-Forwarded-Host需要使用独享型的elb,也就是要额外收费。而aws干脆就没有这块的描述。

那么转而从nginx的配置入手,也就是在经过多级代理时,我们在加入代理的请求头时就要求这个配置不能被重写,那么只要通过proxy_set_header塞入我们自定义的请求头扩展,就可以保证在多级代理中不会被重写,配置如下

    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_set_header X-Forwarded-Proto $scheme;
    proxy_set_header X-Forwarded-Port $server_port;
    proxy_set_header X-Forwarded-Host $http_host;
    #新增配置
    proxy_set_header Myconfig-Forwarded-Proto $scheme;
    proxy_set_header Myconfig-Forwarded-Port $server_port;
    proxy_set_header Myconfig-Real-IP $remote_addr;

参考文档

Forwarded - HTTP | MDN

HTTP headers and Classic Load Balancers - Elastic Load Balancing

添加HTTPS监听器_弹性负载均衡 ELB_用户指南_监听器_华为云

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/kingu_crimson/article/details/124190384
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2022-12-31 21:03:20
  • 阅读 ( 241 )
  • 分类:Go应用

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢