Last active
April 14, 2020 04:59
-
-
Save rpomykala/951812e4c604fd1cecaabdcec2f40d8d to your computer and use it in GitHub Desktop.
Gets all DNS records and formats it into a map of fqdn + short answer, converting the domain from reverse to forward
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"log" | |
"net/http" | |
"os" | |
"time" | |
"net/url" | |
"net" | |
"strings" | |
api "gopkg.in/ns1/ns1-go.v2/rest" | |
) | |
// !!! IMPORTANT!!!! | |
// nsone does not include dot after in-addr.arpa domain in it's DNS records | |
// !!! | |
const ( | |
// IP4arpa is the reverse tree suffix for v4 IP addresses. | |
IP4arpa = ".in-addr.arpa" | |
// IP6arpa is the reverse tree suffix for v6 IP addresses. | |
IP6arpa = ".ip6.arpa" | |
) | |
// map of fqdn --> DNSRecord | |
type DNSRecordsMap map[string]DNSRecord | |
type DNSRecord struct { | |
FQDN string | |
Record interface{} | |
} | |
func (m DNSRecordsMap) Add(record DNSRecord) { | |
m[strings.ToLower(record.FQDN)] = record | |
} | |
func main() { | |
k := os.Getenv("NS1_APIKEY") | |
if k == "" { | |
fmt.Println("NS1_APIKEY environment variable is not set, giving up") | |
os.Exit(1) | |
} | |
httpClient := &http.Client{Timeout: time.Second * 10} | |
client := api.NewClient(httpClient, api.SetAPIKey(k)) | |
//Using Riot's DEV DNS endpoint | |
client.Endpoint, _ = url.Parse("https://dns-dev.riotgames.io/v1/zones") | |
//Returns all active zones and basic zone configuration details for each. | |
zones, _, err := client.Zones.List() | |
if err != nil { | |
log.Fatalf("Error getting zones %v", err) | |
} | |
dnsRecordMap := make(DNSRecordsMap) | |
for _, z := range zones { | |
///Returns a single active zone and its basic configuration details. | |
//For convenience, a list of records in the zone, and some basic details of each record, is also included. | |
k, _ , _ := client.Zones.Get(z.Zone) | |
for _, p := range k.Records { | |
if len(p.ShortAns) > 0 { | |
record := DNSRecord{ | |
FQDN: p.ShortAns[0], | |
Record: ExtractAddressFromReverse(p.Domain), | |
} | |
fmt.Println(record) | |
dnsRecordMap.Add(record) | |
} | |
} | |
} | |
} | |
// ExtractAddressFromReverse turns a standard PTR reverse record name | |
// into an IP address. This works for ipv4 or ipv6. | |
// | |
// 54.119.58.176.in-addr.arpa. becomes 176.58.119.54. If the conversion | |
// fails the empty string is returned. | |
func ExtractAddressFromReverse(reverseName string) string { | |
search := "" | |
f := reverse | |
switch { | |
case strings.HasSuffix(reverseName, IP4arpa): | |
search = strings.TrimSuffix(reverseName, IP4arpa) | |
case strings.HasSuffix(reverseName, IP6arpa): | |
search = strings.TrimSuffix(reverseName, IP6arpa) | |
f = reverse6 | |
default: | |
return "" | |
} | |
// Reverse the segments and then combine them. | |
return f(strings.Split(search, ".")) | |
} | |
// IsReverse returns 0 is name is not in a reverse zone. Anything > 0 indicates | |
// name is in a reverse zone. The returned integer will be 1 for in-addr.arpa. (IPv4) | |
// and 2 for ip6.arpa. (IPv6). | |
func IsReverse(name string) int { | |
if strings.HasSuffix(name, IP4arpa) { | |
return 1 | |
} | |
if strings.HasSuffix(name, IP6arpa) { | |
return 2 | |
} | |
return 0 | |
} | |
func reverse(slice []string) string { | |
for i := 0; i < len(slice)/2; i++ { | |
j := len(slice) - i - 1 | |
slice[i], slice[j] = slice[j], slice[i] | |
} | |
ip := net.ParseIP(strings.Join(slice, ".")).To4() | |
if ip == nil { | |
return "" | |
} | |
return ip.String() | |
} | |
// reverse6 reverse the segments and combine them according to RFC3596: | |
// b.a.9.8.7.6.5.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.8.b.d.0.1.0.0.2 | |
// is reversed to 2001:db8::567:89ab | |
func reverse6(slice []string) string { | |
for i := 0; i < len(slice)/2; i++ { | |
j := len(slice) - i - 1 | |
slice[i], slice[j] = slice[j], slice[i] | |
} | |
slice6 := []string{} | |
for i := 0; i < len(slice)/4; i++ { | |
slice6 = append(slice6, strings.Join(slice[i*4:i*4+4], "")) | |
} | |
ip := net.ParseIP(strings.Join(slice6, ":")).To16() | |
if ip == nil { | |
return "" | |
} | |
return ip.String() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment