-
Notifications
You must be signed in to change notification settings - Fork 4.6k
internal/transport: skip log on EOF when reading client preface #4458
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -125,9 +125,14 @@ type http2Server struct { | |
| connectionID uint64 | ||
| } | ||
|
|
||
| // newHTTP2Server constructs a ServerTransport based on HTTP2. ConnectionError is | ||
| // returned if something goes wrong. | ||
| func newHTTP2Server(conn net.Conn, config *ServerConfig) (_ ServerTransport, err error) { | ||
| // NewServerTransport creates a http2 transport with conn and configuration | ||
| // options from config. | ||
| // | ||
| // It returns a non-nil transport and a nil error on success. On failure, it | ||
| // returns a non-nil transport and a nil-error. For a special case where the | ||
| // underlying conn gets closed before the client preface could be read, it | ||
| // returns a nil transport and a nil error. | ||
| func NewServerTransport(conn net.Conn, config *ServerConfig) (_ ServerTransport, err error) { | ||
| writeBufSize := config.WriteBufferSize | ||
| readBufSize := config.ReadBufferSize | ||
| maxHeaderListSize := defaultServerMaxHeaderListSize | ||
|
|
@@ -266,6 +271,13 @@ func newHTTP2Server(conn net.Conn, config *ServerConfig) (_ ServerTransport, err | |
| // Check the validity of client preface. | ||
| preface := make([]byte, len(clientPreface)) | ||
| if _, err := io.ReadFull(t.conn, preface); err != nil { | ||
| // In deployments where a gRPC server runs behind a cloud load balancer | ||
| // which performs regular TCP level health checks, the connection is | ||
| // closed immediately by the latter. Skipping the error here will help | ||
| // reduce log clutter. | ||
| if err == io.EOF { | ||
| return nil, nil | ||
dfawley marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| } | ||
| return nil, connectionErrorf(false, err, "transport: http2Server.HandleStreams failed to receive the preface from client: %v", err) | ||
|
Comment on lines
+274
to
281
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to only matter for plaintext connections, or else the peer is finishing the handshake. Is this possibly an incomplete fix? Where do we handle handshaker errors? Do they log?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We initiate the handshake from My understanding is that cloud load balancers which perform TCP handshakes do not use TLS. But yes, one could still create a log storm by trying to present an invalid certificate. But server deployments anyway need to handle situations like this (with some kind of firewall) since log storm is not the only problem in such sitations. Wdyt?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
But these logs are from the server, so it doesn't matter what the client is attempting to use. If it connects without TLS then the server's handshaker will fail it before we get here.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. What we could do is that we could handle
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, something like that might be a good idea, too.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Done. Made the change to |
||
| } | ||
| if !bytes.Equal(preface, clientPreface) { | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What about
io.ErrUnexpectedEOF?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about this we check for that in line 283. But I decided not to have it here because we did not have it prior to the refactor in 1739d3b
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this a regression? Maybe the logs were happening before that refactor, too? I would think either error could be safely skipped.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the documentation from
ReadFull:Given that we are trying to avoid logging for the case where the connection is closed as soon as it is made, I feel it makes more sense to only consider
io.EOF. In the case ofio.ErrUnexpectedEOF, we would still have some bytes read, which seems like a totally different case and worth logging.What do you think?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That seems reasonable.