Please purchase the course to watch this video.

Full Course
The net package in Go equips developers with powerful tools for networking, including features for DNS address lookup and reverse DNS resolution. By utilizing functions such as lookup IP
, lookup addr
, and lookup cname
, programmers can create versatile applications for querying DNS records, making it easy to retrieve IP addresses or canonical names associated with various domains. An example project demonstrates how to build a simple command-line DNS lookup tool that allows users to input a domain name and retrieve its corresponding IP addresses efficiently. This functionality not only enhances networking capabilities but also supports the creation of advanced tools for managing and resolving network queries in Go.
No links available for this lesson.
Beyond TCP and UDP client-server functionality, Go's net
package also provides powerful DNS (Domain Name System) capabilities. These functions allow us to resolve domain names to IP addresses, perform reverse DNS lookups, and retrieve various DNS records.
DNS Functions in the Net Package
The net
package includes several DNS-related functions:
net.LookupIP
: Look up IP addresses for a host namenet.LookupAddr
: Perform a reverse DNS lookup to find hostnames for an IP addressnet.LookupCNAME
: Look up the canonical name for a given hostnet.LookupMX
: Look up MX (mail exchange) records for a domainnet.LookupTXT
: Look up TXT records for a domainnet.LookupNS
: Look up NS (name server) records for a domainnet.LookupSRV
: Look up SRV records for a service
These functions provide a simple interface to access DNS information without needing to understand the underlying DNS protocol details.
Building a Simple DNS Lookup Tool
Let's create a command-line tool to demonstrate these DNS capabilities:
package main
import (
"fmt"
"log"
"net"
"os"
)
func main() {
// Check if a domain name was provided
if len(os.Args) < 2 {
log.Fatal("Please provide a domain name")
}
// Get the domain name from command line arguments
domain := os.Args[1]
// Look up IP addresses for the domain
ips, err := net.LookupIP(domain)
if err != nil {
log.Fatalf("Failed to lookup %s: %v", domain, err)
}
// Print each IP address
fmt.Printf("IP addresses for %s:\n", domain)
for _, ip := range ips {
fmt.Println(ip)
}
}
This program:
- Takes a domain name as a command-line argument
- Uses
net.LookupIP
to resolve the domain name to IP addresses - Prints each IP address
When you run this program with a domain name, it will display all IP addresses associated with that domain:
$ go run main.go google.com
IP addresses for google.com:
142.250.190.78
2607:f8b0:4005:80e::200e
Implementing Reverse DNS Lookup
Let's enhance our tool to also perform reverse DNS lookups:
package main
import (
"fmt"
"log"
"net"
"os"
"strings"
)
func main() {
if len(os.Args) < 2 {
log.Fatal("Please provide a domain name or IP address")
}
query := os.Args[1]
// Check if the input looks like an IP address
if strings.Contains(query, ".") && !strings.Contains(query, ":") &&
net.ParseIP(query) != nil {
// Reverse DNS lookup
names, err := net.LookupAddr(query)
if err != nil {
log.Fatalf("Failed to reverse lookup %s: %v", query, err)
}
fmt.Printf("Domain names for %s:\n", query)
for _, name := range names {
fmt.Println(name)
}
} else {
// Forward DNS lookup
ips, err := net.LookupIP(query)
if err != nil {
log.Fatalf("Failed to lookup %s: %v", query, err)
}
fmt.Printf("IP addresses for %s:\n", query)
for _, ip := range ips {
fmt.Println(ip)
}
}
}
This version:
- Checks if the input looks like an IP address
- If it is an IP address, performs a reverse lookup using
net.LookupAddr
- Otherwise, performs a forward lookup using
net.LookupIP
Example usage:
$ go run main.go 8.8.8.8
Domain names for 8.8.8.8:
dns.google.
$ go run main.go google.com
IP addresses for google.com:
142.250.190.78
2607:f8b0:4005:80e::200e
Looking Up CNAME Records
Let's add the ability to look up CNAME (Canonical Name) records:
package main
import (
"fmt"
"log"
"net"
"os"
"strings"
)
func main() {
if len(os.Args) < 2 {
log.Fatal("Please provide a domain name or IP address")
}
query := os.Args[1]
// Check if the input looks like an IP address
if strings.Contains(query, ".") && !strings.Contains(query, ":") &&
net.ParseIP(query) != nil {
// Reverse DNS lookup
names, err := net.LookupAddr(query)
if err != nil {
log.Fatalf("Failed to reverse lookup %s: %v", query, err)
}
fmt.Printf("Domain names for %s:\n", query)
for _, name := range names {
fmt.Println(name)
}
} else {
// Forward DNS lookup
ips, err := net.LookupIP(query)
if err != nil {
log.Fatalf("Failed to lookup %s: %v", query, err)
}
fmt.Printf("IP addresses for %s:\n", query)
for _, ip := range ips {
fmt.Println(ip)
}
// Look up CNAME
cname, err := net.LookupCNAME(query)
if err != nil {
fmt.Printf("No CNAME record for %s\n", query)
} else {
fmt.Printf("CNAME for %s: %s\n", query, cname)
}
}
}
Example usage:
$ go run main.go store.example.com
IP addresses for store.example.com:
104.16.0.35
104.16.1.35
CNAME for store.example.com: shops.myshopify.com.
Complete DNS Lookup Tool
We can expand our tool to include more DNS record types:
package main
import (
"flag"
"fmt"
"log"
"net"
"os"
"strings"
)
func main() {
// Define flags for specific lookups
ipLookup := flag.Bool("ip", false, "Lookup IP addresses")
cnLookup := flag.Bool("cname", false, "Lookup CNAME records")
mxLookup := flag.Bool("mx", false, "Lookup MX records")
txtLookup := flag.Bool("txt", false, "Lookup TXT records")
nsLookup := flag.Bool("ns", false, "Lookup NS records")
revLookup := flag.Bool("rev", false, "Reverse lookup (IP to hostname)")
allLookup := flag.Bool("all", false, "Perform all lookups")
flag.Parse()
if flag.NArg() < 1 {
log.Fatal("Please provide a domain name or IP address")
}
query := flag.Arg(0)
// If no specific lookup is requested, default to IP lookup
if !(*ipLookup || *cnLookup || *mxLookup || *txtLookup || *nsLookup || *revLookup || *allLookup) {
*ipLookup = true
}
// Check if the input looks like an IP address
isIP := strings.Contains(query, ".") && !strings.Contains(query, ":") &&
net.ParseIP(query) != nil
// If it's an IP or reverse lookup is requested
if isIP || *revLookup || *allLookup {
performReverseLookup(query)
}
// If it's not an IP or forward lookups are requested
if !isIP || *allLookup {
if *ipLookup || *allLookup {
performIPLookup(query)
}
if *cnLookup || *allLookup {
performCNAMELookup(query)
}
if *mxLookup || *allLookup {
performMXLookup(query)
}
if *txtLookup || *allLookup {
performTXTLookup(query)
}
if *nsLookup || *allLookup {
performNSLookup(query)
}
}
}
func performIPLookup(domain string) {
ips, err := net.LookupIP(domain)
if err != nil {
fmt.Printf("IP lookup failed for %s: %v\n", domain, err)
return
}
fmt.Printf("IP addresses for %s:\n", domain)
for _, ip := range ips {
fmt.Println(" " + ip.String())
}
fmt.Println()
}
func performReverseLookup(ip string) {
names, err := net.LookupAddr(ip)
if err != nil {
fmt.Printf("Reverse lookup failed for %s: %v\n", ip, err)
return
}
fmt.Printf("Domain names for %s:\n", ip)
for _, name := range names {
fmt.Println(" " + name)
}
fmt.Println()
}
func performCNAMELookup(domain string) {
cname, err := net.LookupCNAME(domain)
if err != nil {
fmt.Printf("CNAME lookup failed for %s: %v\n", domain, err)
return
}
fmt.Printf("CNAME for %s: %s\n\n", domain, cname)
}
func performMXLookup(domain string) {
mxRecords, err := net.LookupMX(domain)
if err != nil {
fmt.Printf("MX lookup failed for %s: %v\n", domain, err)
return
}
fmt.Printf("MX records for %s:\n", domain)
for _, mx := range mxRecords {
fmt.Printf(" %s (preference: %d)\n", mx.Host, mx.Pref)
}
fmt.Println()
}
func performTXTLookup(domain string) {
txtRecords, err := net.LookupTXT(domain)
if err != nil {
fmt.Printf("TXT lookup failed for %s: %v\n", domain, err)
return
}
fmt.Printf("TXT records for %s:\n", domain)
for _, txt := range txtRecords {
fmt.Printf(" %s\n", txt)
}
fmt.Println()
}
func performNSLookup(domain string) {
nsRecords, err := net.LookupNS(domain)
if err != nil {
fmt.Printf("NS lookup failed for %s: %v\n", domain, err)
return
}
fmt.Printf("NS records for %s:\n", domain)
for _, ns := range nsRecords {
fmt.Printf(" %s\n", ns.Host)
}
fmt.Println()
}
This complete DNS lookup tool provides:
- IP address lookup
- Reverse DNS lookup
- CNAME record lookup
- MX record lookup
- TXT record lookup
- NS record lookup
- Option to perform all lookups at once
Summary
In this lesson, we've explored:
- The DNS lookup capabilities of Go's
net
package - How to resolve domain names to IP addresses with
net.LookupIP
- How to perform reverse DNS lookups with
net.LookupAddr
- How to retrieve CNAME records with
net.LookupCNAME
- How to build a comprehensive DNS lookup tool
These DNS functions are valuable for many networking applications, such as:
- Network diagnostics tools
- Web crawlers and scrapers
- Email validation systems
- Security scanning tools
- Network monitoring applications
By leveraging Go's built-in DNS capabilities, you can create powerful networking tools without having to implement the complex DNS protocol yourself.