129 lines
3.5 KiB
Go
129 lines
3.5 KiB
Go
package main
|
|
|
|
import (
|
|
"fmt"
|
|
"math/rand"
|
|
"net"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/miekg/dns"
|
|
"github.com/rs/zerolog"
|
|
"github.com/rs/zerolog/log"
|
|
)
|
|
|
|
func strategyMaker(name string, qtype uint16) uint16 {
|
|
subdomain := strings.ToLower(strings.Split(name, ".")[0])
|
|
if qtype == dns.TypeA {
|
|
if strings.Contains(subdomain, "fwd") {
|
|
return 1 // return rdns ip in cname
|
|
} else if strings.Contains(subdomain, "rdns") {
|
|
return 2 // return honey cname record
|
|
} else if strings.Contains(subdomain, "honey") {
|
|
return 3 // return timestamp in a record
|
|
} else if strings.Contains(subdomain, "echo") {
|
|
return 4 // basic echodns
|
|
} else if strings.Contains(subdomain, "ttl") {
|
|
return 5 // ttl test
|
|
}
|
|
}
|
|
return 0
|
|
}
|
|
|
|
func InttoIPv4(n uint32) net.IP {
|
|
b0 := (n >> 24) & 0xff
|
|
b1 := (n >> 16) & 0xff
|
|
b2 := (n >> 8) & 0xff
|
|
b3 := n & 0xff
|
|
return net.IPv4(byte(b0), byte(b1), byte(b2), byte(b3))
|
|
}
|
|
|
|
func TtlParser(domain string) uint32 {
|
|
subdomain := strings.ToLower(strings.Split(domain, ".")[0])
|
|
ttl, _ := strconv.Atoi(strings.Split(subdomain, "-")[0])
|
|
return uint32(ttl)
|
|
}
|
|
|
|
func handleReflect(w dns.ResponseWriter, r *dns.Msg) {
|
|
var (
|
|
ip net.IP
|
|
port int
|
|
id uint16
|
|
name string
|
|
qtype uint16
|
|
)
|
|
m := new(dns.Msg)
|
|
m.SetReply(r)
|
|
m.Compress = true
|
|
m.Authoritative = true
|
|
if addr, ok := w.RemoteAddr().(*net.UDPAddr); ok {
|
|
ip = addr.IP
|
|
port = addr.Port
|
|
}
|
|
id = m.MsgHdr.Id
|
|
name = m.Question[0].Name
|
|
qtype = m.Question[0].Qtype
|
|
log.Log().Str("sip", ip.String()).Int64("port", int64(port)).Int64("id", int64(id)).Str("name", name).Int64("qtype", int64(qtype)).Msg("")
|
|
//log.Printf("%v|%v|%v|%v|%v", ip, port, id, name, qtype)
|
|
//fmt.Println(ip)
|
|
//fmt.Println(name)
|
|
//fmt.Println(qtype)
|
|
switch strategyMaker(name, qtype) {
|
|
case 1:
|
|
cname_subdomain := "rdns-" + strings.Replace(ip.String(), ".", "-", -1)
|
|
cname_fqdn := cname_subdomain + ".echodns.xyz."
|
|
cname := &dns.CNAME{
|
|
Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeCNAME, Class: dns.ClassINET, Ttl: 14400},
|
|
Target: cname_fqdn,
|
|
}
|
|
//fmt.Println(name+" "+cname_fqdn)
|
|
m.Answer = append(m.Answer, cname)
|
|
case 2:
|
|
cname_fqdn := "honey.echodns.xyz."
|
|
cname := &dns.CNAME{
|
|
Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeCNAME, Class: dns.ClassINET, Ttl: 14400},
|
|
Target: cname_fqdn,
|
|
}
|
|
//fmt.Println(cname_fqdn)
|
|
m.Answer = append(m.Answer, cname)
|
|
case 3:
|
|
time_str := strconv.FormatInt(time.Now().UnixMicro(), 10)
|
|
time_int, _ := strconv.Atoi(time_str[5 : len(time_str)-2])
|
|
time_int += rand.Intn(10000)
|
|
timestamp := InttoIPv4(uint32(time_int))
|
|
a := &dns.A{
|
|
Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 14400},
|
|
A: timestamp,
|
|
}
|
|
m.Answer = append(m.Answer, a)
|
|
case 4:
|
|
a := &dns.A{
|
|
Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 60},
|
|
A: ip,
|
|
}
|
|
m.Answer = append(m.Answer, a)
|
|
case 5:
|
|
query_ttl := TtlParser(name)
|
|
//fmt.Println(query_ttl)
|
|
a := &dns.A{
|
|
Hdr: dns.RR_Header{Name: name, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: query_ttl},
|
|
A: ip,
|
|
}
|
|
m.Answer = append(m.Answer, a)
|
|
case 0:
|
|
return
|
|
}
|
|
w.WriteMsg(m)
|
|
}
|
|
|
|
func main() {
|
|
zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
|
|
dns.HandleFunc("echodns.xyz.", handleReflect)
|
|
server := &dns.Server{Addr: ":53", Net: "udp"}
|
|
if err := server.ListenAndServe(); err != nil {
|
|
fmt.Println("Failed to set up dns server!")
|
|
panic(err)
|
|
}
|
|
}
|