Nginx 报错 unknown connection_upgrade variable 完整解决方案

问题描述

在使用 Nginx 配置 WebSocket 或反向代理时,可能会遇到以下错误:

nginx: [emerg] unknown "connection_upgrade" variable
nginx: configuration file /etc/nginx/nginx.conf test failed

这个错误表明 Nginx 配置文件中使用了 $connection_upgrade 变量,但该变量未定义。

错误原因

$connection_upgrade 变量通常用于 WebSocket 配置,支持 Upgrade 头部的处理。但 Nginx 默认不识别这个变量,需要通过 map 指令手动定义。

常见触发场景

场景是否需要 WebSocket常见配置
普通 Web 应用❌ 不需要HTTP/HTTPS
实时聊天应用✅ 需要WebSocket
API 网关❌ 不需要REST API
在线协作工具✅ 需要WebSocket
直播/流媒体✅ 需要WebSocket/RTMP

解决方案

方案一:添加 map 配置(推荐 - 需要 WebSocket)

如果你需要 WebSocket 支持,在 /etc/nginx/nginx.confhttp 块中添加以下配置:

http {
    # ... 其他配置 ...
    
    # 添加 WebSocket 支持的 map 配置
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }
    
    # ... 其他配置 ...
}

配置说明

  • map 指令:根据 $http_upgrade 的值设置 $connection_upgrade
  • default upgrade:默认情况下允许 Upgrade
  • '' close:如果 Upgrade 头为空,则关闭连接

完整配置示例

http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    # WebSocket 支持配置
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }

    # 基础配置
    sendfile        on;
    keepalive_timeout  65;

    # 上游服务器
    upstream backend {
        server 127.0.0.1:8080;
    }

    # 服务器配置
    server {
        listen 80;
        server_name example.com;

        location / {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            
            # WebSocket 支持
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
            
            # 基础代理头
            proxy_set_header Host $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;
        }
    }
}

方案二:移除 WebSocket 配置(不需要 WebSocket)

如果你不需要 WebSocket 支持,可以直接移除相关配置:

location / {
    proxy_pass http://backend;
    
    # 保留基础代理头
    proxy_set_header Host $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 Upgrade $http_upgrade;
    # proxy_set_header Connection $connection_upgrade;
}

方案三:使用独立的 WebSocket 配置文件

将 WebSocket 配置提取到独立文件,便于管理:

# 创建 WebSocket 配置文件
sudo tee /etc/nginx/conf.d/websocket.conf << 'EOF'
# WebSocket 支持配置
map $http_upgrade $connection_upgrade {
    default upgrade;
    ''      close;
}
EOF

# 在 nginx.conf 中引用
# http 块中添加:
include /etc/nginx/conf.d/*.conf;

验证和测试

1. 测试配置文件

# 测试 Nginx 配置
sudo nginx -t

# 成功输出示例:
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

2. 重载 Nginx

# 重载配置(推荐)
sudo nginx -s reload

# 或者重启服务
sudo systemctl restart nginx

# 检查状态
sudo systemctl status nginx

3. 验证 WebSocket 连接

# 使用 curl 测试 Upgrade 头
curl -i -H "Upgrade: websocket" -H "Connection: Upgrade" http://example.com

# 使用 wscat 测试 WebSocket(需要安装)
npm install -g wscat
wscat -c ws://example.com/websocket

4. 查看 Nginx 日志

# 查看错误日志
sudo tail -f /var/log/nginx/error.log

# 查看访问日志
sudo tail -f /var/log/nginx/access.log

# 实时查看连接状态
sudo nginx -T | grep -A 10 "location"

常见问题排查

问题 1:配置后仍然报错

# 检查 map 配置位置(必须在 http 块内)
sudo nginx -T | grep -A 5 "map"

# 检查配置文件语法
sudo nginx -t

# 检查文件权限
ls -la /etc/nginx/nginx.conf

问题 2:WebSocket 连接失败

# 检查后端服务是否运行
netstat -tlnp | grep 8080

# 检查防火墙规则
sudo ufw status
sudo firewall-cmd --list-ports

# 测试后端直连
curl http://127.0.0.1:8080

问题 3:配置不生效

# 强制重载 Nginx
sudo systemctl stop nginx
sudo systemctl start nginx

# 检查是否有多个 nginx.conf
find /etc -name "nginx.conf"

# 查看实际加载的配置
sudo nginx -T

性能优化建议

WebSocket 连接优化

http {
    # ... 其他配置 ...
    
    map $http_upgrade $connection_upgrade {
        default upgrade;
        ''      close;
    }
    
    # WebSocket 超时配置
    map $http_upgrade $timeout_upgrade {
        default 3600s;
        ''      75s;
    }
    
    server {
        location /websocket {
            proxy_pass http://backend;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
            
            # 优化配置
            proxy_buffering off;
            proxy_cache off;
            proxy_read_timeout $timeout_upgrade;
            proxy_send_timeout $timeout_upgrade;
        }
    }
}

连接池配置

upstream backend {
    server 127.0.0.1:8080;
    
    # 连接池配置
    keepalive 32;
    keepalive_requests 100;
    keepalive_timeout 60s;
}

安全加固建议

1. 限制 WebSocket 路径

# 只允许特定路径使用 WebSocket
location /api/ws {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
}

# 其他路径禁止 WebSocket
location / {
    proxy_pass http://backend;
    
    # 检查是否尝试 Upgrade
    if ($http_upgrade) {
        return 400;
    }
}

2. 添加认证

location /websocket {
    # JWT 认证
    auth_request /auth;
    
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;
}

location = /auth {
    internal;
    proxy_pass http://auth-service/validate;
    proxy_pass_request_body off;
    proxy_set_header Content-Length "";
    proxy_set_header X-Original-URI $request_uri;
}

3. 限流配置

http {
    # 限制连接速率
    limit_conn_zone $binary_remote_addr zone=websocket_limit:10m;
    
    server {
        location /websocket {
            limit_conn websocket_limit 10;  # 每个 IP 最多 10 个连接
            
            proxy_pass http://backend;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection $connection_upgrade;
        }
    }
}

总结

Nginx 报错 unknown "connection_upgrade" variable 的解决方案:

  1. 需要 WebSocket:在 http 块中添加 map 配置定义变量
  2. 不需要 WebSocket:移除 Upgrade 相关配置
  3. 验证配置:使用 nginx -t 测试,nginx -s reload 重载
  4. 性能优化:配置超时、连接池、缓冲
  5. 安全加固:路径限制、认证、限流

根据你的实际需求选择合适的方案,确保 Nginx 配置正确运行!🚀


相关文章:

发表回复

后才能评论