一些Nginx内置变量

后端 0 516 0
发表于: 2022-12-01 01:38:26

简介: mark~

$remote_addr

代表客户端 IP,这里的客户端指的是直接请求 Nginx 的客户端,非间接请求的客户端(即不管中转了几次,都是拿到最上层的用户 IP)。

假设用户请求过程如下

用户客户端 --> 发送请求 --> Nginx1 ---> 转发请求 --> Nginx2 --> 后端服务器

那么,默认情况下,针对 Nginx1 而言,$remote_addr为用户客户端 IP,对 Nginx2 而言,$remote_addr则为 Nginx1 的 IP。此时如果希望 Nginx2 也可以获取用户客户端 IP,那要怎么处理呢?答案如下:

在 Nginx1 配置文件中使用proxy_set_header为转发请求设置请求头

# X-Real-IP 为请求头名称,可自定义
proxy_set_header X-Real-IP $remote_addr;

然后,在 Nginx2 配置文件中通过$http_x_real_ip来获取X-Real-IP请求头的值来获取真实客户端 IP.

此时,如果要求“后端服务器”也要获取用户客户端 IP,咋处理呢?做法和上述类似,在 Nginx2 配置文件中,使用proxy_set_header做同样的配置,即:

# X-Real-IP 为请求头名称,可自定义
proxy_set_header X-Real-IP $remote_addr;

然后,“后端服务器”获取请求头“X-Real-IP”的值即为用户客户端 IP。

很多 HTTP 代理会在 HTTP 协议头中添加X-Forwarded-For头,用来追踪请求的来源。X-Forwarded-For的格式如下:

X-Forwarded-For包含多个 IP 地址,每个值通过逗号+空格分开,最左边(client1)是最原始客户端的 IP 地址,中间如果有多层代理,每一层代理会将连接它的客户端 IP 追加在X-Forwarded-For右边。

$proxy_add_x_forwarded_for

“X-Forwarded-For”客户端请求头字段,其中附加了$remote_addr变量,用逗号分隔。如果客户端请求标头中不存在“X-Forwarded-For”字段,则$proxy_add_X_Forwarded_For 变量等于$remote_addr 变量。

代表附加$remote_addr变量的客户端请求头X-Forwarded-For ,其值如果包含多个地址,用逗号+空格分隔,标准格式如下:

X-Forwarded-For: clientIP, proxyIP1, proxyIP2 # 最左边的clientIp即为客户端真实IP

如果X-Forwarded-For字段没出现在客户端请求头,$proxy_add_x_forwarded_for 等同于$remote_addr 变量。

这里,假设用户请求过程和上文所述一样,如下:

用户客户端 --> 发送请求 --> Nginx1 ---> 转发请求 --> Nginx2 --> 后端服务器

假设,仅在 Nginx1 配置文件中进行了以下配置

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

那么,Nginx2 配置的X-Forwarded-For请求头的值即为clientIP当然,这个结论的前提是,客户端 IP 没有配置X-Forwarded-For请求头,因为如上所述,客户端没有出现这个请求头时,$proxy_add_x_forwarded_for 的值即为$remote_addr 变量的值,否则,则是客户端为X-forwarded-for请求头的实际值

$host

浏览器请求的 ip,不显示端口号

admin.hsslive.cn 是博客后台地址,admin.hsslive.cn 在浏览器里的请求的地址都是 api.hsslive.cn,浏览器发请求默认的请求头:

