Nginx - 内置变量

核心请求变量(最常用)

1. 连接/客户端信息

变量 说明 示例值
$remote_addr 客户端IP地址 192.168.1.100
$remote_port 客户端端口 54321
$remote_user HTTP基本认证用户名 alice
$server_addr 服务器接收请求的IP 10.0.0.1
$server_port 服务器接收请求的端口 80, 443

2. 主机/域名信息

变量 区别 示例
$host 请求头中的 Host 字段(不含端口) example.com
$http_host $host,但包含端口(如果有) example.com:8080
$server_name 匹配的 server 块名称 www.example.com

详细对比

# 请求:GET / HTTP/1.1  Host: www.example.com:8080
$host = "www.example.com"           # ← 最常用
$http_host = "www.example.com:8080" # 带端口
$server_name = "default"            # 匹配的server名称

3. 请求信息

变量 说明 示例
$request 完整的原始请求行 GET /api/user?name=john HTTP/1.1
$request_method HTTP方法 GET, POST, PUT
$request_uri 完整的URI(带参数) /api/user?name=john
$uri 当前请求的URI(不含参数) /api/user
$document_uri $uri /api/user
$args 查询字符串 name=john&age=20
$query_string $args name=john&age=20
$is_args 如果有参数则为"?",否则为空 ?
$arg_XXX 获取特定查询参数 $arg_name = "john"
$request_body 请求体内容(POST/PUT) {"id":1}
$request_length 请求长度(字节) 125
$request_time 请求处理时间(秒,毫秒精度) 0.123

4. 头部信息

变量 说明
$http_XXX 获取请求头(XXX转为小写,横线变下划线)
$sent_http_XXX 获取响应头

示例

# 获取各种头部
$http_user_agent      # User-Agent 头
$http_referer         # Referer 头
$http_content_type    # Content-Type 头
$http_x_forwarded_for # X-Forwarded-For 头
$sent_http_content_type # 响应 Content-Type

响应相关变量

1. 响应状态

变量 说明 示例
$status HTTP响应状态码 200, 404, 500
$body_bytes_sent 发送给客户端的响应体字节数 1024
$bytes_sent 发送的总字节数 1500
$connection 连接序列号 12345
$connection_requests 当前连接已处理的请求数 5

2. 响应头控制

# 常用于 add_header 指令
add_header X-Request-ID $request_id;
add_header X-Response-Time $request_time;

# 返回特定状态码
return 200 "Request ID: $request_id";

代理相关变量

1. 反向代理变量

变量 说明
$proxy_host proxy_pass 指令中指定的主机
$proxy_port proxy_pass 指令中指定的端口
$proxy_add_x_forwarded_for 追加IP到 X-Forwarded-For
$proxy_protocol_addr PROXY协议中的客户端地址

2. 上游服务器变量

变量 说明
$upstream_addr 后端服务器地址
$upstream_status 后端响应状态码
$upstream_response_time 后端响应时间(秒)
$upstream_connect_time 连接后端时间
$upstream_header_time 接收后端响应头时间
$upstream_cache_status 缓存状态

示例配置

log_format upstream_debug '$remote_addr - $upstream_addr - '
                          'upstream_response_time=$upstream_response_time - '
                          'upstream_cache_status=$upstream_cache_status';

SSL/TLS 相关变量

HTTPS 连接信息

变量 说明 示例
$scheme 请求协议 http, https
$https 如果是HTTPS则为"on",否则为空 on
$ssl_protocol SSL协议版本 TLSv1.2
$ssl_cipher 协商的加密套件 ECDHE-RSA-AES256-GCM-SHA384
$ssl_session_id SSL会话ID a1b2c3...
$ssl_session_reused 会话是否重用 r
$ssl_client_serial 客户端证书序列号 1234567890
$ssl_client_s_dn 客户端证书主题 CN=John Doe, O=Example Inc.
$ssl_client_verify 客户端证书验证结果 SUCCESS, FAILED

SSL配置示例

server {
    listen 443 ssl;
    
    ssl_certificate /path/to/cert.pem;
    ssl_certificate_key /path/to/key.pem;
    
    location /secure {
        # 记录SSL信息
        access_log /var/log/nginx/ssl.log '$ssl_protocol $ssl_cipher';
        
        # 要求客户端证书
        if ($ssl_client_verify != SUCCESS) {
            return 403;
        }
    }
}

时间和日期变量

时间格式变量

变量 格式 示例
$time_local 本地时间(通用日志格式) 18/Dec/2025:10:30:45 +0800
$time_iso8601 ISO 8601 格式 2025-12-18T10:30:45+08:00
$msec 当前时间(秒.毫秒) 1671337845.123
$request_time 请求处理时间 0.123
$upstream_response_time 后端响应时间 0.056

