this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

identity: add fallback DNS servers

+67 -1
+2
atproto/identity/base_directory.go
··· 26 26 TryAuthoritativeDNS bool 27 27 // set of handle domain suffixes for for which DNS handle resolution will be skipped 28 28 SkipDNSDomainSuffixes []string 29 + // set of fallback DNS servers (eg, domain registrars) to try as a fallback. each entry should be "ip:port", eg "8.8.8.8:53" 30 + FallbackDNSServers []string 29 31 } 30 32 31 33 var _ Directory = (*BaseDirectory)(nil)
+45 -1
atproto/identity/handle.go
··· 89 89 return parseTXTResp(res) 90 90 } 91 91 92 + // variant of ResolveHandleDNS which uses any configured fallback DNS servers 93 + func (d *BaseDirectory) ResolveHandleDNSFallback(ctx context.Context, handle syntax.Handle) (syntax.DID, error) { 94 + retErr := fmt.Errorf("no fallback servers configured") 95 + var dnsErr *net.DNSError 96 + for _, ns := range d.FallbackDNSServers { 97 + // create a custom resolver to use the specific nameserver for TXT lookup 98 + resolver := &net.Resolver{ 99 + PreferGo: true, 100 + Dial: func(ctx context.Context, network, address string) (net.Conn, error) { 101 + rd := net.Dialer{ 102 + Timeout: time.Second * 5, 103 + } 104 + return rd.DialContext(ctx, network, ns) 105 + }, 106 + } 107 + res, err := resolver.LookupTXT(ctx, "_atproto."+handle.String()) 108 + // check for NXDOMAIN 109 + if errors.As(err, &dnsErr) { 110 + if dnsErr.IsNotFound { 111 + retErr = ErrHandleNotFound 112 + continue 113 + } 114 + } 115 + if err != nil { 116 + retErr = err 117 + continue 118 + } 119 + ret, err := parseTXTResp(res) 120 + if err != nil { 121 + retErr = err 122 + continue 123 + } 124 + return ret, nil 125 + } 126 + return "", retErr 127 + } 128 + 92 129 func (d *BaseDirectory) ResolveHandleWellKnown(ctx context.Context, handle syntax.Handle) (syntax.DID, error) { 93 130 req, err := http.NewRequestWithContext(ctx, "GET", fmt.Sprintf("https://%s/.well-known/atproto-did", handle), nil) 94 131 if err != nil { ··· 138 175 if tryDNS { 139 176 start := time.Now() 140 177 triedAuthoritative := false 178 + triedFallback := false 141 179 did, dnsErr = d.ResolveHandleDNS(ctx, handle) 142 180 if dnsErr == ErrHandleNotFound && d.TryAuthoritativeDNS { 143 181 slog.Info("attempting authoritative handle DNS resolution", "handle", handle) ··· 145 183 // try harder with authoritative lookup 146 184 did, dnsErr = d.ResolveHandleDNSAuthoritative(ctx, handle) 147 185 } 186 + if dnsErr == ErrHandleNotFound && len(d.FallbackDNSServers) > 0 { 187 + slog.Info("attempting fallback DNS resolution", "handle", handle) 188 + triedFallback = true 189 + // try harder with fallback lookup 190 + did, dnsErr = d.ResolveHandleDNSFallback(ctx, handle) 191 + } 148 192 elapsed := time.Since(start) 149 - slog.Debug("resolve handle DNS", "handle", handle, "err", dnsErr, "did", did, "authoritative", triedAuthoritative, "duration_ms", elapsed.Milliseconds()) 193 + slog.Debug("resolve handle DNS", "handle", handle, "err", dnsErr, "did", did, "authoritative", triedAuthoritative, "fallback", triedFallback, "duration_ms", elapsed.Milliseconds()) 150 194 if nil == dnsErr { // if *not* an error 151 195 return did, nil 152 196 }
+20
atproto/identity/live_test.go
··· 115 115 } 116 116 wg.Wait() 117 117 } 118 + 119 + func TestFallbackDNS(t *testing.T) { 120 + assert := assert.New(t) 121 + ctx := context.Background() 122 + handle := syntax.Handle("no-such-record.atproto.com") 123 + dir := BaseDirectory{ 124 + FallbackDNSServers: []string{"1.1.1.1:53", "8.8.8.8:53"}, 125 + } 126 + 127 + // valid DNS server 128 + _, err := dir.LookupHandle(ctx, handle) 129 + assert.Error(err) 130 + assert.Equal(ErrHandleNotFound, err) 131 + 132 + // invalid DNS server syntax 133 + dir.FallbackDNSServers = []string{"_"} 134 + _, err = dir.LookupHandle(ctx, handle) 135 + assert.Error(err) 136 + assert.NotEqual(ErrHandleNotFound, err) 137 + }