-
Notifications
You must be signed in to change notification settings - Fork 0
/
intercept-dns.go
98 lines (85 loc) · 2.41 KB
/
intercept-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
package main
import (
"flag"
"fmt"
"github.com/miekg/dns"
"log"
"regexp"
"strconv"
)
var interceptDomain = "ip.net."
var ip, _ = regexp.Compile("(.*\\.)?([0-2]?\\d?\\d\\.[0-2]?\\d?\\d\\.[0-2]?\\d?\\d\\.[0-2]?\\d?\\d)\\.ip\\.net")
var ttl = "3600"
var remoteDns string
func interceptDnsRequest(w dns.ResponseWriter, m *dns.Msg) {
r := new(dns.Msg)
r.SetReply(m)
r.Compress = false
switch m.Opcode {
case dns.OpcodeQuery:
for _, q := range m.Question {
switch q.Qtype {
case dns.TypeA:
log.Printf("Intercept A %s\n", q.Name)
ip := ip.FindStringSubmatch(q.Name)[2]
a, e := dns.NewRR(fmt.Sprintf("%s %s A %s", q.Name, ttl, ip))
if e != nil {
log.Fatalf("Failed to handle request: %s\n ", e.Error())
}
log.Printf("Answer %s\n", a)
r.Answer = append(r.Answer, a)
break
case dns.TypeAAAA:
log.Printf("Intercept AAAA %s. This is currently not supported.\n", q.Name)
r.Rcode = dns.RcodeNameError
break
default:
log.Printf("Qtype %d net set up.", q.Qtype)
r.Rcode = dns.RcodeServerFailure
}
}
break
default:
log.Printf("Opcode %d not set up.", m.Opcode)
}
err := w.WriteMsg(r)
if err != nil {
log.Fatalf("Failed to handle request: %s\n ", err.Error())
}
}
func handleDnsRequest(w dns.ResponseWriter, m *dns.Msg) {
r := new(dns.Msg)
r.SetReply(m)
r.Compress = false
n := new(dns.Msg)
n.Id = dns.Id()
n.RecursionDesired = true
n.Question = r.Question
c := new(dns.Client)
a, t, e := c.Exchange(n, remoteDns)
if e != nil {
log.Fatalf("Failed to forward request: %s\n", e.Error())
}
log.Printf("Forward response: %s (%d)\n", a.Answer, t)
r.Answer = a.Answer
err := w.WriteMsg(r)
if err != nil {
log.Fatalf("Failed to handle request: %s\n ", err.Error())
}
}
func main() {
var remotePort int
remoteIp := flag.String("remote-dns-ip", "1.1.1.1", "ip address of the next dns resolver")
flag.IntVar(&remotePort, "remote-dns-port", 53, "port of the next dns resolver")
flag.Parse()
remoteDns = *remoteIp + ":" + strconv.Itoa(remotePort)
log.Printf("Forwarding non intercepted requests to %s\n", remoteDns)
dns.HandleFunc(interceptDomain, interceptDnsRequest)
dns.HandleFunc(".", handleDnsRequest)
server := dns.Server{Addr: "0.0.0.0:53", Net: "udp"}
err := server.ListenAndServe()
defer server.Shutdown()
if err != nil {
log.Fatalf("Failed to start server (check if you have permission to listen on specific port): %s\n ", err.Error())
}
}