日志时间配置

# 推荐使用 ISO 8601 格式,便于解析
log_format json_log '{"@timestamp":"$time_iso8601", "request":"$request"}';

# 传统格式(兼容旧系统)
log_format combined '$remote_addr - $remote_user [$time_local] "$request"';

特殊用途变量

1. 速率限制相关

变量 说明
$limit_rate 客户端传输速率限制(可设置)
$connection 连接序列号
$connection_requests 当前连接请求数

2. GeoIP 模块变量

# 需要 ngx_http_geoip_module 模块
geoip_country /etc/nginx/GeoIP.dat;

location / {
    # 获取地理位置信息
    add_header X-Country $geoip_country_code;
    add_header X-City $geoip_city;
}

3. Real IP 模块变量

# 从代理头获取真实IP
real_ip_header X-Forwarded-For;
set_real_ip_from 10.0.0.0/8;

# 变量变化
# $remote_addr 变为真实客户端IP
# $realip_remote_addr 保存原 $remote_addr

实际应用场景

场景1:日志增强

log_format enhanced '$remote_addr - "$http_user_agent" - '
                    '"$request" $status $body_bytes_sent - '
                    'Referer: "$http_referer" - '
                    'Forwarded: "$http_x_forwarded_for" - '
                    'Upstream: $upstream_addr ($upstream_response_time s) - '
                    'SSL: $ssl_protocol/$ssl_cipher';

场景2:动态代理配置

# 根据请求头动态选择后端
map $http_x_api_version $backend {
    default  "http://api-v1:8080";
    "v2"     "http://api-v2:8080";
}

location /api {
    proxy_pass $backend;
}

场景3:安全限制

# 限制特定User-Agent
if ($http_user_agent ~* (wget|curl|bot)) {
    return 403 "No bots allowed";
}

# 检查必要的请求头
if ($http_x_api_key = "") {
    return 401 "API key required";
}

场景4:A/B测试

# 基于Cookie的路由
map $cookie_experiment $backend_group {
    "A" "backend_a";
    "B" "backend_b";
    default "backend_default";
}

upstream backend_a { server 10.0.0.1:8080; }
upstream backend_b { server 10.0.0.2:8080; }
upstream backend_default { server 10.0.0.3:8080; }

location / {
    proxy_pass http://$backend_group;
}

场景5:调试信息

location /debug {
    # 返回所有变量信息
    return 200 "
        Host: $host\n
        Remote: $remote_addr\n
        URI: $uri\n
        Args: $args\n
        Method: $request_method\n
        Scheme: $scheme\n
        User-Agent: $http_user_agent\n
        Referer: $http_referer\n
        Time: $time_iso8601\n
    ";
}

变量优先级与作用域

变量作用域

  1. 请求级别:大多数变量(如 $uri, $args
  2. 连接级别$connection, $connection_requests
  3. 服务器级别$server_name, $server_addr

常见陷阱

# ❌ 错误:在 server 作用域使用请求级别变量
server {
    # $uri 在这里是 undefined!
    set $fixed_uri $uri;  # 错误!
    
    location / {
        # ✅ 正确:在 location 中使用
        set $fixed_uri $uri;
    }
}

# ❌ 变量不能嵌套
set $original_host $host;
set $new_host "$original_host:8080";  # ✅ 可以
set $new_host "${host}:8080";         # ❌ 不能嵌套

常用变量速查表

基础三要素

$host        # 域名(无端口)
$remote_addr # 客户端IP
$request_uri # 完整路径+参数

代理必备

$proxy_add_x_forwarded_for  # 追加代理链
$upstream_addr              # 后端地址
$upstream_response_time     # 后端响应时间

SSL相关

$scheme        # http/https
$ssl_protocol  # TLS版本
$ssl_cipher    # 加密套件

时间相关

$time_iso8601  # ISO时间(推荐)
$request_time  # 请求处理时间

头部访问

$http_xxx      # 请求头(xxx转小写,-转_)
$sent_http_xxx # 响应头

最佳实践建议

  1. 日志格式化:使用 $time_iso8601 而不是 $time_local
  2. 代理设置:总是传递 HostX-Real-IP 头部
  3. 安全考虑:不要在生产环境暴露 $request_body 等敏感信息
  4. 性能监控:记录 $request_time$upstream_response_time
  5. 调试技巧:创建 /debug 端点返回关键变量值
posted @ 2025-12-18 15:38  【唐】三三  阅读(19)  评论(0)    收藏  举报