mirror of
https://github.com/coredns/coredns.git
synced 2026-06-15 13:40:11 -04:00
dnsserver: use http.LocalAddrContextKey for DoH local address (#8149)
The DoH server resolved the per-connection local address in a custom http.Server.ConnContext callback. ConnContext runs synchronously in the http.Server accept loop, so calling c.LocalAddr() there is a problem when the listener is proxyproto-wrapped: LocalAddr() triggers the PROXY-header read, which blocks the accept loop until the header arrives and head-of-line-blocks acceptance of every other connection. net/http and http2 already populate http.LocalAddrContextKey from the connection in the per-connection serving goroutine (net/http server.go, http2 server_common.go / h2_bundle.go), resolved through the same tls.Conn -> proxyproto.Conn chain. For a proxyproto connection that value is the PROXY header's destination address -- byte-identical to what the custom callback produced -- and it is set off the accept loop on both the HTTP/1.1 and HTTP/2 paths. Drop the custom ConnContext callback and the connKey type, and read http.LocalAddrContextKey in localAddr() instead. The client address is unaffected: it arrives via r.RemoteAddr, which the framework populates natively. Signed-off-by: zongqi-wang <wangzongqi@msn.com>
This commit is contained in:
@@ -52,9 +52,6 @@ func (l *loggerAdapter) Write(p []byte) (n int, err error) {
|
||||
// Plugins can access the original HTTP request to retrieve headers, client IP, and metadata.
|
||||
type HTTPRequestKey struct{}
|
||||
|
||||
// connAddrKey is the context key for the per-connection local address set by ConnContext.
|
||||
type connAddrKey struct{}
|
||||
|
||||
// NewServerHTTPS returns a new CoreDNS HTTPS server and compiles all plugins in to it.
|
||||
func NewServerHTTPS(addr string, group []*Config) (*ServerHTTPS, error) {
|
||||
s, err := NewServer(addr, group)
|
||||
@@ -93,9 +90,6 @@ func NewServerHTTPS(addr string, group []*Config) (*ServerHTTPS, error) {
|
||||
WriteTimeout: s.WriteTimeout,
|
||||
IdleTimeout: s.IdleTimeout,
|
||||
ErrorLog: stdlog.New(&loggerAdapter{}, "", 0),
|
||||
ConnContext: func(ctx context.Context, c net.Conn) context.Context {
|
||||
return context.WithValue(ctx, connAddrKey{}, c.LocalAddr())
|
||||
},
|
||||
}
|
||||
maxConnections := DefaultHTTPSMaxConnections
|
||||
if len(group) > 0 && group[0] != nil && group[0].MaxHTTPSConnections != nil {
|
||||
@@ -176,9 +170,9 @@ func (s *ServerHTTPS) Stop() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// localAddr returns the per-connection local address from context, or s.listenAddr as fallback.
|
||||
// localAddr returns the per-connection local address, or s.listenAddr as fallback.
|
||||
func (s *ServerHTTPS) localAddr(r *http.Request) net.Addr {
|
||||
if addr, ok := r.Context().Value(connAddrKey{}).(net.Addr); ok {
|
||||
if addr, ok := r.Context().Value(http.LocalAddrContextKey).(net.Addr); ok {
|
||||
return addr
|
||||
}
|
||||
return s.listenAddr
|
||||
|
||||
Reference in New Issue
Block a user