HTTP/2 与 Proxy-Connection 头兼容问题

发表于 2017-11-10   |   分类于 默认分类

问题

最近有部分客户反馈在 Chrome 浏览器偶尔 https 访问部分 URL 报错。但是在 UC 等其他浏览器里面正常。
出现错误截图:

问题排查

通过抓包对比分析发现,在出现问题的请求里面,响应头里面多了 Proxy-Connection: keep-alive 怀疑可能和这个响应头有关。由于 CDN 一个 VIP 节点下有多台机器,不是每次都能命中有 Proxy-Connection: keep-alive 这个响应头的缓存的机器。决定自己搭建环境测试复现。

搭建环境

通过又拍云 CDN 的「 Rewrite 」可以直接添加这个响应头规则 $ADD_RSP_HEADER(Proxy-Connection , keep-alive) 。 就可以轻松测试这样问题了。

测试 HTTP/1.1 没有问题

curl -I https://deqing.b0.upaiyun.com/logo/%E5%8F%88%E6%8B%8D%E4%BA%91_logo1.png
HTTP/1.1 200 OK
Server: marco/1.9
Date: Fri, 10 Nov 2017 07:35:18 GMT
Content-Type: image/png
Content-Length: 24726
Connection: keep-alive
X-Request-Id: 1e93128fbc4f9ddfb92e7081bdfbd5b8
X-Source: U/304
Last-Modified: Thu, 30 Mar 2017 02:20:05 GMT
ETag: "28c62b9b0b8bc913bc2b091bff52e415"
Expires: Sat, 18 Nov 2017 07:33:15 GMT
Cache-Control: max-age=691200
Accept-Ranges: bytes
Age: 123
Via: T.5204.N.1, V.403-zj-fud-207, S.mix-hz-fdi-167, T.101165.M.1, V.mix-hz-fdi-163, T.16.H, M.ctn-zj-lna3-019
Proxy-Connection: keep-alive

测试 HTTP/2 发现错误。

curl -I  https://deqing.b0.upaiyun.com/logo/%E5%8F%88%E6%8B%8D%E4%BA%91_logo1.png --http2
curl: (92) HTTP/2 stream 1 was not closed cleanly: PROTOCOL_ERROR (err 1)    

带 -v 参数发现详细错误 :
http2 error: Invalid HTTP header field was received: frame type: 1, stream: 1, name: [proxy-connection], value: [keep-alive]

curl -I  https://deqing.b0.upaiyun.com/logo/%E5%8F%88%E6%8B%8D%E4%BA%91_logo1.png --http2 -v
*   Trying 183.158.35.59...
* TCP_NODELAY set
* Connected to deqing.b0.upaiyun.com (183.158.35.59) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /usr/local/etc/openssl/cert.pem
  CApath: /usr/local/etc/openssl/certs
* TLSv1.2 (OUT), TLS header, Certificate Status (22):
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Server hello (2):
* TLSv1.2 (IN), TLS handshake, Certificate (11):
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
* TLSv1.2 (IN), TLS handshake, Server finished (14):
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
* TLSv1.2 (OUT), TLS handshake, Finished (20):
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
* TLSv1.2 (IN), TLS handshake, Finished (20):
* SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256
* ALPN, server accepted to use h2
* Server certificate:
*  subject: C=CN; ST=zhejiang; L=hangzhou; O=Hangzhou Weiju Network Ltd.; OU=\U6280\U672F\U90E8; CN=*.b0.upaiyun.com
*  start date: Nov 14 00:00:00 2016 GMT
*  expire date: Dec 12 23:59:59 2017 GMT
*  subjectAltName: host "deqing.b0.upaiyun.com" matched cert's "*.b0.upaiyun.com"
*  issuer: C=US; O=GeoTrust Inc.; CN=GeoTrust SSL CA - G3
*  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 0x7f9cb2002400)
> HEAD /logo/%E5%8F%88%E6%8B%8D%E4%BA%91_logo1.png HTTP/2
> Host: deqing.b0.upaiyun.com
> User-Agent: curl/7.56.1
> Accept: */*
>
* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
* http2 error: Invalid HTTP header field was received: frame type: 1, stream: 1, name: [proxy-connection], value: [keep-alive]
* HTTP/2 stream 1 was not closed cleanly: PROTOCOL_ERROR (err 1)
* Closing connection 0
* TLSv1.2 (OUT), TLS alert, Client hello (1):
curl: (92) HTTP/2 stream 1 was not closed cleanly: PROTOCOL_ERROR (err 1)

看错误提示确实是因为 HTTP/2 与这个响应头有关系:[proxy-connection] 。

解决办法

  1. 暂时方案:通过 「 Rewrite 」规则删除这个响应头 $DEL_RSP_HEADER(Proxy-Connection)
  2. 彻底解决:更新 CDN 上的缓存组件不缓存[proxy-connection] 响应头。
所有用户赞赏通道:

发表新评论

© ICP: 浙ICP备17033011号-1