You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

浏览器显示h3但http3check报错[Nginx 1.25.3]求助

Nginx 1.25.3 HTTP/3 验证失败但浏览器已启用h3协议的问题排查

我正在将网站从Apache迁移至Nginx 1.25.3(自带QUIC支持),使用http3check.net验证时报错,但Chrome开发者工具的Network标签显示已正常使用"h3"协议。

我的配置文件

nginx.conf

user  www-data;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    log_format quic '$remote_addr - $remote_user [$time_local] '
                    '"$request" $status $body_bytes_sent '
                    '"$http_referer" "$http_user_agent" "$http3"';

    access_log /var/log/nginx/access_http3.log quic;
    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    tcp_nopush     on;

    ##
    # SSL Configuration
    ##

    ssl_protocols TLSv1.3; # Dropping SSLv3, ref: POODLE
    ssl_prefer_server_ciphers on;


    ##
    # FastCGI Cache Settings
    ##

    fastcgi_cache_path /etc/nginx-cache levels=1:2 keys_zone=phpcache:100m inactive=60m;
    fastcgi_cache_key "$scheme$request_method$host$request_uri";
    fastcgi_ignore_headers Cache-Control Expires;
    


gzip on;
gzip_disable "msie6";

gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;

gzip_min_length 256;
gzip_types
  application/atom+xml
  application/geo+json
  application/javascript
  application/x-javascript
  application/json
  application/ld+json
  application/manifest+json
  application/rdf+xml
  application/rss+xml
  application/xhtml+xml
  application/xml
  font/eot
  font/otf
  font/ttf
  image/svg+xml
  text/css
  text/javascript
  text/plain
  text/xml;
    
    keepalive_timeout  65;

    include /etc/nginx/conf.d/*.conf;
}

kvlk.me.conf

map $sent_http_content_type $expires {
    default                    off;
    text/html                  epoch;
    text/css                   max;
    application/javascript     max;
    ~assets/                    max;

}
server {
    listen 443 ssl;
    listen [::]:443 ssl;
    http2 on;
    listen 443 quic reuseport;
    listen [::]:443 quic reuseport;
    http3 on;
    http3_hq on;
    quic_retry on;
    quic_gso on;
    ssl_early_data on;
    index index.php;
    expires $expires;

    server_name kvlk.me;
    
    root /var/www/kvlk.me/landing;
 #   listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/kvlk.me/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/kvlk.me/privkey.pem; # managed by Certbot
    
    ssl_protocols TLSv1.3;
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    location / {
                add_header Alt-Svc 'h3=":$server_port"; ma=86400';
                add_header x-quic 'h3';
                
                add_header X-protocol $server_protocol always;        
    
                proxy_cache my_cache;
                proxy_cache_valid 200 30m;
                proxy_cache_valid 404 1m;
                proxy_cache_key "$request_method$host$request_uri";
                proxy_cache_lock on;
                proxy_cache_lock_timeout 5s;
                add_header X-Proxy-Cache $upstream_cache_status;
                # Protects against SSL Early Data Replay Attacks
                # See RFC8446 or NGINX Documentation
                proxy_set_header Early-Data $ssl_early_data;# Standard proxying headers
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-Host $server_name;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;# SSL proxying headers
                proxy_set_header X-Forwarded-Proto $scheme;
                proxy_set_header X-Forwarded-Ssl on;
                if (!-e $request_filename){
                    rewrite ^/([^/]*)$ /index.php?view=$1 last;
                }
                if (!-e $request_filename){
                    rewrite ^/([^/]*)/([^/]*)$ /index.php?view=$1&id=$2 last;
                }
        
    }
    location /api {
                rewrite ^/api/([^/]*)$ /worker.php?action=$1 last;
    }
    location ~ \.php$ {
                include snippets/fastcgi-php.conf;
                fastcgi_pass unix:/run/php/php8.1-fpm.sock;
    }

}
server {
    add_header alt-svc 'h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400, h3=":443"; ma=86400';
  
    if ($host = kvlk.me) {
        return 301 https://$host$request_uri;
    } # managed by Certbot



    server_name kvlk.me;
    listen 80;
    return 404; # managed by Certbot


}

nginx -V 输出

nginx version: nginx/1.25.3
built by gcc 11.4.0 (Ubuntu 11.4.0-1ubuntu1~22.04)
built with OpenSSL 3.0.2 15 Mar 2022
TLS SNI support enabled
configure arguments: --prefix=/etc/nginx --sbin-path=/usr/sbin/nginx --modules-path=/usr/lib/nginx/modules --conf-path=/etc/nginx/nginx.conf --error-log-path=/var/log/nginx/error.log --http-log-path=/var/log/nginx/access.log --pid-path=/var/run/nginx.pid --lock-path=/var/run/nginx.lock --http-client-body-temp-path=/var/cache/nginx/client_temp --http-proxy-temp-path=/var/cache/nginx/proxy_temp --http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp --http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp --http-scgi-temp-path=/var/cache/nginx/scgi_temp --user=nginx --group=nginx --with-compat --with-file-aio --with-threads --with-http_addition_module --with-http_auth_request_module --with-http_dav_module --with-http_flv_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_mp4_module --with-http_random_index_module --with-http_realip_module --with-http_secure_link_module --with-http_slice_module --with-http_ssl_module --with-http_stub_status_module --with-http_sub_module --with-http_v2_module --with-http_v3_module --with-mail --with-mail_ssl_module --with-stream --with-stream_realip_module --with-stream_ssl_module --with-stream_ssl_preread_module --with-cc-opt='-g -O2 -ffile-prefix-map=/data/builder/debuild/nginx-1.25.3/debian/debuild-base/nginx-1.25.3=. -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -fstack-protector-strong -Wformat -Werror=format-security -Wp,-D_FORTIFY_SOURCE=2 -fPIC' --with-ld-opt='-Wl,-Bsymbolic-functions -flto=auto -ffat-lto-objects -flto=auto -Wl,-z,relro -Wl,-z,now -Wl,--as-needed -pie'

排查建议

1. 修正Alt-Svc头格式

配置里的"是HTML转义字符,Nginx配置中不需要,直接使用双引号即可:

# 主server块的Alt-Svc修正
add_header Alt-Svc 'h3=":$server_port"; ma=86400';
# 80端口跳转server块的Alt-Svc修正
add_header alt-svc 'h3-27=":443"; ma=86400, h3-28=":443"; ma=86400, h3-29=":443"; ma=86400, h3=":443"; ma=86400';

错误的转义会导致部分工具无法解析Alt-Svc头,无法触发HTTP/3连接尝试。

2. 检查QUIC端口监听

  • 确认UDP 443端口仅被Nginx占用:
    ss -ulpn | grep :443
    
  • 确保系统开启了SO_REUSEPORT:
    sysctl net.ipv4.tcp_reuseport
    
    若值为0,执行sysctl -w net.ipv4.tcp_reuseport=1临时开启,或者写入/etc/sysctl.conf永久生效。

3. 调整TLS配置兼容性

全局仅启用TLSv1.3可能导致部分验证工具无法完成QUIC握手,建议兼容TLSv1.2:

ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;

同时检查/etc/letsencrypt/options-ssl-nginx.conf,确保没有覆盖该配置或禁用必要的加密套件。

4. 禁用HTTP/3 HQ模式尝试

临时注释http3_hq on;,重新加载Nginx后再用验证工具测试,部分工具可能不支持HQ模式。

5. 用curl测试HTTP/3

curl -I --http3 https://kvlk.me

若返回HTTP/3 200则说明HTTP/3服务正常,问题出在验证工具本身。

6. 查看Nginx日志排查错误

  • 查看QUIC相关错误日志:
    grep -i quic /var/log/nginx/error.log
    
  • 实时监控HTTP/3访问日志:
    tail -f /var/log/nginx/access_http3.log
    
    检查是否有连接失败、TLS握手错误等异常信息。

内容的提问来源于stack exchange,提问作者KovMus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 05:24:52