mirror of
https://github.com/SamTherapy/dnscrypt.git
synced 2024-11-24 14:23:47 +00:00
113 lines
3.6 KiB
Go
113 lines
3.6 KiB
Go
package main
|
|
|
|
import (
|
|
"encoding/json"
|
|
"os"
|
|
"strings"
|
|
"time"
|
|
|
|
"dns.froth.zone/dnscrypt"
|
|
"github.com/AdguardTeam/golibs/log"
|
|
"github.com/ameshkov/dnsstamps"
|
|
"github.com/miekg/dns"
|
|
)
|
|
|
|
// LookupStampArgs is the "lookup-stamp" command arguments structure
|
|
type LookupStampArgs struct {
|
|
Network string `short:"n" long:"network" description:"network type (tcp/udp)" default:"udp"`
|
|
Stamp string `short:"s" long:"stamp" description:"DNSCrypt resolver stamp. Param is required." required:"true"`
|
|
Domain string `short:"d" long:"domain" description:"Domain to resolve. Param is required." required:"true"`
|
|
Type string `short:"t" long:"type" description:"DNS query type" default:"A"`
|
|
}
|
|
|
|
// LookupArgs is the "lookup" command arguments structure
|
|
type LookupArgs struct {
|
|
Network string `short:"n" long:"network" description:"network type (tcp/udp)" default:"udp"`
|
|
ProviderName string `short:"p" long:"provider-name" description:"DNSCrypt resolver provider name. Param is required." required:"true"`
|
|
PublicKey string `short:"k" long:"public-key" description:"DNSCrypt resolver public key. Param is required." required:"true"`
|
|
ServerAddr string `short:"a" long:"addr" description:"Resolver address (IP[:port]). By default, the port is 443. Param is required." required:"true"`
|
|
Domain string `short:"d" long:"domain" description:"Domain to resolve. Param is required." required:"true"`
|
|
Type string `short:"t" long:"type" description:"DNS query type" default:"A"`
|
|
}
|
|
|
|
// LookupResult is the lookup result that contains the cert info and the query response
|
|
type LookupResult struct {
|
|
Certificate struct {
|
|
Serial uint32 `json:"serial"`
|
|
EsVersion string `json:"encryption"`
|
|
NotAfter time.Time `json:"not_after"`
|
|
NotBefore time.Time `json:"not_before"`
|
|
} `json:"certificate"`
|
|
|
|
Reply *dns.Msg `json:"reply"`
|
|
}
|
|
|
|
// lookup performs a DNS lookup, prints DNSCrypt info and lookup results
|
|
func lookup(args LookupArgs) {
|
|
serverPk, err := dnscrypt.HexDecodeKey(args.PublicKey)
|
|
if err != nil {
|
|
log.Fatalf("invalid resolver public key: %v", err)
|
|
}
|
|
|
|
stamp := dnsstamps.ServerStamp{
|
|
ProviderName: args.ProviderName,
|
|
ServerPk: serverPk,
|
|
ServerAddrStr: args.ServerAddr,
|
|
Proto: dnsstamps.StampProtoTypeDNSCrypt,
|
|
}
|
|
|
|
lookupStamp(LookupStampArgs{
|
|
Network: args.Network,
|
|
Stamp: stamp.String(),
|
|
Domain: args.Domain,
|
|
Type: args.Type,
|
|
})
|
|
}
|
|
|
|
// lookupStamp performs a DNS lookup, prints DNSCrypt cert info and lookup results
|
|
func lookupStamp(args LookupStampArgs) {
|
|
c := &dnscrypt.Client{
|
|
Net: args.Network,
|
|
Timeout: 10 * time.Second,
|
|
}
|
|
ri, err := c.Dial(args.Stamp)
|
|
|
|
if err != nil {
|
|
log.Fatalf("failed to establish connection with the server: %v", err)
|
|
}
|
|
|
|
res := LookupResult{}
|
|
res.Certificate.Serial = ri.ResolverCert.Serial
|
|
res.Certificate.NotAfter = time.Unix(int64(ri.ResolverCert.NotAfter), 0)
|
|
res.Certificate.NotBefore = time.Unix(int64(ri.ResolverCert.NotBefore), 0)
|
|
res.Certificate.EsVersion = ri.ResolverCert.EsVersion.String()
|
|
|
|
dnsType, ok := dns.StringToType[strings.ToUpper(args.Type)]
|
|
if !ok {
|
|
log.Fatalf("invalid type %s", args.Type)
|
|
}
|
|
|
|
req := &dns.Msg{}
|
|
req.Id = dns.Id()
|
|
req.RecursionDesired = true
|
|
req.Question = []dns.Question{
|
|
{
|
|
Name: dns.Fqdn(args.Domain),
|
|
Qtype: dnsType,
|
|
Qclass: dns.ClassINET,
|
|
},
|
|
}
|
|
|
|
reply, err := c.Exchange(req, ri)
|
|
if err != nil {
|
|
log.Fatalf("failed to resolve %s %s", args.Type, args.Domain)
|
|
}
|
|
|
|
res.Reply = reply
|
|
b, err := json.MarshalIndent(res, "", " ")
|
|
if err != nil {
|
|
log.Fatalf("failed to marshal result to json: %v", err)
|
|
}
|
|
|
|
_, _ = os.Stdout.WriteString(string(b) + "\n")
|
|
}
|