-
-
Notifications
You must be signed in to change notification settings - Fork 2
/
dns.go
121 lines (103 loc) · 2.51 KB
/
dns.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
package main
import (
"encoding/json"
"flag"
"log"
"net/http"
"os"
"os/signal"
"strings"
"syscall"
"time"
"github.com/miekg/dns"
)
type DNSData struct {
IP string
EdnsSubnet string
Expire time.Time
}
var (
dnsListen = flag.String("dns-listen", ":8053", "Port to listen on for DNS server")
dnsIP = flag.String("dns-public-ip", "", "Public IP to return")
)
var dnsMap = map[string]DNSData{}
func dnsHandler(w http.ResponseWriter, req *http.Request) {
host := strings.TrimSuffix(req.Host, ".")
w.Header().Add("Access-Control-Allow-Origin", "*")
w.Header().Add("Access-Control-Allow-Methods", "GET, OPTIONS, HEAD")
if m, ok := dnsMap[host]; ok {
err := json.NewEncoder(w).Encode(m)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
}
} else {
http.Error(w, "not found", http.StatusNotFound)
}
}
// MustNewRR is a shortcut to dns.NewRR that panics on error.
func MustNewRR(s string) dns.RR {
r, err := dns.NewRR(s)
if err != nil {
panic(err)
}
return r
}
func dnsServe() {
SOA := "@ SOA " + *flagHost + ". " + *flagHost + ". 2021010100 1800 900 0604800 60"
myAddrA := ". 0 A " + *dnsIP
z := "dns." + *flagHost
rrx := MustNewRR("$ORIGIN " + z + ".\n" + SOA)
dns.HandleFunc(z, func(w dns.ResponseWriter, r *dns.Msg) {
subnet := ""
for _, ext := range r.Extra {
opt, ok := ext.(*dns.OPT)
if !ok {
continue
}
for _, s := range opt.Option {
switch e := s.(type) {
case *dns.EDNS0_SUBNET:
subnet = e.String()
}
}
}
m := new(dns.Msg)
m.SetReply(r)
m.Authoritative = true
if strings.ToLower(r.Question[0].Name) == z+"." {
m.Answer = []dns.RR{rrx}
} else {
name := strings.TrimSuffix(r.Question[0].Name, ".")
dnsMap[name] = DNSData{
IP: w.RemoteAddr().String(),
EdnsSubnet: subnet,
Expire: time.Now().Add(2 * time.Minute),
}
rr := MustNewRR(name + myAddrA)
m.Answer = []dns.RR{rr}
}
w.WriteMsg(m)
})
if len(*dnsListen) == 0 {
return
}
if len(*dnsIP) == 0 {
return
}
go func() {
srv := &dns.Server{Addr: *dnsListen, Net: "udp"}
if err := srv.ListenAndServe(); err != nil {
log.Fatalf("Failed to set udp listener %s\n", err.Error())
}
}()
go func() {
srv := &dns.Server{Addr: *dnsListen, Net: "tcp"}
if err := srv.ListenAndServe(); err != nil {
log.Fatalf("Failed to set tcp listener %s\n", err.Error())
}
}()
sig := make(chan os.Signal)
signal.Notify(sig, syscall.SIGINT, syscall.SIGTERM)
s := <-sig
log.Fatalf("Signal (%v) received, stopping\n", s)
}