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.
|
// Plugins can access the original HTTP request to retrieve headers, client IP, and metadata.
|
||||||
type HTTPRequestKey struct{}
|
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.
|
// NewServerHTTPS returns a new CoreDNS HTTPS server and compiles all plugins in to it.
|
||||||
func NewServerHTTPS(addr string, group []*Config) (*ServerHTTPS, error) {
|
func NewServerHTTPS(addr string, group []*Config) (*ServerHTTPS, error) {
|
||||||
s, err := NewServer(addr, group)
|
s, err := NewServer(addr, group)
|
||||||
@@ -93,9 +90,6 @@ func NewServerHTTPS(addr string, group []*Config) (*ServerHTTPS, error) {
|
|||||||
WriteTimeout: s.WriteTimeout,
|
WriteTimeout: s.WriteTimeout,
|
||||||
IdleTimeout: s.IdleTimeout,
|
IdleTimeout: s.IdleTimeout,
|
||||||
ErrorLog: stdlog.New(&loggerAdapter{}, "", 0),
|
ErrorLog: stdlog.New(&loggerAdapter{}, "", 0),
|
||||||
ConnContext: func(ctx context.Context, c net.Conn) context.Context {
|
|
||||||
return context.WithValue(ctx, connAddrKey{}, c.LocalAddr())
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
maxConnections := DefaultHTTPSMaxConnections
|
maxConnections := DefaultHTTPSMaxConnections
|
||||||
if len(group) > 0 && group[0] != nil && group[0].MaxHTTPSConnections != nil {
|
if len(group) > 0 && group[0] != nil && group[0].MaxHTTPSConnections != nil {
|
||||||
@@ -176,9 +170,9 @@ func (s *ServerHTTPS) Stop() error {
|
|||||||
return nil
|
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 {
|
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 addr
|
||||||
}
|
}
|
||||||
return s.listenAddr
|
return s.listenAddr
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ func TestDoHWriterLaddrFromConnContext(t *testing.T) {
|
|||||||
ppDst := &net.TCPAddr{IP: net.ParseIP("10.0.0.1"), Port: 443}
|
ppDst := &net.TCPAddr{IP: net.ParseIP("10.0.0.1"), Port: 443}
|
||||||
|
|
||||||
r := httptest.NewRequest(http.MethodPost, "/dns-query", io.NopCloser(bytes.NewReader(buf)))
|
r := httptest.NewRequest(http.MethodPost, "/dns-query", io.NopCloser(bytes.NewReader(buf)))
|
||||||
ctx := context.WithValue(r.Context(), connAddrKey{}, ppDst)
|
ctx := context.WithValue(r.Context(), http.LocalAddrContextKey, ppDst)
|
||||||
r = r.WithContext(ctx)
|
r = r.WithContext(ctx)
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
@@ -230,7 +230,7 @@ func TestDoHWriterLaddrFallback(t *testing.T) {
|
|||||||
t.Fatal(err)
|
t.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// No connAddrKey in context; should fall back to s.listenAddr.
|
// No LocalAddrContextKey in context; should fall back to s.listenAddr.
|
||||||
r := httptest.NewRequest(http.MethodPost, "/dns-query", io.NopCloser(bytes.NewReader(buf)))
|
r := httptest.NewRequest(http.MethodPost, "/dns-query", io.NopCloser(bytes.NewReader(buf)))
|
||||||
w := httptest.NewRecorder()
|
w := httptest.NewRecorder()
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user