mirror of
https://github.com/tailscale/tailscale.git
synced 2026-10-23 03:37:19 +09:00
fixups: will squash before merge
This commit is contained in:
1 parent
ab7caf5fd5
commit
663838c63c
5 files changed
+54
-65
No files matched your search
@@ -31,7 +31,7 @@ import (
|
||||
"tailscale.com/ipn/ipnext"
|
||||
"tailscale.com/ipn/ipnlocal"
|
||||
"tailscale.com/ipn/localapi"
|
||||
tsresolver "tailscale.com/net/dns/resolver"
|
||||
"tailscale.com/net/dns/resolver"
|
||||
"tailscale.com/net/packet"
|
||||
"tailscale.com/net/traffic"
|
||||
"tailscale.com/net/tsaddr"
|
||||
@@ -163,12 +163,12 @@ func (e *extension) installHooks(dph *datapathHandler) error {
|
||||
if !ok {
|
||||
return errors.New("could not access system tun")
|
||||
}
|
||||
resolver := dnsManager.Resolver()
|
||||
if resolver == nil {
|
||||
r := dnsManager.Resolver()
|
||||
if r == nil {
|
||||
return errors.New("dns manager resolver not ready")
|
||||
}
|
||||
|
||||
if err := resolver.RegisterCustomScheme(appc.DNSAddrScheme, func(addr string) (string, error) {
|
||||
if err := r.RegisterCustomScheme(appc.DNSAddrScheme, func(addr string) (string, error) {
|
||||
scheme, appName, ok := strings.Cut(addr, ":")
|
||||
if !ok || scheme != appc.DNSAddrScheme {
|
||||
return "", fmt.Errorf("unexpected conn25 scheme %q", scheme)
|
||||
@@ -196,7 +196,7 @@ func (e *extension) installHooks(dph *datapathHandler) error {
|
||||
|
||||
// Set up the DNS manager to rewrite responses for app domains
|
||||
// to answer with Magic IPs.
|
||||
dnsManager.SetQueryResponseMapper(func(res *tsresolver.Response) []byte {
|
||||
dnsManager.SetQueryResponseMapper(func(res *resolver.Response) []byte {
|
||||
if !e.conn25.isConfigured() {
|
||||
return res.Bs
|
||||
}
|
||||
@@ -1032,7 +1032,7 @@ var passThroughQuestionTypes = set.Of(
|
||||
// mapDNSResponse parses and inspects the DNS response. If the domain
|
||||
// is determined to belong to app this node is client for, it assigns addresses
|
||||
// for connecting and rewrites the response to contain Magic IPs.
|
||||
func (c *Conn25) mapDNSResponse(res *tsresolver.Response) []byte {
|
||||
func (c *Conn25) mapDNSResponse(res *resolver.Response) []byte {
|
||||
var p dnsmessage.Parser
|
||||
buf := res.Bs
|
||||
hdr, err := p.Start(buf)
|
||||
|
||||
@@ -65,14 +65,14 @@ func TestDoH(t *testing.T) {
|
||||
if !ok {
|
||||
t.Fatal("expected DoH")
|
||||
}
|
||||
res, err := f.sendDoH(context.Background(), urlBase, c, someDNSQuestion(t), false)
|
||||
res, err := f.sendDoH(context.Background(), urlBase, c, someDNSQuestion(t))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
c.Transport.(*http.Transport).CloseIdleConnections()
|
||||
|
||||
if res.PeerAPIMeta != nil {
|
||||
t.Errorf("unexpected PeerAPIMeta %+v for non-PeerAPI DoH", res.PeerAPIMeta)
|
||||
if res.DoHMeta == nil {
|
||||
t.Errorf("expected DoHMeta")
|
||||
}
|
||||
|
||||
var p dnsmessage.Parser
|
||||
|
||||
@@ -640,9 +640,7 @@ func (f *forwarder) newDoHClientLocked(cacheKey, urlBase string, allIPs []netip.
|
||||
const dohType = "application/dns-message"
|
||||
|
||||
// sendDoH sends packet as a DoH query to urlBase using client c.
|
||||
// If isPeerAPI is true, urlBase references a PeerAPI's DoH server
|
||||
// and the returned Response has PeerAPIMeta populated.
|
||||
func (f *forwarder) sendDoH(ctx context.Context, urlBase string, c *http.Client, packet []byte, isPeerAPI bool) (*Response, error) {
|
||||
func (f *forwarder) sendDoH(ctx context.Context, urlBase string, c *http.Client, packet []byte) (*Response, error) {
|
||||
ctx = sockstats.WithSockStats(ctx, sockstats.LabelDNSForwarderDoH, f.logf)
|
||||
metricDNSFwdDoH.Add(1)
|
||||
req, err := http.NewRequestWithContext(ctx, "POST", urlBase, bytes.NewReader(packet))
|
||||
@@ -680,15 +678,13 @@ func (f *forwarder) sendDoH(ctx context.Context, urlBase string, c *http.Client,
|
||||
metricDNSFwdDoHErrorBody.Add(1)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
ret := &Response{Bs: res}
|
||||
if isPeerAPI {
|
||||
ret.PeerAPIMeta = &PeerAPIMetadata{
|
||||
RequestURL: hres.Request.URL.Clone(),
|
||||
ResponseHeader: hres.Header.Clone(),
|
||||
}
|
||||
}
|
||||
return ret, nil
|
||||
return &Response{
|
||||
Bs: res,
|
||||
DoHMeta: &DoHMetadata{
|
||||
RequestURL: hres.Request.URL,
|
||||
ResponseHeader: hres.Header,
|
||||
},
|
||||
}, nil
|
||||
}
|
||||
|
||||
var (
|
||||
@@ -717,11 +713,10 @@ func (f *forwarder) send(ctx context.Context, fq *forwardQuery, rr resolverAndDe
|
||||
}()
|
||||
}
|
||||
if strings.HasPrefix(rr.name.Addr, "http://") {
|
||||
const isPeerAPI = true
|
||||
if !buildfeatures.HasPeerAPIClient {
|
||||
return nil, feature.ErrUnavailable
|
||||
}
|
||||
res, err := f.sendDoH(ctx, rr.name.Addr, f.dialer.PeerAPIHTTPClient(), fq.packet, isPeerAPI)
|
||||
res, err := f.sendDoH(ctx, rr.name.Addr, f.dialer.PeerAPIHTTPClient(), fq.packet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -736,9 +731,8 @@ func (f *forwarder) send(ctx context.Context, fq *forwardQuery, rr resolverAndDe
|
||||
// usable when the resolver carries a bootstrap resolution, or when the
|
||||
// URL's host is an IP literal, since we cannot resolve the DoH
|
||||
// server's own name through DNS without recursing through ourselves.
|
||||
const isPeerAPI = false
|
||||
if hc, ok := f.getDoHClientForResolver(rr.name); ok {
|
||||
res, err := f.sendDoH(ctx, rr.name.Addr, hc, fq.packet, isPeerAPI)
|
||||
res, err := f.sendDoH(ctx, rr.name.Addr, hc, fq.packet)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
@@ -1697,9 +1691,9 @@ func (p *closePool) Close() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// PeerAPIMetadata captures data about the HTTP
|
||||
// DoHMetadata captures data about the HTTP
|
||||
// request and response when a DNS request is
|
||||
// forwarded to a PeerAPI DoH server, e.g. for
|
||||
// forwarded to a DoH server, e.g. PeerAPI DoH for
|
||||
// exit nodes or app connectors.
|
||||
//
|
||||
// As of 2026-09-24, the only known consumer is
|
||||
@@ -1708,21 +1702,26 @@ func (p *closePool) Close() error {
|
||||
// a client, and to extract authorization tokens
|
||||
// from the response headers, which it then uses
|
||||
// in further communication with the connector.
|
||||
type PeerAPIMetadata struct {
|
||||
// RequestURL is a clone of the URL of the PeerAPI request
|
||||
type DoHMetadata struct {
|
||||
// RequestURL is the URL of the DoH request
|
||||
// that produced the response.
|
||||
// It is passed as a pointer to avoid allocations.
|
||||
// It should not be modified.
|
||||
RequestURL *url.URL
|
||||
// ResponseHeader is a clone of the PeerAPI HTTP response headers.
|
||||
// ResponseHeader is the DoH HTTP response headers.
|
||||
// It references the actual headers which may or may
|
||||
// not have been sent to the HTTP client.
|
||||
// It should not be modified.
|
||||
ResponseHeader http.Header
|
||||
}
|
||||
|
||||
// Response is a DNS response in bytes, along with metadata
|
||||
// from the PeerAPI DoH server that served it, if it was served
|
||||
// by a PeerAPI DoH server.
|
||||
// from the DoH server that served it, if it was served
|
||||
// by a DoH server.
|
||||
type Response struct {
|
||||
// Bs is the wire-encoded DNS response.
|
||||
Bs []byte
|
||||
// PeerAPIMeta is non-nil if the response came
|
||||
// from a PeerAPI DoH server, and nil otherwise.
|
||||
PeerAPIMeta *PeerAPIMetadata
|
||||
// DoHMeta is non-nil if the response came
|
||||
// from a DoH server, and nil otherwise.
|
||||
DoHMeta *DoHMetadata
|
||||
}
|
||||
@@ -299,7 +299,7 @@ func TestControlDPremiumDoHLive(t *testing.T) {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 15*time.Second)
|
||||
defer cancel()
|
||||
|
||||
res, err := fwd.sendDoH(ctx, urlBase, c, query, false)
|
||||
res, err := fwd.sendDoH(ctx, urlBase, c, query)
|
||||
if err != nil {
|
||||
t.Fatalf("sendDoH: %v", err)
|
||||
}
|
||||
@@ -2479,11 +2479,11 @@ func TestResolversCustomScheme(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestPeerAPIDoH(t *testing.T) {
|
||||
func TestDoHMeta(t *testing.T) {
|
||||
const domain = "example.com."
|
||||
query := makeTestRequest(t, domain, dns.TypeA, 0)
|
||||
response := makeTestResponse(t, domain, dns.RCodeSuccess, netip.MustParseAddr("1.2.3.4"))
|
||||
testHdrVal := "hello from PeerAPI"
|
||||
testHdrVal := "hello from DoH"
|
||||
|
||||
srv := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", dohType)
|
||||
@@ -2495,30 +2495,20 @@ func TestPeerAPIDoH(t *testing.T) {
|
||||
f := &forwarder{logf: t.Logf}
|
||||
urlBase := srv.URL + "/dns-query"
|
||||
|
||||
for _, isPeerAPI := range []bool{true, false} {
|
||||
t.Run(fmt.Sprintf("isPeerAPI=%v", isPeerAPI), func(t *testing.T) {
|
||||
res, err := f.sendDoH(t.Context(), urlBase, srv.Client(), query, isPeerAPI)
|
||||
if err != nil {
|
||||
t.Fatalf("sendDoH: %+v", err)
|
||||
}
|
||||
if !bytes.Equal(res.Bs, response) {
|
||||
t.Errorf("response = %x, want %x", res.Bs, response)
|
||||
}
|
||||
if !isPeerAPI {
|
||||
if res.PeerAPIMeta != nil {
|
||||
t.Errorf("PeerAPIMeta = %+v, want nil", res.PeerAPIMeta)
|
||||
}
|
||||
return
|
||||
}
|
||||
if res.PeerAPIMeta == nil {
|
||||
t.Fatal("PeerAPIMeta = nil, want non-nil")
|
||||
}
|
||||
if want, got := testHdrVal, res.PeerAPIMeta.ResponseHeader.Get("Tailscale-Test"); want != got {
|
||||
t.Errorf("PeerAPIMeta.Header[Tailscale-Test] = %q, want %q", got, want)
|
||||
}
|
||||
if want, got := urlBase, res.PeerAPIMeta.RequestURL.String(); want != got {
|
||||
t.Errorf("PeerAPIMeta.RequestURL = %q, want %q", got, want)
|
||||
}
|
||||
})
|
||||
res, err := f.sendDoH(t.Context(), urlBase, srv.Client(), query)
|
||||
if err != nil {
|
||||
t.Fatalf("sendDoH: %+v", err)
|
||||
}
|
||||
if !bytes.Equal(res.Bs, response) {
|
||||
t.Errorf("response = %x, want %x", res.Bs, response)
|
||||
}
|
||||
if res.DoHMeta == nil {
|
||||
t.Fatal("DoHMeta = nil, want non-nil")
|
||||
}
|
||||
if want, got := testHdrVal, res.DoHMeta.ResponseHeader.Get("Tailscale-Test"); want != got {
|
||||
t.Errorf("DoHMeta.Header[Tailscale-Test] = %q, want %q", got, want)
|
||||
}
|
||||
if want, got := urlBase, res.DoHMeta.RequestURL.String(); want != got {
|
||||
t.Errorf("DoHMeta.RequestURL = %q, want %q", got, want)
|
||||
}
|
||||
}
|
||||
@@ -550,9 +550,9 @@ func (r *Resolver) HandlePeerDNSQuery(ctx context.Context, q []byte, from netip.
|
||||
}
|
||||
}
|
||||
select {
|
||||
case fwdRes, ok := <-ch:
|
||||
case p, ok := <-ch:
|
||||
if ok {
|
||||
return fwdRes.Bs, nil
|
||||
return p.Bs, nil
|
||||
}
|
||||
panic("unexpected close chan")
|
||||
default:
|
||||
|
||||
Reference in new issue
Block a user