cloudflare / sslconfig

Cloudflare's Internet facing SSL configuration
BSD 3-Clause "New" or "Revised" License
1.3k stars 132 forks source link

Compatibility issues with nginx 1.13.9 http2_push #96

Closed CarterLi closed 6 years ago

CarterLi commented 6 years ago

It seems that hpack patch has compatibility issue with http2_push, which results in ERR_SPDY_PROTOCOL_ERROR in Chrome

Some debug info

$ nghttp -nv https://test.eoitek.net/test.html
[  0.009] Connected
The negotiated protocol: h2
[  0.011] recv SETTINGS frame <length=18, flags=0x00, stream_id=0>
          (niv=3)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):128]
          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65536]
          [SETTINGS_MAX_FRAME_SIZE(0x05):16777215]
[  0.011] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
          (window_size_increment=2147418112)
[  0.011] send SETTINGS frame <length=12, flags=0x00, stream_id=0>
          (niv=2)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[  0.011] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.011] send PRIORITY frame <length=5, flags=0x00, stream_id=3>
          (dep_stream_id=0, weight=201, exclusive=0)
[  0.011] send PRIORITY frame <length=5, flags=0x00, stream_id=5>
          (dep_stream_id=0, weight=101, exclusive=0)
[  0.011] send PRIORITY frame <length=5, flags=0x00, stream_id=7>
          (dep_stream_id=0, weight=1, exclusive=0)
[  0.011] send PRIORITY frame <length=5, flags=0x00, stream_id=9>
          (dep_stream_id=7, weight=1, exclusive=0)
[  0.011] send PRIORITY frame <length=5, flags=0x00, stream_id=11>
          (dep_stream_id=3, weight=1, exclusive=0)
