【杂记】在 AWS ALB 后的服务如何获得客户端的真实 IP?

该文章根据 CC-BY-4.0 协议发表,转载请遵循该协议。
本文地址:https://fenying.net/post/2024/07/10/how-to-get-client-ip-behind-aws-alb/

今天下午部署了一个新的子系统,在前面挂了一个 AWS ALB 负载均衡器,每台 Worker 机器上再配一个 Nginx 对机器内的工作进程做负载均衡。

下面记录下如何配置 Nginx 通过 AWS ALB 负载均衡器获取客户端的真实 IP。虽然不常做这个,但总好过重复踩坑。

1. 配置 AWS ALB

确保 ALB 的配置项(Attributes)中的 X-Forwarded-For Header 设置为 Append 模式。

这个模式下,ALB 会将客户端的真实 IP 附加在请求头的 X-Forwarded-For 字段尾部,以逗号分隔。

另外两个模式也解释下:

  • Preserve 模式,ALB 将会把客户端发送的 X-Forwarded-For 字段原封不动地传递给后端服务,这样会导致客户端可以伪造自己的 IP。
  • Remove 模式,ALB 将不发送 X-Forwarded-For 字段给后端服务,这样后端服务就无法获取客户端的任何 IP。

2. 配置 Nginx

在 Nginx 的 http.server 配置里,增加 Real-IP 模块的配置,例如:

 1http {
 2
 3    server {
 4
 5        # 其他配置省略,自行补充...
 6
 7        # 取 X-Forwarded-For 的最后一个 IP 当作客户端 IP($remote_addr)
 8        real_ip_header X-Forwarded-For;
 9
10        # 只信任 ALB 的 IP 段(CIDR),这个取决于你的 VPC 的 CIDR,通常只在没有配置安全组限制端口只允许 ALB 访问的情况。
11        set_real_ip_from 172.31.0.0/16;
12
13        # 其他配置省略,自行补充...
14    }
15}

然后往 location 里增加 $remote_addr 的使用,例如:

1location / {
2
3    proxy_pass http://backend;
4
5    # 用 $remote_addr 代替 X-Forwarded-For 发送给后端服务
6    proxy_set_header X-Forwarded-For $remote_addr;
7}

参考文献

comments powered by Disqus

翻译: