-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
110 lines (92 loc) · 2.28 KB
/
main.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
package main
import (
"flag"
"fmt"
"io"
"os"
"os/signal"
"github.com/miekg/dns"
)
type config struct {
port int
host string
}
func main() {
c, err := parseArgs(os.Stderr, os.Args[1:])
if err != nil {
os.Exit(1)
}
err = runCmd(os.Stdout, c)
if err != nil {
fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}
func parseArgs(w io.Writer, args []string) (*config, error) {
c := config{}
fs := flag.NewFlagSet("ccdns", flag.ContinueOnError)
fs.SetOutput(w)
fs.IntVar(&c.port, "p", 53, "Port where the server will listen for incoming requests")
fs.StringVar(&c.host, "h", "", "Host where the server will listen for incoming requests")
fs.Usage = func() {
var usageString = `ccdns is a DNS Forwarder used to resolve DNS queries instead of directly using the authoritative nameserver chain.
Usage of %s: <options> [value]`
fmt.Fprintf(w, usageString, fs.Name())
fmt.Fprintln(w)
fmt.Fprintln(w, "Options: ")
fs.PrintDefaults()
}
if err := fs.Parse(args); err != nil {
return &c, err
}
return &c, nil
}
func runCmd(w io.Writer, c *config) error {
// Setup signal handling for graceful shutdown
signalCh := make(chan os.Signal, 1)
signal.Notify(signalCh, os.Interrupt)
go func() {
<-signalCh
// Initiate graceful shutdown
fmt.Println("Bye bye ;-)")
os.Exit(0)
}()
handler := new(dnsHandler)
server := &dns.Server{
Addr: fmt.Sprintf("%s:%d", c.host, c.port),
Net: "udp",
Handler: handler,
UDPSize: 65535,
ReusePort: true,
}
fmt.Printf("Starting DNS server on %v\n", server.Addr)
err := server.ListenAndServe()
if err != nil {
fmt.Printf("Failed to start server: %s\n", err.Error())
}
return nil
}
type dnsHandler struct{}
func (h *dnsHandler) ServeDNS(w dns.ResponseWriter, r *dns.Msg) {
msg := new(dns.Msg)
msg.SetReply(r)
msg.Authoritative = true
for _, question := range r.Question {
//fmt.Printf("Received query: %s\n", question.Name)
answers := resolve(question.Name, question.Qtype)
msg.Answer = append(msg.Answer, answers...)
}
w.WriteMsg(msg)
}
func resolve(domain string, qtype uint16) []dns.RR {
m := new(dns.Msg)
m.SetQuestion(dns.Fqdn(domain), qtype)
m.RecursionDesired = true
c := new(dns.Client)
in, _, err := c.Exchange(m, "8.8.8.8:53")
if err != nil {
fmt.Println(err)
return nil
}
return in.Answer
}