-
Notifications
You must be signed in to change notification settings - Fork 17
/
Copy pathdnss.go
163 lines (136 loc) · 4.54 KB
/
dnss.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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
// dnss is a tool for encapsulating DNS over HTTPS.
//
// It can act as a DNS-to-HTTPS proxy, exposing a traditional DNS server and
// resolving queries using any DNS-over-HTTP (DoH) server.
//
// It can also act as an HTTPS-to-DNS proxy, so you can use it as a DoH server
// if you want more control over the servers and the final DNS server used
// (for example if you are in an isolated environment, such as a test lab or a
// private network).
//
// See the README.md file for more details.
package main
import (
"flag"
"net/url"
"os"
"os/signal"
"sync"
"syscall"
"blitiri.com.ar/go/dnss/internal/dnsserver"
"blitiri.com.ar/go/dnss/internal/httpresolver"
"blitiri.com.ar/go/dnss/internal/httpserver"
"blitiri.com.ar/go/log"
// Register pprof handlers for monitoring and debugging.
_ "net/http/pprof"
)
var (
dnsListenAddr = flag.String("dns_listen_addr", ":53",
"address to listen on for DNS")
dnsUnqualifiedUpstream = flag.String("dns_unqualified_upstream", "",
"DNS server to forward unqualified requests to")
dnsServerForDomain = flag.String("dns_server_for_domain", "",
"DNS server to use for a specific domain, "+
`in the form of "domain1:addr1, domain2:addr, ..."`)
fallbackUpstream = flag.String("fallback_upstream", "8.8.8.8:53",
"DNS server used to resolve domains in -https_upstream"+
" (including proxy if needed)")
enableDNStoHTTPS = flag.Bool("enable_dns_to_https", false,
"enable DNS-to-HTTPS proxy")
httpsUpstream = flag.String("https_upstream",
"https://dns.google/dns-query",
"URL of upstream DNS-to-HTTP server")
httpsClientCAFile = flag.String("https_client_cafile", "",
"CA file to use for the HTTPS client")
enableCache = flag.Bool("enable_cache", true, "enable the local cache")
enableHTTPStoDNS = flag.Bool("enable_https_to_dns", false,
"enable HTTPS-to-DNS proxy")
dnsUpstream = flag.String("dns_upstream",
"8.8.8.8:53",
"Address of the upstream DNS server (for the HTTPS-to-DNS proxy)")
httpsCertFile = flag.String("https_cert", "",
"certificate to use for the HTTPS server")
httpsKeyFile = flag.String("https_key", "",
"key to use for the HTTPS server")
httpsAddr = flag.String("https_server_addr", ":443",
"address to listen on for HTTPS-to-DNS requests")
insecureHTTPServer = flag.Bool("insecure_http_server", false,
"listen on plain HTTP, not HTTPS")
monitoringListenAddr = flag.String("monitoring_listen_addr", "",
"address to listen on for monitoring HTTP requests")
// Deprecated flags that no longer make sense; we keep them for backwards
// compatibility but may be removed in the future.
_ = flag.Duration("log_flush_every", 0, "deprecated, will be removed")
_ = flag.Bool("logtostderr", false, "deprecated, will be removed")
_ = flag.String("force_mode", "", "deprecated, will be removed")
_ = flag.String("fallback_domains", "", "deprecated, will be removed")
)
func main() {
flag.Parse()
log.Init()
log.Infof("dnss starting (%s, %s)",
Version,
SourceDate.Format("2006-01-02 15:04:05 -0700"))
go signalHandler()
if *monitoringListenAddr != "" {
go monitoringServer(*monitoringListenAddr)
}
if !(*enableDNStoHTTPS || *enableHTTPStoDNS) {
log.Errorf("Need to set one of the following:")
log.Errorf(" --enable_dns_to_https")
log.Errorf(" --enable_https_to_dns")
log.Fatalf("")
}
var wg sync.WaitGroup
// DNS to HTTPS.
if *enableDNStoHTTPS {
upstream, err := url.Parse(*httpsUpstream)
if err != nil {
log.Fatalf("-https_upstream is not a valid URL: %v", err)
}
var resolver dnsserver.Resolver
resolver = httpresolver.NewDoH(upstream, *httpsClientCAFile, *fallbackUpstream)
if *enableCache {
cr := dnsserver.NewCachingResolver(resolver)
cr.RegisterDebugHandlers()
resolver = cr
}
overrides, err := dnsserver.DomainMapFromString(*dnsServerForDomain)
if err != nil {
log.Fatalf("-dns_server_for_domain is not valid: %v", err)
}
dth := dnsserver.New(*dnsListenAddr, resolver,
*dnsUnqualifiedUpstream, overrides)
wg.Add(1)
go func() {
defer wg.Done()
dth.ListenAndServe()
}()
}
// HTTPS to DNS.
if *enableHTTPStoDNS {
s := httpserver.Server{
Addr: *httpsAddr,
Upstream: *dnsUpstream,
CertFile: *httpsCertFile,
KeyFile: *httpsKeyFile,
Insecure: *insecureHTTPServer,
}
wg.Add(1)
go func() {
defer wg.Done()
s.ListenAndServe()
}()
}
wg.Wait()
}
func signalHandler() {
signals := make(chan os.Signal, 1)
signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT)
for sig := range signals {
switch sig {
case syscall.SIGTERM, syscall.SIGINT:
log.Fatalf("Got signal to exit: %v", sig)
}
}
}