[  0.011] send HEADERS frame <length=46, flags=0x25, stream_id=13>
          ; END_STREAM | END_HEADERS | PRIORITY
          (padlen=0, dep_stream_id=11, weight=16, exclusive=0)
          ; Open new stream
          :method: GET
          :path: /test.html
          :scheme: https
          :authority: test.eoitek.net
          accept: */*
          accept-encoding: gzip, deflate
          user-agent: nghttp2/1.32.0
[  0.011] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.011] recv (stream_id=13) :method: GET
[  0.011] recv (stream_id=13) :path: /restapi/shopping/v1/cities
[  0.011] recv (stream_id=13) :scheme: https
[  0.011] recv (stream_id=13) :authority: test.eoitek.net
[  0.011] recv (stream_id=13) accept-encoding: gzip, deflate
[  0.011] recv (stream_id=13) user-agent: nghttp2/1.32.0
[  0.011] recv PUSH_PROMISE frame <length=64, flags=0x04, stream_id=13>
          ; END_HEADERS
          (padlen=0, promised_stream_id=2)
[  0.011] recv (stream_id=13) :status: 200
[  0.011] recv (stream_id=13) server: nginx/1.13.12
[  0.011] recv (stream_id=13) date: Sun, 03 Jun 2018 16:43:34 GMT
[  0.011] recv (stream_id=13) content-type: text/html
[  0.012] recv (stream_id=13) last-modified: Sun, 03 Jun 2018 14:39:28 GMT
[  0.012] recv (stream_id=13) vary: Accept-Encoding
[  0.012] recv (stream_id=13) etag: W/"5b13fda0-4e8"
[  0.012] recv (stream_id=13) link: </restapi/shopping/v1/cities>; rel=preload; as=fetch; crossorigin
[  0.012] recv (stream_id=13) content-encoding: gzip
[  0.012] recv HEADERS frame <length=155, flags=0x04, stream_id=13>
          ; END_HEADERS
          (padlen=0)
          ; First response header
[  0.012] recv DATA frame <length=612, flags=0x01, stream_id=13>
          ; END_STREAM
[  0.140] recv (stream_id=2) :status: 200
[  0.140] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
          (last_stream_id=2, error_code=COMPRESSION_ERROR(0x09), opaque_data(0)=[])
Some requests were not processed. total=2, processed=1

Removing --with-http_v2_hpack_enc ( but still keep --with-http_spdy_module ) resolve this issue ( seems )

hakasenyang commented 6 years ago

Hello!

Not a great way, but I can suggest one solution.

Result:

root@hakase:~/# nghttp -ns https://hakase.pw/
***** Statistics *****

Request timing:
  responseEnd: the  time  when  last  byte of  response  was  received
               relative to connectEnd
 requestStart: the time  just before  first byte  of request  was sent
               relative  to connectEnd.   If  '*' is  shown, this  was
               pushed by server.
      process: responseEnd - requestStart
         code: HTTP status code
         size: number  of  bytes  received as  response  body  without
               inflation.
          URI: request URI

see http://www.w3.org/TR/resource-timing/#processing-model

sorted by 'complete'

id  responseEnd requestStart  process code size request path
 13      +450us        +71us    379us  200  691 /
  4      +692us *     +350us    342us  404   1K /seized2.png
  2     +6.18ms *     +323us   5.86ms  200 605K /seized.png

Use this patch. This patch has not been fully tested.

hakasenyang commented 6 years ago

Okay!

I have completed a push error patch for hpack.

The following results are displayed. Test site: https://test.hakase.io/

root@hakase:~# nghttp -ns https://test.hakase.io/
***** Statistics *****

Request timing:
  responseEnd: the  time  when  last  byte of  response  was  received
               relative to connectEnd
 requestStart: the time  just before  first byte  of request  was sent
               relative  to connectEnd.   If  '*' is  shown, this  was
               pushed by server.
      process: responseEnd - requestStart
         code: HTTP status code
         size: number  of  bytes  received as  response  body  without
               inflation.
          URI: request URI

see http://www.w3.org/TR/resource-timing/#processing-model

sorted by 'complete'

id  responseEnd requestStart  process code size request path
 13      +414us        +80us    334us  200  691 /
  4      +651us *     +311us    339us  404   1K /seized2.png
  2     +6.04ms *     +282us   5.76ms  200 605K /seized.png
root@hakase:~# nghttp -nv https://test.hakase.io
[  0.005] Connected
The negotiated protocol: h2
[  0.007] recv SETTINGS frame <length=18, flags=0x00, stream_id=0>
          (niv=3)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):512]
          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):262144]
          [SETTINGS_MAX_FRAME_SIZE(0x05):16777215]
[  0.007] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
          (window_size_increment=2147418112)
[  0.007] send SETTINGS frame <length=12, flags=0x00, stream_id=0>
          (niv=2)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[  0.007] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.007] send PRIORITY frame <length=5, flags=0x00, stream_id=3>
          (dep_stream_id=0, weight=201, exclusive=0)
[  0.007] send PRIORITY frame <length=5, flags=0x00, stream_id=5>
          (dep_stream_id=0, weight=101, exclusive=0)
[  0.007] send PRIORITY frame <length=5, flags=0x00, stream_id=7>
          (dep_stream_id=0, weight=1, exclusive=0)
[  0.007] send PRIORITY frame <length=5, flags=0x00, stream_id=9>
          (dep_stream_id=7, weight=1, exclusive=0)
[  0.007] send PRIORITY frame <length=5, flags=0x00, stream_id=11>
          (dep_stream_id=3, weight=1, exclusive=0)
[  0.007] send HEADERS frame <length=38, flags=0x25, stream_id=13>
          ; END_STREAM | END_HEADERS | PRIORITY
          (padlen=0, dep_stream_id=11, weight=16, exclusive=0)
          ; Open new stream
          :method: GET
          :path: /
          :scheme: https
          :authority: test.hakase.io
          accept: */*
          accept-encoding: gzip, deflate
          user-agent: nghttp2/1.31.1
[  0.007] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.007] recv (stream_id=13) :method: GET
[  0.007] recv (stream_id=13) :path: /seized.png
[  0.007] recv (stream_id=13) :scheme: https
[  0.007] recv (stream_id=13) :authority: test.hakase.io
[  0.007] recv (stream_id=13) accept-encoding: gzip, deflate
[  0.007] recv (stream_id=13) user-agent: nghttp2/1.31.1
[  0.007] recv PUSH_PROMISE frame <length=86, flags=0x04, stream_id=13>
          ; END_HEADERS
          (padlen=0, promised_stream_id=2)

...................

I uploaded a patch file to my repository. Please test my patch file.

https://github.com/hakasenyang/openssl-patch

kn007 commented 6 years ago

@hakasenyang after patch other patch with hpack, then using nginx_hpack_push_fix.patch, compile failed

hakasenyang commented 6 years ago

@kn007 Hello! Please let me know about the compilation error.

hakasenyang commented 6 years ago

OMG!!! My mistake. Some sources were missing.

Please re-download and test again.

Build test : auto/configure --with-http_v2_module --with-http_v2_hpack_enc

root@hakase:~/nginx/objs# ./nginx -V
nginx version: nginx/1.15.0
built by gcc 8.1.0 (GCC) 
configure arguments: --with-http_v2_module --with-http_v2_hpack_enc
kn007 commented 6 years ago

Test pass now.~

CarterLi commented 6 years ago

Great @hakasenyang! Thanks for your patch. It helps a lot.