forked from StalkR/dns-reverse-proxy
-
Notifications
You must be signed in to change notification settings - Fork 0
/
dns_reverse_proxy.go
124 lines (104 loc) · 2.51 KB
/
dns_reverse_proxy.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
122
123
124
package main
import (
"flag"
"fmt"
"log"
"net"
"os"
"os/signal"
"strings"
"syscall"
"github.com/miekg/dns"
)
var (
address = flag.String("address", ":53", "Address to listen to (TCP and UDP)")
defaultServer = flag.String("default", "",
"Default DNS server where to send queries if no route matched (host:port)")
routes map[string]string
)
func main() {
flag.Parse()
routes = make(map[string]string)
for i := 0; i <= 255; i++ {
backend := fmt.Sprintf("10.30.%d.255:53", i)
name := fmt.Sprintf("%d.orionet.re.", i)
reverse := fmt.Sprintf("%d.30.10.in-addr.arpa.", i)
routes[name] = backend
routes[reverse] = backend
log.Printf("Adding %s for %s and %s", backend, name, reverse)
}
udpServer := &dns.Server{Addr: *address, Net: "udp"}
tcpServer := &dns.Server{Addr: *address, Net: "tcp"}
dns.HandleFunc(".", route)
go func() {
if err := udpServer.ListenAndServe(); err != nil {
log.Fatal(err)
}
}()
go func() {
if err := tcpServer.ListenAndServe(); err != nil {
log.Fatal(err)
}
}()
log.Println("Server is loaded.")
// Wait for SIGINT or SIGTERM
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM)
<-sigs
udpServer.Shutdown()
tcpServer.Shutdown()
}
func route(w dns.ResponseWriter, req *dns.Msg) {
if len(req.Question) == 0 || !allowed(req) {
dns.HandleFailed(w, req)
return
}
lcName := strings.ToLower(req.Question[0].Name)
for name, addrs := range routes {
// All DS records should be forwarded to the default server (which is the autoritative DNS server)
for _, q := range req.Question {
switch q.Qtype {
case dns.TypeIXFR, dns.TypeDS:
proxy(*defaultServer, w, req)
return
}
}
// Check if the dns name in under
if strings.HasSuffix(lcName, fmt.Sprintf(".%s", name)) || lcName == name {
addr := addrs
proxy(addr, w, req)
return
}
}
if *defaultServer == "" {
dns.HandleFailed(w, req)
return
}
proxy(*defaultServer, w, req)
}
func isTransfer(req *dns.Msg) bool {
for _, q := range req.Question {
switch q.Qtype {
case dns.TypeIXFR, dns.TypeAXFR:
return true
}
}
return false
}
func allowed(req *dns.Msg) bool {
return !isTransfer(req)
}
func proxy(addr string, w dns.ResponseWriter, req *dns.Msg) {
transport := "udp"
if _, ok := w.RemoteAddr().(*net.TCPAddr); ok {
transport = "tcp"
}
c := &dns.Client{Net: transport}
resp, _, err := c.Exchange(req, addr)
if err != nil {
dns.HandleFailed(w, req)
fmt.Printf("Error while proxying %s", err.Error())
return
}
w.WriteMsg(resp)
}