You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
97 lines
2.3 KiB
Go
97 lines
2.3 KiB
Go
//go:build dyngoogips
|
|
|
|
package fuckgoogle
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"net"
|
|
"regexp"
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
matchSpfIncludes = regexp.MustCompile(`include:([^ ]+)`)
|
|
matchSpfIPs = regexp.MustCompile(` ip[46]:([^ ]+)`)
|
|
resolver = net.Resolver{
|
|
PreferGo: true,
|
|
Dial: func(ctx context.Context, network, address string) (net.Conn, error) {
|
|
d := net.Dialer{Timeout: time.Millisecond * time.Duration(2000)}
|
|
return d.DialContext(ctx, network, "8.8.8.8:53")
|
|
},
|
|
}
|
|
)
|
|
|
|
// FetchGoogleIPRanges gets IP ranges via the advertised DNS SPF records
|
|
func FetchGoogleIPRanges(ctx context.Context) ([]string, error) {
|
|
return lookupSPF(&resolver, ctx, "google.com")
|
|
}
|
|
|
|
// FetchGoogleIPRangesFull gets IP ranges via DNS SPF records, and includes
|
|
// all that can be trivially found (FetchGoogleIPRanges will miss a couple..)
|
|
func FetchGoogleIPRangesFull(ctx context.Context) ([]string, error) {
|
|
rangeSet := map[string]bool{}
|
|
for _, b := range []string{"", "2", "3", "4", "5", "6", "7", "8", "9"} {
|
|
res, err := lookupSPF(&resolver, ctx, fmt.Sprintf("_netblocks%s.google.com", b))
|
|
if err != nil {
|
|
if dnsErr, ok := err.(*net.DNSError); ok && dnsErr.IsNotFound {
|
|
continue
|
|
}
|
|
return nil, err
|
|
}
|
|
for _, r := range res {
|
|
rangeSet[r] = true
|
|
}
|
|
}
|
|
|
|
// flatten map to list (duplicates)
|
|
ranges := make([]string, 0, len(rangeSet))
|
|
for r := range rangeSet {
|
|
ranges = append(ranges, r)
|
|
}
|
|
return ranges, nil
|
|
}
|
|
|
|
func lookupSPF(r *net.Resolver, ctx context.Context, subject string) ([]string, error) {
|
|
records, err := r.LookupTXT(ctx, subject)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
var includes = make([]string, 0, 4)
|
|
var ipRanges = make([]string, 0, 4)
|
|
for _, rec := range records {
|
|
if !strings.HasPrefix(rec, "v=spf1") {
|
|
continue
|
|
}
|
|
matches := matchSpfIncludes.FindAllStringSubmatch(rec, -1)
|
|
if matches != nil {
|
|
for _, m := range matches {
|
|
if len(m) > 0 {
|
|
includes = append(includes, m[1])
|
|
}
|
|
}
|
|
}
|
|
|
|
ranges := matchSpfIPs.FindAllStringSubmatch(rec, -1)
|
|
if ranges != nil {
|
|
for _, m := range ranges {
|
|
if len(m) > 0 {
|
|
ipRanges = append(ipRanges, m[1])
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for _, inc := range includes {
|
|
rec, err := lookupSPF(r, ctx, inc)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
ipRanges = append(ipRanges, rec...)
|
|
}
|
|
|
|
return ipRanges, err
|
|
}
|