diff --git a/pkg/event_processor/http2_request.go b/pkg/event_processor/http2_request.go index ac83c6073..dffa339e8 100644 --- a/pkg/event_processor/http2_request.go +++ b/pkg/event_processor/http2_request.go @@ -27,8 +27,7 @@ import ( "golang.org/x/net/http2/hpack" ) -const H2Magic = "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n" -const H2MagicLen = len(H2Magic) +const ClientPrefaceLen = len(http2.ClientPreface) type HTTP2Request struct { framer *http2.Framer @@ -40,9 +39,13 @@ type HTTP2Request struct { } func (h2r *HTTP2Request) detect(payload []byte) error { - data := string(payload[0:H2MagicLen]) - if data != H2Magic { - return errors.New("Not match http2 magic") + payloadLen := len(payload) + if payloadLen < ClientPrefaceLen { + return errors.New("Payload less than http2 ClientPreface") + } + data := string(payload[0:ClientPrefaceLen]) + if data != http2.ClientPreface { + return errors.New("Not match http2 ClientPreface") } return nil } @@ -83,7 +86,7 @@ func (h2r *HTTP2Request) IsDone() bool { } func (h2r *HTTP2Request) Display() []byte { - _, err := h2r.bufReader.Discard(H2MagicLen) + _, err := h2r.bufReader.Discard(ClientPrefaceLen) if err != nil { log.Println("[http2 request] Discard HTTP2 Magic error:", err) return h2r.reader.Bytes() diff --git a/pkg/event_processor/http2_request_test.go b/pkg/event_processor/http2_request_test.go index 6124dcb58..13cf69cdc 100644 --- a/pkg/event_processor/http2_request_test.go +++ b/pkg/event_processor/http2_request_test.go @@ -40,7 +40,7 @@ func TestHttp2RequestParser(t *testing.T) { } t.Logf("TestHttp2RequestParser: wrot body:%d", i) - _, err = h2r.bufReader.Discard(H2MagicLen) + _, err = h2r.bufReader.Discard(ClientPrefaceLen) if err != nil { t.Logf("[http2 request] Discard HTTP2 Magic error:%v", err) } diff --git a/pkg/event_processor/http2_response.go b/pkg/event_processor/http2_response.go index 2a2d4112b..ffe4f4bb1 100644 --- a/pkg/event_processor/http2_response.go +++ b/pkg/event_processor/http2_response.go @@ -18,6 +18,7 @@ import ( "bufio" "bytes" "compress/gzip" + "errors" "fmt" "io" "log" @@ -26,6 +27,22 @@ import ( "golang.org/x/net/http2/hpack" ) +const frameHeaderLen = 9 + +// http2.FrameType +// const ( +// FrameData FrameType = 0x0 +// FrameHeaders FrameType = 0x1 +// FramePriority FrameType = 0x2 +// FrameRSTStream FrameType = 0x3 +// FrameSettings FrameType = 0x4 +// FramePushPromise FrameType = 0x5 +// FramePing FrameType = 0x6 +// FrameGoAway FrameType = 0x7 +// FrameWindowUpdate FrameType = 0x8 +// FrameContinuation FrameType = 0x9 +// ) + type HTTP2Response struct { framer *http2.Framer packerType PacketType @@ -36,15 +53,37 @@ type HTTP2Response struct { } func (h2r *HTTP2Response) detect(payload []byte) error { - rd := bytes.NewReader(payload) - buf := bufio.NewReader(rd) - framer := http2.NewFramer(nil, buf) - framer.ReadMetaHeaders = hpack.NewDecoder(0, nil) - _, err := framer.ReadFrame() - if err != nil { - return err + payloadLen := len(payload) + if payloadLen < frameHeaderLen { + return errors.New("Payload less than http2 frame Header") + } + // https://httpwg.org/specs/rfc7540.html#FrameHeader + // All frames begin with a fixed 9-octet header followed by a variable-length payload. + // + // +-----------------------------------------------+ + // | Length (24) | + // +---------------+---------------+---------------+ + // | Type (8) | Flags (8) | + // +-+-------------+---------------+-------------------------------+ + // |R| Stream Identifier (31) | + // +=+=============================================================+ + // | Frame Payload (0...) ... + // +---------------------------------------------------------------+ + data := payload[0:frameHeaderLen] + // currentFrameLen := uint32(data[0])<<16 | uint32(data[1])<<8 | uint32(data[2]) + currentFrameType := http2.FrameType(data[3]) + // Frame type in http2.FrameType + if currentFrameType > http2.FrameContinuation { + return errors.New("Invalid frame type") + } + // R: A reserved 1-bit field. + // The semantics of this bit are undefined, and the bit MUST remain unset (0x0) when + // sending and MUST be ignored when receiving. + reservedBit := uint32(data[5]) >> 7 + if reservedBit == 0 { + return nil } - return nil + return errors.New("Invalid reserved bit in frame header") } func (h2r *HTTP2Response) Init() {