awl/util/dns.go
grumbulon 9b979667d6 Make everything more readable (#2)
1. I made JSON print indented instead of inline
2. I created a util package and moved `ReverseDNS` and `ResolveHTTPS` there
3. I created a new struct called Answers where all variables for the output live now, and adjusted the response struct to have the Answers struct in it. This lets us reuse the struct more instead of having variables floating around, lets us make the response more custom, offers more understandable code reuse, and makes things (I think) more readable.

Aside: you will notice the struct has little json defs. This is because struct values encode as JSON objects and can preserve the output name this way

Most of this just makes expanding on awl easier in the future.

Co-authored-by: grumbulon <grumbulon@dismail.de>
Reviewed-on: #2
Co-authored-by: grumbulon <grumbulon@grumbulon.xyz>
Co-committed-by: grumbulon <grumbulon@grumbulon.xyz>
2022-06-22 11:55:38 +00:00

90 lines
2 KiB
Go

package util
import (
"encoding/base64"
"errors"
"fmt"
"io"
"net"
"net/http"
"strings"
"time"
"github.com/c-robinson/iplib"
"github.com/miekg/dns"
)
type Response struct {
Answers Answers `json:"Response"` //
}
// The Answers struct is the basic structure of a DNS request
// to be returned to the user upon making a request
type Answers struct {
Server string `json:"Server"` // The server to make the DNS request from
Request uint16 `json:"Request"` // The type of request
Name string `json:"Name"` // The domain name to make a DNS request for
RTT time.Duration `json:"RTT"` // When AWL was ran
}
func ReverseDNS(dom string, q string) (string, error) {
if q == "PTR" {
if strings.Contains(dom, ".") {
// It's an IPv4 address
ip := net.ParseIP(dom)
if ip != nil {
return iplib.IP4ToARPA(ip), nil
} else {
return "", errors.New("error: Could not parse IPv4 address")
}
} else if strings.Contains(dom, ":") {
// It's an IPv6 address
ip := net.ParseIP(dom)
if ip != nil {
return iplib.IP6ToARPA(ip), nil
} else {
return "", errors.New("error: Could not parse IPv6 address")
}
}
}
return "", errors.New("error: -x flag given but no IP found")
}
func ResolveHTTPS(msg *dns.Msg, server string) (*dns.Msg, error) {
httpR := &http.Client{}
buf, err := msg.Pack()
if err != nil {
return nil, err
}
query := server + "?dns=" + base64.RawURLEncoding.EncodeToString(buf)
req, err := http.NewRequest("GET", query, nil)
if err != nil {
return nil, err
}
req.Header.Set("Accept", "application/dns-message")
res, err := httpR.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
if res.StatusCode != http.StatusOK {
return nil, fmt.Errorf("bad HTTP Request: %d", res.StatusCode)
}
fullRes, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
response := dns.Msg{}
err = response.Unpack(fullRes)
if err != nil {
return nil, err
}
return &response, nil
}