Skip to content

Commit cdfb27a

Browse files
committed
dns: export Make methods to client
Lets client create standalone DNS transports. Useful especially for Measure()
1 parent 5ae08b2 commit cdfb27a

1 file changed

Lines changed: 103 additions & 63 deletions

File tree

intra/dns.go

Lines changed: 103 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ package intra
88

99
import (
1010
"context"
11+
"net/netip"
1112
"strconv"
1213
"strings"
1314

@@ -24,35 +25,97 @@ import (
2425
"github.com/celzero/firestack/intra/xdns"
2526
)
2627

28+
// MakeDoHTransport creates a DNS-over-HTTPS transport for id, dialing via the
29+
// tunnel's proxies. ipcsv, if any, is a csv of IP (or ip:port) addresses of the
30+
// DoH server, used to bypass the system resolver when dialing url.
31+
func MakeDoHTransport(t Tunnel, id, url, ipcsv string) (dnsx.Transport, error) {
32+
px, perr := t.internalProxies()
33+
if perr != nil {
34+
return nil, perr
35+
}
36+
return doh.NewTransport(t.internalCtx(), id, url, csv2slice(ipcsv), px)
37+
}
38+
39+
// MakeODoHTransport creates an Oblivious-DoH transport for id, dialing via the
40+
// tunnel's proxies. endpoint is the entry / proxy for the ODoH server; resolver
41+
// is the URL of the target ODoH server. epipcsv, if any, is a csv of IP (or
42+
// ip:port) addresses of the endpoint, used to bypass the system resolver.
43+
func MakeODoHTransport(t Tunnel, id, endpoint, resolver, epipcsv string) (dnsx.Transport, error) {
44+
px, perr := t.internalProxies()
45+
if perr != nil {
46+
return nil, perr
47+
}
48+
return doh.NewOdohTransport(t.internalCtx(), id, endpoint, resolver, csv2slice(epipcsv), px)
49+
}
50+
51+
// MakeDoTTransport creates a DNS-over-TLS transport for id, dialing via the
52+
// tunnel's proxies. ipcsv, if any, is a csv of IP (or ip:port) addresses of the
53+
// DoT server, used to bypass the system resolver.
54+
func MakeDoTTransport(t Tunnel, id, url, ipcsv string) (dnsx.Transport, error) {
55+
px, perr := t.internalProxies()
56+
if perr != nil {
57+
return nil, perr
58+
}
59+
return dns53.NewTLSTransport(t.internalCtx(), id, url, csv2slice(ipcsv), px)
60+
}
61+
62+
// MakeDNS53Transport creates a DNS53 (plain DNS over UDP/TCP) transport for id,
63+
// serving from hostOrHostport (a host, host:port, or ip:port), dialing via the
64+
// tunnel's proxies. ipcsv, if any, is a csv of ip or ip:port addresses of the
65+
// server, bypassing the system resolver.
66+
func MakeDNS53Transport(t Tunnel, id, hostOrHostport, ipcsv string) (dnsx.Transport, error) {
67+
px, perr := t.internalProxies()
68+
if perr != nil {
69+
return nil, perr
70+
}
71+
return dns53.NewTransportFromHostname(t.internalCtx(), id, hostOrHostport, ipcsv, px)
72+
}
73+
74+
// MakeDNS53TransportFrom creates a DNS53 transport for id, serving from ipp,
75+
// dialing via the tunnel's proxies.
76+
func MakeDNS53TransportFrom(t Tunnel, id string, ipp netip.AddrPort) (dnsx.Transport, error) {
77+
px, perr := t.internalProxies()
78+
if perr != nil {
79+
return nil, perr
80+
}
81+
return dns53.NewTransportFrom(t.internalCtx(), id, ipp, px)
82+
}
83+
84+
// csv2slice splits a comma-separated csv into a slice; returns nil if csv is
85+
// empty (the underlying transports treat nil/empty the same).
86+
func csv2slice(csv string) (xs []string) {
87+
if len(csv) > 0 {
88+
xs = strings.Split(csv, ",")
89+
}
90+
return // nil for empty csv
91+
}
92+
2793
// AddDNSProxy creates and adds a DNS53 transport to the tunnel's resolver.
2894
func AddDNSProxy(t Tunnel, id, ippcsv string) error {
29-
p, perr := t.internalProxies()
3095
r, rerr := t.internalResolver()
31-
if rerr != nil || perr != nil {
32-
return core.JoinErr(rerr, perr)
96+
if rerr != nil {
97+
return rerr
3398
}
34-
ctx := t.internalCtx()
3599
specialHostname := protect.HostlessPrefix + id
36-
if dns, err := dns53.NewTransportFromHostname(ctx, id, specialHostname, ippcsv, p); err != nil {
100+
dns, err := MakeDNS53Transport(t, id, specialHostname, ippcsv)
101+
if err != nil {
37102
return err
38-
} else {
39-
return addDNSTransport(r, dns)
40103
}
104+
return addDNSTransport(r, dns)
41105
}
42106

43-
func newSystemDNSProxy(ctx context.Context, p ipn.ProxyProvider, ipcsv string) (d dnsx.Transport, err error) {
107+
func newSystemDNSProxy(t Tunnel, ipcsv string) (d dnsx.Transport, err error) {
44108
specialHostname := protect.Systemhost // never resolved by ipmap:LookupNetIP
45-
return dns53.NewTransportFromHostname(ctx, dnsx.System, specialHostname, ipcsv, p)
109+
return MakeDNS53Transport(t, dnsx.System, specialHostname, ipcsv)
46110
}
47111

48112
// SetSystemDNS creates and adds a DNS53 transport of the specified IP addresses.
49113
func SetSystemDNS(t Tunnel, ipcsvx string) error {
50114
r, rerr := t.internalResolver()
51-
p, perr := t.internalProxies()
52-
ctx := t.internalCtx()
115+
_, perr := t.internalProxies()
53116
ipcsv := ipcsvx
54117
n := len(ipcsv)
55-
if r == nil || p == nil {
118+
if rerr != nil || perr != nil {
56119
log.W("dns: sys: cannot set system dns; n: %d, errs: %v %v", n, rerr, perr)
57120
return core.JoinErr(dnsx.ErrAddFailed, rerr, perr)
58121
}
@@ -74,7 +137,7 @@ func SetSystemDNS(t Tunnel, ipcsvx string) error {
74137
}
75138

76139
var ok bool
77-
if sdns, err := newSystemDNSProxy(ctx, p, ipcsv); err == nil {
140+
if sdns, err := newSystemDNSProxy(t, ipcsv); err == nil {
78141
ok = r.Add(sdns)
79142
} else {
80143
return err
@@ -131,13 +194,11 @@ func AddDefaultTransport(t Tunnel, typ, ippOrUrl, ips string) error {
131194

132195
// AddProxyDNS creates and adds a DNS53 transport as defined in Proxy's configuration.
133196
func AddProxyDNS(t Tunnel, p x.Proxy) error {
134-
pxr, perr := t.internalProxies()
135197
r, rerr := t.internalResolver()
136-
if rerr != nil || perr != nil {
137-
return core.JoinErr(rerr, perr)
198+
if rerr != nil {
199+
return rerr
138200
}
139201
pid := p.ID()
140-
ctx := t.internalCtx()
141202
// TODO: create dns53.NewTransportForProxy() which is self-healing and
142203
// uses updated DNS addresses if p.DNS() has changed/updated
143204
ipOrHostCsv := p.DNS() // may return csv(host:port), csv(ip:port), csv(ips), csv(host)
@@ -152,81 +213,60 @@ func AddProxyDNS(t Tunnel, p x.Proxy) error {
152213
}
153214
first := ipsOrHost[0]
154215
ipport, err := xdns.DnsIPPort(first)
155-
hostOrHostport := first // could be multiple hostnames or host:ports, but choose the first
156-
if err != nil { // use hostname
157-
if dns, err := dns53.NewTransportFromHostname(ctx, pid, hostOrHostport, "" /*ip or ip:port csv*/, pxr); err != nil {
158-
return err
159-
} else {
160-
return addDNSTransport(r, dns)
216+
if err != nil { // use hostname
217+
dns, derr := MakeDNS53Transport(t, pid, first, "" /*ip or ip:port csv*/)
218+
if derr != nil {
219+
return derr
161220
}
162-
// use ipports; register with same id as the proxy p
163-
} else if dns, err := dns53.NewTransportFrom(ctx, pid, ipport, pxr); err != nil {
164-
return err
165-
} else {
166221
return addDNSTransport(r, dns)
167222
}
223+
// use ipports; register with same id as the proxy p
224+
dns, derr := MakeDNS53TransportFrom(t, pid, ipport)
225+
if derr != nil {
226+
return derr
227+
}
228+
return addDNSTransport(r, dns)
168229
}
169230

170231
// AddDoHTransport creates and adds a Transport that connects to the specified DoH server.
171232
// `url` is the URL of a DoH server (no template, POST-only).
172233
func AddDoHTransport(t Tunnel, id, url, ipcsv string) error {
173-
pxr, perr := t.internalProxies()
174234
r, rerr := t.internalResolver()
175-
if rerr != nil || perr != nil {
176-
return core.JoinErr(rerr, perr)
177-
}
178-
ips := ipcsv
179-
ctx := t.internalCtx()
180-
split := []string{}
181-
if len(ips) > 0 {
182-
split = strings.Split(ips, ",")
235+
if rerr != nil {
236+
return rerr
183237
}
184-
if dns, err := doh.NewTransport(ctx, id, url, split, pxr); err != nil {
238+
dns, err := MakeDoHTransport(t, id, url, ipcsv)
239+
if err != nil {
185240
return err
186-
} else {
187-
return addDNSTransport(r, dns)
188241
}
242+
return addDNSTransport(r, dns)
189243
}
190244

191245
// AddODoHTransport creates and adds a Transport that connects to the specified ODoH server.
192246
// `endpoint` is the entry / proxy for the ODoH server, `resolver` is the URL of the target ODoH server.
193247
func AddODoHTransport(t Tunnel, id, endpoint, resolver, epipcsv string) error {
194-
pxr, perr := t.internalProxies()
195248
r, rerr := t.internalResolver()
196-
if rerr != nil || perr != nil {
197-
return core.JoinErr(rerr, perr)
198-
}
199-
epips := epipcsv
200-
ctx := t.internalCtx()
201-
split := []string{}
202-
if len(epips) > 0 {
203-
split = strings.Split(epips, ",")
249+
if rerr != nil {
250+
return rerr
204251
}
205-
if dns, err := doh.NewOdohTransport(ctx, id, endpoint, resolver, split, pxr); err != nil {
252+
dns, err := MakeODoHTransport(t, id, endpoint, resolver, epipcsv)
253+
if err != nil {
206254
return err
207-
} else {
208-
return addDNSTransport(r, dns)
209255
}
256+
return addDNSTransport(r, dns)
210257
}
211258

212259
// AddDoTTransport creates and adds a Transport that connects to the specified DoT server.
213260
func AddDoTTransport(t Tunnel, id, url, ipcsv string) error {
214-
pxr, perr := t.internalProxies()
215261
r, rerr := t.internalResolver()
216-
if rerr != nil || perr != nil {
217-
return core.JoinErr(rerr, perr)
218-
}
219-
ctx := t.internalCtx()
220-
split := []string{}
221-
ips := ipcsv
222-
if len(ips) > 0 {
223-
split = strings.Split(ips, ",")
262+
if rerr != nil {
263+
return rerr
224264
}
225-
if dns, err := dns53.NewTLSTransport(ctx, id, url, split, pxr); err != nil {
265+
dns, err := MakeDoTTransport(t, id, url, ipcsv)
266+
if err != nil {
226267
return err
227-
} else {
228-
return addDNSTransport(r, dns)
229268
}
269+
return addDNSTransport(r, dns)
230270
}
231271

232272
// AddDNSCryptTransport creates and adds a DNSCrypt transport to the tunnel's resolver.

0 commit comments

Comments
 (0)