GET /prodapi/admin/visitor_log/list?nowPage=1&pageSize=10&orderName=id&orderBy=desc HTTP/1.1
Accept: application/json, text/plain, */*
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Authorization: Bearer eyJhbGcxxxxxxx
Cache-Control: no-cache
Connection: keep-alive
Cookie: Hm_lvt_dfb02eddbeccf11629b56d7477284c6d=1669783032; token=eyJhbGcxxxxxxx
Host: api.hsslive.cn
Origin: https://admin.hsslive.cn
Pragma: no-cache
Referer: https://admin.hsslive.cn/
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/108.0.0.0 Safari/537.36
sec-ch-ua: "Not?A_Brand";v="8", "Chromium";v="108", "Google Chrome";v="108"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"

可以看到 Host 的值是 api.hsslive.cn,但是 api.hsslive.cn 的 nginx 是这样的:

# api.hsslive.cn 443端口
server {
    listen 443 ssl;
    server_name api.hsslive.cn;

    # 开启gzip,关闭用off
    gzip on;
    # 选择压缩的文件类型,其值可以在 mime.types 文件中找到。
    gzip_types text/plain text/css application/json application/javascript
    # 是否在http header中添加Vary: Accept-Encoding,建议开启
    gzip_vary on;
    # gzip 压缩级别,1-9,数字越大压缩的越好,也越占用CPU时间,推荐6
    gzip_comp_level 6;

    # https://cloud.tencent.com/document/product/400/47360
    ssl_certificate /usr/local/webserver/nginx/conf/cert/api.hsslive.cn_bundle.crt;
    ssl_certificate_key /usr/local/webserver/nginx/conf/cert/api.hsslive.cn.key;
    ssl_session_timeout 5m;
    ssl_protocols TLSv1 TlSv1.1 TLSv1.2;
    ssl_ciphers SM2-WITH-SMS4SM3:ECDH:AESGCM:HIGH:MEDIUM:!RC4:!DH:!MD5:!aNULL:!eNULL;
    ssl_prefer_server_ciphers on;

    location /prodapi/ {
        # X-Real-IP是自定义的,给koa里记录日志
        proxy_set_header X-Real-IP $remote_addr;
        # X-Forwarded-For,是事实上的标准,暂时没地方用到
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # X-Forwarded-Proto,是事实上的标准,给koa里的cookie使用
        proxy_set_header X-Forwarded-Proto $scheme;
        # proxy_set_header X-NginX-Proxy true;
        proxy_pass http://localhost:3200/;
    }

    location /betaapi/ {
        # X-Real-IP是自定义的,给koa里记录日志
        proxy_set_header X-Real-IP $remote_addr;
        # X-Forwarded-For,是事实上的标准,暂时没地方用到
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        # X-Forwarded-Proto,是事实上的标准,给koa里的cookie使用
        proxy_set_header X-Forwarded-Proto $scheme;
        # proxy_set_header X-NginX-Proxy true;
        proxy_pass http://localhost:3300/;
    }
}

因为使用了 proxy_pass 代理,所以浏览器的请求头 Host 其实是不生效的,最终 http://localhost:3300/里的 koa 服务拿到的 req.headers.host 是 localhost:3200,req.headers.hostname 是 localhost,并没有办法将浏览器的 Host 值(api.hsslive.cn)给传递给 koa 服务的 host,但是我们可以手动配置 host:

location /prodapi/ {
    # X-Real-IP是自定义的,给koa里记录日志
    proxy_set_header X-Real-IP $remote_addr;
    # X-Forwarded-For,是事实上的标准,暂时没地方用到
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    # X-Forwarded-Proto,是事实上的标准,给koa里的cookie使用
    proxy_set_header X-Forwarded-Proto $scheme;
    # proxy_set_header X-NginX-Proxy true;
    proxy_set_header Host $host;
    proxy_pass http://localhost:3200/;
}

这样的话,最终 http://localhost:3300/里的 koa 服务拿到的 req.headers.host 就是 api.hsslive.cn 了

$http_host

浏览器请求的 ip 和端口号(如果没有端口号则不显示)

$https

如果开启了 SSL 安全模式,值为“on”,否则为空字符串。

$scheme

请求使用的 Web 协议, 值是 http 或 https

未完待续,持续补充

参考

https://www.cnblogs.com/shouke/p/15511149.html

https://nginx.org/en/docs/http/ngx_http_core_module.html#var_remote_addr

https://nginx.org/en/docs/http/ngx_http_proxy_module.html#var_proxy_add_x_forwarded_for

nginx

最后更新于:2022-12-01 01:38:26

欢迎评论留言~
0/200
支持markdown
Comments | 0 条留言
按时间
按热度
目前还没有人留言~