// Package fastlyxff provides Fastly CDN IP range management for trusted proxy handling. // // This package parses Fastly's public IP ranges JSON file and generates Echo framework // trust options for proper client IP extraction from X-Forwarded-For headers. // It's designed specifically for services deployed behind Fastly's CDN that need // to identify real client IPs for logging, rate limiting, and security purposes. // // Fastly publishes their edge server IP ranges in a JSON format that this package // consumes to automatically configure trusted proxy ranges. This ensures that // X-Forwarded-For headers are only trusted when they originate from legitimate // Fastly edge servers. // // Key features: // - Automatic parsing of Fastly's IP ranges JSON format // - Support for both IPv4 and IPv6 address ranges // - Echo framework integration via TrustOption generation // - CIDR notation parsing and validation // // The JSON file typically contains IP ranges in this format: // // { // "addresses": ["23.235.32.0/20", "43.249.72.0/22", ...], // "ipv6_addresses": ["2a04:4e40::/32", "2a04:4e42::/32", ...] // } package fastlyxff import ( "encoding/json" "net" "net/netip" "os" "github.com/labstack/echo/v4" ) // FastlyXFF represents Fastly's published IP ranges for their CDN edge servers. // This structure matches the JSON format provided by Fastly for their public IP ranges. // It contains separate lists for IPv4 and IPv6 CIDR ranges. type FastlyXFF struct { IPv4 []string `json:"addresses"` // IPv4 CIDR ranges (e.g., "23.235.32.0/20") IPv6 []string `json:"ipv6_addresses"` // IPv6 CIDR ranges (e.g., "2a04:4e40::/32") } // TrustedNets holds parsed network prefixes for efficient IP range checking. // This type is currently unused but reserved for future optimizations // where frequent IP range lookups might benefit from pre-parsed prefixes. type TrustedNets struct { prefixes []netip.Prefix // Parsed network prefixes for efficient lookups } // New loads and parses Fastly IP ranges from a JSON file. // The file should contain Fastly's published IP ranges in their standard JSON format. // // Parameters: // - fileName: Path to the Fastly IP ranges JSON file // // Returns the parsed FastlyXFF structure or an error if the file cannot be // read or the JSON format is invalid. func New(fileName string) (*FastlyXFF, error) { b, err := os.ReadFile(fileName) if err != nil { return nil, err } d := FastlyXFF{} err = json.Unmarshal(b, &d) if err != nil { return nil, err } return &d, nil } // EchoTrustOption converts Fastly IP ranges into Echo framework trust options. // This method generates trust configurations that tell Echo to accept X-Forwarded-For // headers only from Fastly's edge servers, ensuring accurate client IP extraction. // // The generated trust options should be used with Echo's IP extractor: // // options, err := fastlyRanges.EchoTrustOption() // if err != nil { // return err // } // e.IPExtractor = echo.ExtractIPFromXFFHeader(options...) // // Returns a slice of Echo trust options or an error if any CIDR range cannot be parsed. func (xff *FastlyXFF) EchoTrustOption() ([]echo.TrustOption, error) { ranges := []echo.TrustOption{} for _, s := range append(xff.IPv4, xff.IPv6...) { _, cidr, err := net.ParseCIDR(s) if err != nil { return nil, err } trust := echo.TrustIPRange(cidr) ranges = append(ranges, trust) } return ranges, nil }