Skip to content

Commit e5ca8db

Browse files
committed
check http version while reading the connection
1 parent b1e8ece commit e5ca8db

File tree

2 files changed

+21
-19
lines changed

2 files changed

+21
-19
lines changed

modules/caddyhttp/app.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,8 @@ func (app *App) Start() error {
552552
// check if the connection is h2c
553553
ln = &http2Listener{
554554
useTLS: useTLS,
555-
useH2C: h2cok,
555+
useH1: h1ok,
556+
useH2: h2ok || h2cok,
556557
Listener: ln,
557558
logger: app.logger,
558559
}

modules/caddyhttp/http2listener.go

Lines changed: 19 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,11 @@ type connectionStater interface {
2121
// can do this.
2222
// 2. After wrapping the connection doesn't implement connectionStater, emit a warning so that listener
2323
// wrapper authors will hopefully implement it.
24+
// 3. check if the connection matches a specific http version. h2/h2c has a distinct preface.
2425
type http2Listener struct {
2526
useTLS bool
26-
useH2C bool
27+
useH1 bool
28+
useH2 bool
2729
net.Listener
2830
logger *zap.Logger
2931
}
@@ -39,35 +41,32 @@ func (h *http2Listener) Accept() (net.Conn, error) {
3941
if _, ok := conn.(connectionStater); !ok {
4042
h.logger.Warn("tls is enabled, but listener wrapper returns a connection that doesn't implement connectionStater")
4143
}
42-
return &http2Conn{
43-
idx: len(http2.ClientPreface),
44-
Conn: conn,
45-
}, nil
4644
}
4745

4846
if _, ok := conn.(connectionStater); ok {
4947
h.logger.Warn("tls is disabled, but listener wrapper returns a connection that implements connectionStater")
50-
return &http2Conn{
51-
idx: len(http2.ClientPreface),
52-
Conn: conn,
53-
}, nil
5448
}
5549

56-
if h.useH2C {
50+
// if both h1 and h2 are enabled, we don't need to check the preface
51+
if h.useH1 && h.useH2 {
5752
return &http2Conn{
5853
idx: len(http2.ClientPreface),
5954
Conn: conn,
6055
}, nil
6156
}
6257

6358
return &http2Conn{
64-
Conn: conn,
59+
h2Expected: h.useH2,
60+
Conn: conn,
6561
}, nil
6662
}
6763

6864
type http2Conn struct {
69-
// check h2 preface if it's smaller that the preface
65+
// current index where the preface should match,
66+
// no matching is done if idx is >= len(http2.ClientPreface)
7067
idx int
68+
// whether the connection is expected to be h2/h2c
69+
h2Expected bool
7170
// log if one such connection is detected
7271
logger *zap.Logger
7372
net.Conn
@@ -79,14 +78,16 @@ func (c *http2Conn) Read(p []byte) (int, error) {
7978
}
8079
n, err := c.Conn.Read(p)
8180
for i := range n {
82-
// mismatch
83-
if p[i] != http2.ClientPreface[c.idx] {
84-
c.idx = len(http2.ClientPreface)
85-
return n, err
81+
// first mismatch, close the connection if h2 is expected
82+
if p[i] != http2.ClientPreface[c.idx] && c.h2Expected {
83+
c.logger.Debug("h1 connection detected, but h1 is not enabled")
84+
_ = c.Conn.Close()
85+
return 0, io.EOF
8686
}
8787
c.idx++
88-
if c.idx == len(http2.ClientPreface) {
89-
c.logger.Warn("h2c connection detected, but h2c is not enabled")
88+
// matching complete
89+
if c.idx == len(http2.ClientPreface) && !c.h2Expected {
90+
c.logger.Debug("h2/h2c connection detected, but h2/h2c is not enabled")
9091
_ = c.Conn.Close()
9192
return 0, io.EOF
9293
}

0 commit comments

Comments
 (0)