Skip to content

Commit

Permalink
Adding support for v6 and dynamic zone via SOA
Browse files Browse the repository at this point in the history
  • Loading branch information
AndrewAubury committed Aug 6, 2024
1 parent 69a04a0 commit 20229d3
Show file tree
Hide file tree
Showing 3 changed files with 145 additions and 15 deletions.
9 changes: 7 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,13 @@ require (
github.com/google/go-querystring v1.1.0 // indirect
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
github.com/hashicorp/go-retryablehttp v0.7.5 // indirect
golang.org/x/net v0.24.0 // indirect
golang.org/x/text v0.14.0 // indirect
github.com/miekg/dns v1.1.61 // indirect
golang.org/x/mod v0.18.0 // indirect
golang.org/x/net v0.27.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.22.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/time v0.5.0 // indirect
golang.org/x/tools v0.22.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
)
18 changes: 18 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,32 @@ github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/S
github.com/hashicorp/go-hclog v0.9.2/go.mod h1:5CU+agLiy3J7N7QjHK5d05KxGsuXiQLrjA0H7acj2lQ=
github.com/hashicorp/go-retryablehttp v0.7.5 h1:bJj+Pj19UZMIweq/iie+1u5YCdGrnxCT9yvm0e+Nd5M=
github.com/hashicorp/go-retryablehttp v0.7.5/go.mod h1:Jy/gPYAdjqffZ/yFGCFV2doI5wjtH1ewM9u8iYVjtX8=
github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs=
github.com/miekg/dns v1.1.61/go.mod h1:mnAarhS3nWaW+NVP2wTkYVIZyHNJ098SJZUki3eykwQ=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
golang.org/x/mod v0.18.0 h1:5+9lSbEzPSdWkH32vYPBwEpX8KwDbM52Ud9xBUvNlb0=
golang.org/x/mod v0.18.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w=
golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8=
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.22.0 h1:gqSGLZqv+AI9lIQzniJ0nZDRG5GBPsSi+DRNHWNz6yA=
golang.org/x/tools v0.22.0/go.mod h1:aCwcsjqvq7Yqt6TNyX7QMU2enbQ/Gt0bo6krSeEri+c=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
Expand Down
133 changes: 120 additions & 13 deletions main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@ import (
"net"
"os"
"strings"
"time"

"github.com/cloudflare/cloudflare-go"
"golang.org/x/net/dns/dnsmessage"
"gopkg.in/yaml.v2"
)

