目前流行的 Web 服务器,例如 Apache, Nginx 都已经对 http/2 支持得比较完善了,Nginx 在版本 1.9.5 开始支持 Http/2。
Http/2 的配置是兼容 Http/1.1 的,客户端发起请求时,在握手之前,会发起 ALPN,查询服务端是否支持 Http/2, 如果不支持会回退到 Http/1.1 协议。
在这里我们使用 Curl 来测试一个 http/2 的站点:
➤ /usr/local/opt/curl-openssl/bin/curl --tlsv1.3 --http2 -v https://http2.example.com* Trying 129.211.xx.xxx:443...* Connected to https://http2.example.com (129.211.xx.xxx) port 443 (#0)* ALPN, offering h2* ALPN, offering http/1.1* successfully set certificate verify locations:* CAfile: usr/local/etc/openssl@1.1/cert.pem* CApath: usr/local/etc/openssl@1.1/certs* TLSv1.3 (OUT), TLS handshake, Client hello (1):* TLSv1.3 (IN), TLS handshake, Server hello (2):* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):* TLSv1.3 (IN), TLS handshake, Certificate (11):* TLSv1.3 (IN), TLS handshake, CERT verify (15):* TLSv1.3 (IN), TLS handshake, Finished (20):* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):* TLSv1.3 (OUT), TLS handshake, Finished (20):* SSL connection using TLSv1.3 TLS_AES_256_GCM_SHA384* ALPN, server accepted to use h2* Server certificate:* subject: CN=http2.example.com* start date: Sep 30 18:16:51 2020 GMT* expire date: Dec 29 18:16:51 2020 GMT* subjectAltName: host "http2.example.com" matched cert's "http2.example.com"* issuer: C=US; O=Let's Encrypt; CN=Let's Encrypt Authority X3* SSL certificate verify ok.* Using HTTP2, server supports multi-use* Connection state changed (HTTP/2 confirmed)* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0* Using Stream ID: 1 (easy handle 0x7f90c2814e00)> GET HTTP/2> Host: http2.example.com> user-agent: curl/7.73.0> accept: */*>* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):* old SSL session ID is stale, removing* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!< HTTP/2 200< content-type: Application/json;charset=utf-8< vary: Accept-Encoding< cache-control: no-cache, private< date: Mon, 07 Dec 2020 05:37:58 GMT< x-robots-tag: noindex<* Connection #0 to host http2.example.com left intact{"code":0,"data":{"title":"api server","version":"0.1.0","stage":"dev"},"msg":"ok"}⏎
因此无论是出于安全性还是性能方面的考虑,都应该使用 Http/2。在Nginx 中配置 Http/2,同时需要启用 SSL 加密,Http/2 协议本身并没有规定需要使用 SSL 加密,但是各大浏览器都统一默认 Http/2 需要 SSL 加密。SSL 的加密证书可以使用 Let’s encrypt,https://certbot.eff.org/,这个工具可以生成 Let’s encrypt 证书。
Let’s encrypt 证书适合用作开发环境的证书,因为 IE 和 Safari 浏览器在访问 https 站点的时候,客户端会发起 OCSP 证书检验,而 Let’s encrypt 的 ocsp 服务器在大陆访问非常缓慢,所以在 苹果设备访问 Let’s encrypt 会非常缓慢,这个也没有很好的解决方案,所以在生成环境中尽量使用其他证书,好在阿里云和腾讯云都有提供免费的 DV 证书,个人推荐使用。
Http/2 在 Nginx 中的配置:
server {listen 443 ssl http2 fastopen=3 reuseport;ssl_certificate var/www/certs/api.example.tech.pem;ssl_certificate_key var/www/certs/api.example.tech.key;ssl_session_timeout 1d;ssl_session_cache builtin:1000 shared:SSL:10m;ssl_protocols TLSv1.2 TLSv1.3;ssl_ciphers "ECDHE-ECDSA-CHACHA20-POLY1305 ECDHE-RSA-CHACHA20-POLY1305 DHE-RSA-CHACHA20-POLY1305";ssl_ocsp off;ssl_prefer_server_ciphers on;root var/www/html/app/prod/current/public;index index.php index.html;server_name api.example.tech;location / {try_files $uri $uri/ /index.php?$query_string;}error_page 404 /404.html;error_page 500 502 503 504 /50x.html;location = /50x.html {root /usr/share/nginx/html;}location ~ \.php$ {fastcgi_split_path_info ^(.+\.php)(/.+)$;fastcgi_pass unix:/run/php-fpm/www.sock;fastcgi_index index.php;fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;fastcgi_param APP_ENV prod;include fastcgi_params;}}
最主要的配置是以下几行:
listen 443 ssl http2 fastopen=3 reuseport;ssl_certificate /var/www/certs/api.example.tech.pem;ssl_certificate_key /var/www/certs/api.example.tech.key;ssl_session_timeout 1d;ssl_session_cache builtin:1000 shared:SSL:10m;ssl_protocols TLSv1.2 TLSv1.3;ssl_ciphers "ECDHE-ECDSA-CHACHA20-POLY1305 ECDHE-RSA-CHACHA20-POLY1305 DHE-RSA-CHACHA20-POLY1305";ssl_ocsp off;ssl_prefer_server_ciphers on;
根据需要对 ssl 的证书目录和 ssl 支持的协议和加密方式进行更改,配置完成之后就可以使用 curl 对站点进行测试,查看是否配置生效。




