go-proxyproto icon indicating copy to clipboard operation
go-proxyproto copied to clipboard

Protocol: Keep listener listening if we don't trust the upstream address

Open peteski22 opened this issue 8 months ago • 5 comments

This PR is designed to prevent listeners being stopped when an error is returned, if the upstream connection address is not trusted (ErrInvalidUpstream). Instead, we continue to close the connection but now the Accept method has a for loop to continue looking for other connections to accept.

In using this library we discovered that the listener Accept method returning an error caused the listener to be closed and never reopened when trying to serve HTTP endpoints.

The change was based on github.com/armon/go-proxyproto/ which does something similar with the loop and checking for a particular type of error.

Notes:

See: net/http/server.go => Serve(l net.Listener)

https://cs.opensource.google/go/go/+/master:src/net/http/server.go;l=3333-3351

rw, err := l.Accept()
if err != nil {
	if srv.shuttingDown() {
		return ErrServerClosed
	}
	if ne, ok := err.(net.Error); ok && ne.Temporary() {
		if tempDelay == 0 {
			tempDelay = 5 * time.Millisecond
		} else {
			tempDelay *= 2
		}
		if max := 1 * time.Second; tempDelay > max {
			tempDelay = max
		}
		srv.logf("http: Accept error: %v; retrying in %v", err, tempDelay)
		time.Sleep(tempDelay)
		continue
	}
	return err
}

Above we end up returning the err at the end, which stops the Serve method (so prevents us listening).

peteski22 avatar Jun 14 '24 10:06 peteski22