Expand Down Expand Up @@ -104,25 +106,123 @@ func getArpaZone(ip string) (string, error) {
// Parse the IP address to ensure it is valid
parsedIP := net.ParseIP(ip)
if parsedIP == nil {
sendOutput(false, "Error to get rDNS Zone", "Invalid IP address")
sendOutput(false, "Error to get rDNS Zone", "Invalid IP address INT")
return "", nil
}

// Extract the first three octets for a /24 network
octets := strings.Split(ip, ".")
if len(octets) != 4 {
ipAddr := net.ParseIP(ip)
if ipAddr == nil {
sendOutput(false, "Error to get rDNS Zone", "Invalid IP address")
return "", fmt.Errorf("invalid IP address format")
}

var arpa string
if strings.Contains(ip, ":") {
// IPv6 address
if strings.Count(ip, ":") < 2 || strings.Count(ip, ":") > 7 {
sendOutput(false, "Error to get rDNS Zone", "Invalid IPv6 address format")
return "", fmt.Errorf("invalid IPv6 address format")
}
arpa = getIPv6Arpa(ipAddr)
} else {
// IPv4 address
octets := strings.Split(ip, ".")
if len(octets) != 4 {
sendOutput(false, "Error to get rDNS Zone", "Invalid IP address OCT")
return "", fmt.Errorf("invalid IPv4 address format")
}
arpa = fmt.Sprintf("%s.%s.%s.%s.in-addr.arpa", octets[3], octets[2], octets[1], octets[0])

}

// Reverse the order of the first three octets
reversedOctets := fmt.Sprintf("%s.%s.%s.in-addr.arpa", octets[2], octets[1], octets[0])
return reversedOctets, nil
return arpa, nil
}

func SOAArpaLookup(domain string) (string, error) {
// Create a DNS message
var msg dnsmessage.Message
msg.Header.RecursionDesired = true
msg.Questions = []dnsmessage.Question{
{
Name: dnsmessage.MustNewName(domain + "."),
Type: dnsmessage.TypeSOA,
Class: dnsmessage.ClassINET,
},
}

// Pack the DNS message
packedMsg, err := msg.Pack()
if err != nil {
return "", fmt.Errorf("failed to pack DNS message: %v", err)
}

// Set up a connection to the DNS server
conn, err := net.Dial("udp", "1.1.1.1:53")
if err != nil {
return "", fmt.Errorf("failed to connect to DNS server: %v", err)
}
defer conn.Close()

// Set a timeout for the connection
conn.SetDeadline(time.Now().Add(5 * time.Second))

Check failure on line 168 in main.go

View workflow job for this annotation

GitHub Actions / Lint files

Error return value of `conn.SetDeadline` is not checked (errcheck)

// Send the DNS query
_, err = conn.Write(packedMsg)
if err != nil {
return "", fmt.Errorf("failed to send DNS query: %v", err)
}

// Receive the DNS response
buf := make([]byte, 512)
n, err := conn.Read(buf)
if err != nil {
return "", fmt.Errorf("failed to read DNS response: %v", err)
}

// Unpack the DNS response
var response dnsmessage.Message
err = response.Unpack(buf[:n])
if err != nil {
return "", fmt.Errorf("failed to unpack DNS response: %v", err)
}

// Extract the SOA record from the Answers or Authority section
for _, rr := range append(response.Answers, response.Authorities...) {
return strings.TrimRight(rr.Header.Name.String(), "."), nil
}

return "", fmt.Errorf("no SOA record found")
}

func getIPv6Arpa(ipAddr net.IP) string {
// Convert IP to 16-byte representation
ipv6 := ipAddr.To16()
hexDigits := "0123456789abcdef"
var arpaBuilder strings.Builder

for i := len(ipv6) - 1; i >= 0; i-- {
b := ipv6[i]
// Append each half-byte (nibble) in reverse order
arpaBuilder.WriteByte(hexDigits[b&0xF])
arpaBuilder.WriteByte('.')
arpaBuilder.WriteByte(hexDigits[b>>4])
arpaBuilder.WriteByte('.')
}

arpaBuilder.WriteString("ip6.arpa")
return arpaBuilder.String()
}

func getCloudflareZone(api *cloudflare.API, ip string) string {
arpa, _ := getArpaZone(ip)
zoneID, err := api.ZoneIDByName(arpa)
// arpa = arpa
// Define the domain for which you want to perform the SOA DNS lookup
// Create a DNS message
zonedArpa, _ := SOAArpaLookup(arpa)
//fmt.Printf("We got zone %s from authoritive server via 1.1.1.1", zonedArpa)
zoneID, err := api.ZoneIDByName(zonedArpa)

if err != nil {
sendOutput(false, "Error to get rDNS Zone", err.Error())
return ""
Expand All @@ -133,9 +233,11 @@ func getCloudflareZone(api *cloudflare.API, ip string) string {
func getRDNS(api *cloudflare.API, ip string) (string, error) {
// Dummy implementation, replace with actual Cloudflare API call
zoneID := getCloudflareZone(api, ip)
octets := strings.Split(ip, ".")
// octets := strings.Split(ip, ".")
arpa, _ := getArpaZone(ip)
records, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.ListDNSRecordsParams{Name: octets[3] + "." + arpa})

records, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.ListDNSRecordsParams{Name: arpa})
//records, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.ListDNSRecordsParams{})
// Fetch DNS records according to the criteria
if err != nil {
fmt.Println("Error fetching DNS records:", err)
Expand All @@ -144,7 +246,7 @@ func getRDNS(api *cloudflare.API, ip string) (string, error) {

// Check if any records are returned and print them
if len(records) == 0 {
sendOutput(true, "", "No PTR record found for IP")
sendOutput(false, "", "No PTR record found for IP")
} else {
for _, record := range records {
sendOutput(true, record.Content, record.Name)
Expand All @@ -158,9 +260,8 @@ func getRDNS(api *cloudflare.API, ip string) (string, error) {
func updateRDNS(api *cloudflare.API, ip, ptr string) error {
// Dummy implementation, replace with actual Cloudflare API call
zoneID := getCloudflareZone(api, ip)
octets := strings.Split(ip, ".")
arpa, _ := getArpaZone(ip)
records, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.ListDNSRecordsParams{Name: octets[3] + "." + arpa})
records, _, err := api.ListDNSRecords(context.Background(), cloudflare.ZoneIdentifier(zoneID), cloudflare.ListDNSRecordsParams{Name: arpa})
// Fetch DNS records according to the criteria
if err != nil {
fmt.Println("Error fetching DNS records:", err)
Expand All @@ -170,7 +271,7 @@ func updateRDNS(api *cloudflare.API, ip, ptr string) error {
// Check if any records are returned and print them
if len(records) == 0 {
rr := cloudflare.CreateDNSRecordParams{
Name: octets[3] + "." + arpa,
Name: arpa,
Type: "ptr",
Content: ptr,
}
Expand Down Expand Up @@ -247,4 +348,10 @@ func sendOutput(success bool, message string, error string) {
return
}
fmt.Println(output)
if success {
os.Exit(0)
} else {
os.Exit(1)
}

}

0 comments on commit 20229d3

Please sign in to comment.