Skip to content

Commit b7735ec

Browse files
committed
fix(updater): only uses DoH to cloudflare+google
- prevent dns plaintext manipulation both the periodic update and when running in cli mode - possibly higher reliability on poor connections versus UDP - drop `-dns` flag in update command - for now no configuration allowed since it makes everything rather complex
1 parent 457e559 commit b7735ec

7 files changed

Lines changed: 47 additions & 37 deletions

File tree

cmd/gluetun/main.go

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import (
1616
_ "time/tzdata"
1717

1818
_ "github.com/breml/rootcerts"
19+
"github.com/qdm12/dns/v2/pkg/doh"
20+
dnsprovider "github.com/qdm12/dns/v2/pkg/provider"
1921
"github.com/qdm12/gluetun/internal/alpine"
2022
"github.com/qdm12/gluetun/internal/boringpoll"
2123
"github.com/qdm12/gluetun/internal/cli"
@@ -433,10 +435,18 @@ func _main(ctx context.Context, buildInfo models.BuildInformation,
433435
go healthcheckServer.Run(healthServerCtx, healthServerDone)
434436
healthChecker := healthcheck.NewChecker(healthLogger)
435437

438+
// Note: we use a separate DoH dialer for the VPN servers data updater, separate from the
439+
// main DNS local server to make sure no request is blocked by filters.
440+
dohDialer, err := doh.New(doh.Settings{
441+
UpstreamResolvers: []dnsprovider.Provider{dnsprovider.Cloudflare(), dnsprovider.Google()},
442+
})
443+
if err != nil {
444+
return fmt.Errorf("creating updater DoH dialer: %w", err)
445+
}
436446
updaterLogger := logger.New(log.SetComponent("updater"))
437447

438448
unzipper := unzip.New(httpClient)
439-
parallelResolver := resolver.NewParallelResolver(allSettings.Updater.DNSAddress)
449+
parallelResolver := resolver.NewParallelResolver(dohDialer)
440450
openvpnFileExtractor := extract.New()
441451
providers := provider.NewProviders(storage, time.Now, updaterLogger,
442452
httpClient, unzipper, parallelResolver, publicIPLooper.Fetcher(),

internal/cli/update.go

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ import (
1010
"strings"
1111
"time"
1212

13+
"github.com/qdm12/dns/v2/pkg/doh"
14+
dnsprovider "github.com/qdm12/dns/v2/pkg/provider"
1315
"github.com/qdm12/gluetun/internal/configuration/settings"
1416
"github.com/qdm12/gluetun/internal/constants"
1517
"github.com/qdm12/gluetun/internal/constants/providers"
@@ -38,12 +40,12 @@ type UpdaterLogger interface {
3840
func (c *CLI) Update(ctx context.Context, args []string, logger UpdaterLogger) error {
3941
options := settings.Updater{}
4042
var endUserMode, maintainerMode, updateAll bool
41-
var csvProviders, ipToken, protonUsername, protonEmail, protonPassword string
43+
var dnsServer, csvProviders, ipToken, protonUsername, protonEmail, protonPassword string
4244
flagSet := flag.NewFlagSet("update", flag.ExitOnError)
4345
flagSet.BoolVar(&endUserMode, "enduser", false, "Write results to /gluetun/servers.json (for end users)")
4446
flagSet.BoolVar(&maintainerMode, "maintainer", false,
4547
"Write results to ./internal/storage/servers.json to modify the program (for maintainers)")
46-
flagSet.StringVar(&options.DNSAddress, "dns", "8.8.8.8", "DNS resolver address to use")
48+
flagSet.StringVar(&dnsServer, "dns", "", "no longer used, your DNS will use DoH with Cloudflare and Google")
4749
const defaultMinRatio = 0.8
4850
flagSet.Float64Var(&options.MinRatio, "minratio", defaultMinRatio,
4951
"Minimum ratio of servers to find for the update to succeed")
@@ -58,6 +60,10 @@ func (c *CLI) Update(ctx context.Context, args []string, logger UpdaterLogger) e
5860
return err
5961
}
6062

63+
if dnsServer != "" {
64+
logger.Warn("The -dns flag is no longer used, your DNS will use DoH with Cloudflare and Google")
65+
}
66+
6167
if !endUserMode && !maintainerMode {
6268
return fmt.Errorf("%w", ErrModeUnspecified)
6369
}
@@ -97,10 +103,21 @@ func (c *CLI) Update(ctx context.Context, args []string, logger UpdaterLogger) e
97103
return fmt.Errorf("creating servers storage: %w", err)
98104
}
99105

106+
dohSettings := doh.Settings{
107+
UpstreamResolvers: []dnsprovider.Provider{
108+
dnsprovider.Cloudflare(),
109+
dnsprovider.Google(),
110+
},
111+
}
112+
dnsDialer, err := doh.New(dohSettings)
113+
if err != nil {
114+
return fmt.Errorf("creating DoH dialer: %w", err)
115+
}
116+
100117
const clientTimeout = 10 * time.Second
101118
httpClient := &http.Client{Timeout: clientTimeout}
102119
unzipper := unzip.New(httpClient)
103-
parallelResolver := resolver.NewParallelResolver(options.DNSAddress)
120+
parallelResolver := resolver.NewParallelResolver(dnsDialer)
104121
nameTokenPairs := []api.NameToken{
105122
{Name: string(api.IPInfo), Token: ipToken},
106123
{Name: string(api.IP2Location)},

internal/configuration/settings/updater.go

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,6 @@ type Updater struct {
2121
// updater. It cannot be nil in the internal state.
2222
// TODO change to value and add Enabled field.
2323
Period *time.Duration
24-
// DNSAddress is the DNS server address to use
25-
// to resolve VPN server hostnames to IP addresses.
26-
// It cannot be the empty string in the internal state.
27-
DNSAddress string
2824
// MinRatio is the minimum ratio of servers to
2925
// find per provider, compared to the total current
3026
// number of servers. It defaults to 0.8.
@@ -76,7 +72,6 @@ func (u Updater) Validate() (err error) {
7672
func (u *Updater) copy() (copied Updater) {
7773
return Updater{
7874
Period: gosettings.CopyPointer(u.Period),
79-
DNSAddress: u.DNSAddress,
8075
MinRatio: u.MinRatio,
8176
Providers: gosettings.CopySlice(u.Providers),
8277
ProtonEmail: gosettings.CopyPointer(u.ProtonEmail),
@@ -89,7 +84,6 @@ func (u *Updater) copy() (copied Updater) {
8984
// settings.
9085
func (u *Updater) overrideWith(other Updater) {
9186
u.Period = gosettings.OverrideWithPointer(u.Period, other.Period)
92-
u.DNSAddress = gosettings.OverrideWithComparable(u.DNSAddress, other.DNSAddress)
9387
u.MinRatio = gosettings.OverrideWithComparable(u.MinRatio, other.MinRatio)
9488
u.Providers = gosettings.OverrideWithSlice(u.Providers, other.Providers)
9589
u.ProtonEmail = gosettings.OverrideWithPointer(u.ProtonEmail, other.ProtonEmail)
@@ -98,7 +92,6 @@ func (u *Updater) overrideWith(other Updater) {
9892

9993
func (u *Updater) SetDefaults(vpnProvider string) {
10094
u.Period = gosettings.DefaultPointer(u.Period, 0)
101-
u.DNSAddress = gosettings.DefaultComparable(u.DNSAddress, "1.1.1.1:53")
10295

10396
if u.MinRatio == 0 {
10497
const defaultMinRatio = 0.8
@@ -125,7 +118,6 @@ func (u Updater) toLinesNode() (node *gotree.Node) {
125118

126119
node = gotree.New("Server data updater settings:")
127120
node.Appendf("Update period: %s", *u.Period)
128-
node.Appendf("DNS address: %s", u.DNSAddress)
129121
node.Appendf("Minimum ratio: %.1f", u.MinRatio)
130122
node.Appendf("Providers to update: %s", strings.Join(u.Providers, ", "))
131123
if slices.Contains(u.Providers, providers.Protonvpn) {
@@ -142,11 +134,6 @@ func (u *Updater) read(r *reader.Reader) (err error) {
142134
return err
143135
}
144136

145-
u.DNSAddress, err = readUpdaterDNSAddress()
146-
if err != nil {
147-
return err
148-
}
149-
150137
u.MinRatio, err = r.Float64("UPDATER_MIN_RATIO")
151138
if err != nil {
152139
return err
@@ -166,12 +153,3 @@ func (u *Updater) read(r *reader.Reader) (err error) {
166153

167154
return nil
168155
}
169-
170-
func readUpdaterDNSAddress() (address string, err error) {
171-
// TODO this is currently using Cloudflare in
172-
// plaintext to not be blocked by DNS over TLS by default.
173-
// If a plaintext address is set in the DNS settings, this one will be used.
174-
// use custom future encrypted DNS written in Go without blocking
175-
// as it's too much trouble to start another parallel unbound instance for now.
176-
return "", nil
177-
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package resolver
2+
3+
import (
4+
"context"
5+
"net"
6+
)
7+
8+
type Dialer interface {
9+
Dial(ctx context.Context, network, address string) (net.Conn, error)
10+
}

internal/updater/resolver/net.go

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,12 @@
11
package resolver
22

33
import (
4-
"context"
54
"net"
65
)
76

8-
func newResolver(resolverAddress string) *net.Resolver {
9-
d := net.Dialer{}
10-
resolverAddress = net.JoinHostPort(resolverAddress, "53")
7+
func newResolver(d Dialer) *net.Resolver {
118
return &net.Resolver{
129
PreferGo: true,
13-
Dial: func(ctx context.Context, _, _ string) (net.Conn, error) {
14-
return d.DialContext(ctx, "udp", resolverAddress)
15-
},
10+
Dial: d.Dial,
1611
}
1712
}

internal/updater/resolver/parallel.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ type Parallel struct {
1111
repeatResolver *Repeat
1212
}
1313

14-
func NewParallelResolver(resolverAddress string) *Parallel {
14+
func NewParallelResolver(dialer Dialer) *Parallel {
1515
return &Parallel{
16-
repeatResolver: NewRepeat(resolverAddress),
16+
repeatResolver: NewRepeat(dialer),
1717
}
1818
}
1919

internal/updater/resolver/repeat.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ type Repeat struct {
1414
resolver *net.Resolver
1515
}
1616

17-
func NewRepeat(resolverAddress string) *Repeat {
17+
func NewRepeat(dialer Dialer) *Repeat {
1818
return &Repeat{
19-
resolver: newResolver(resolverAddress),
19+
resolver: newResolver(dialer),
2020
}
2121
}
2222

0 commit comments

Comments
 (0)