Something went wrong. Try again.
Caddy module to require at-proto authentication and restrict routes to DIDs
Something went wrong. Try again.
4.0 kB · 151 lines
Go
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152package resolver
import ( "context" "fmt" "net" "net/http" "strings" "time"
"github.com/bluesky-social/indigo/atproto/identity" "github.com/bluesky-social/indigo/atproto/syntax")
// Resolver handles AT Protocol identity resolution (Handles, DID:PLC, DID:Web).type Resolver struct { dir identity.Directory}
// New initializes a new identity resolver using the default Bluesky directory.// This handles DNS TXT, HTTPS well-known, PLC, and DID:Web lookups with caching.func New() *Resolver { return &Resolver{ dir: identity.DefaultDirectory(), }}
// NewWithAllowedCIDRs initializes a new identity resolver with a custom HTTP client// that allows connections to the specified private CIDRs.func NewWithAllowedCIDRs(allowedCIDRs []net.IPNet) *Resolver { base := identity.BaseDirectory{ HTTPClient: createCustomHTTPClient(allowedCIDRs), }
cached := identity.NewCacheDirectory(&base, 250000, time.Hour*24, time.Minute*2, time.Minute*5)
return &Resolver{ dir: cached, }}
func createCustomHTTPClient(allowedCIDRs []net.IPNet) http.Client { if len(allowedCIDRs) == 0 { return http.Client{} }
transport := http.DefaultTransport.(*http.Transport).Clone() originalDial := transport.DialContext
transport.DialContext = func(ctx context.Context, network, addr string) (net.Conn, error) { host, _, err := net.SplitHostPort(addr) if err != nil { host = addr }
ip := net.ParseIP(host) if ip == nil { addrs, err := net.DefaultResolver.LookupIP(ctx, "ip", host) if err != nil { return nil, fmt.Errorf("failed to resolve %s: %w", host, err) } for _, a := range addrs { if isPublicIP(a) { return originalDial(ctx, network, addr) } for _, cidr := range allowedCIDRs { if cidr.Contains(a) { return originalDial(ctx, network, addr) } } } return nil, fmt.Errorf("resolved IP for %s is not public and not in allowed private CIDRs", host) }
if isPublicIP(ip) { return originalDial(ctx, network, addr) }
for _, cidr := range allowedCIDRs { if cidr.Contains(ip) { return originalDial(ctx, network, addr) } }
return nil, fmt.Errorf("address %s is not public and not in allowed private CIDRs", addr) }
return http.Client{ Transport: transport, Timeout: 10 * time.Second, }}
func isPublicIP(ip net.IP) bool { if ip.IsLoopback() || ip.IsLinkLocalUnicast() || ip.IsUnspecified() { return false } if ip4 := ip.To4(); ip4 != nil { return (ip4[0] != 10) && (ip4[0] != 172 || ip4[1] < 16 || ip4[1] > 31) && (ip4[0] != 192 || ip4[1] != 168) } _, ipv6private, _ := net.ParseCIDR("fc00::/7") return ipv6private == nil || !ipv6private.Contains(ip)}
// ResolveIdentifier converts either a handle (e.g., @user.com) or a DID into// a verified DID, validating it against the directory.func (r *Resolver) ResolveIdentifier(ctx context.Context, ident string) (string, error) { ident = strings.TrimPrefix(ident, "@")
atID, err := syntax.ParseAtIdentifier(ident) if err != nil { return "", fmt.Errorf("invalid identifier '%s': %w", ident, err) }
id, err := r.dir.Lookup(ctx, atID) if err != nil { return "", fmt.Errorf("failed to resolve identity '%s': %w", ident, err) }
if id == nil { return "", fmt.Errorf("identity '%s' not found", ident) }
return id.DID.String(), nil}
// GetPDSEndpoint returns the Personal Data Server (PDS) URL for a given DID or handle.func (r *Resolver) GetPDSEndpoint(ctx context.Context, ident string) (string, error) { ident = strings.TrimPrefix(ident, "@")
atID, err := syntax.ParseAtIdentifier(ident) if err != nil { return "", fmt.Errorf("invalid identifier '%s': %w", ident, err) }
id, err := r.dir.Lookup(ctx, atID) if err != nil { return "", fmt.Errorf("failed to resolve identity '%s': %w", ident, err) }
if id == nil { return "", fmt.Errorf("identity '%s' not found", ident) }
pds := id.PDSEndpoint() if pds == "" { return "", fmt.Errorf("no PDS endpoint found for identity '%s'", ident) }
return pds, nil}