From 811a3d94df2d096f9afbbfffabd033de882ce30c Mon Sep 17 00:00:00 2001 From: Vladimir Stoilov Date: Tue, 5 Nov 2024 13:13:24 +0200 Subject: [PATCH] [service] Add disabled state to the resolver --- go.mod | 3 ++- go.sum | 2 ++ service/compat/module.go | 9 +++++++++ service/firewall/bypassing.go | 12 ++++++++++++ service/firewall/module.go | 5 +++-- service/firewall/packet_handler.go | 3 ++- service/resolver/main.go | 7 +++++-- service/resolver/resolvers.go | 11 +++++++++-- 8 files changed, 44 insertions(+), 8 deletions(-) diff --git a/go.mod b/go.mod index 436df0948..74baff29e 100644 --- a/go.mod +++ b/go.mod @@ -34,6 +34,7 @@ require ( github.com/hashicorp/go-version v1.7.0 github.com/jackc/puddle/v2 v2.2.1 github.com/lmittmann/tint v1.0.5 + github.com/maruel/panicparse/v2 v2.3.1 github.com/mat/besticon v3.12.0+incompatible github.com/mattn/go-colorable v0.1.13 github.com/mattn/go-isatty v0.0.20 @@ -57,6 +58,7 @@ require ( github.com/tidwall/gjson v1.17.3 github.com/tidwall/sjson v1.2.5 github.com/umahmood/haversine v0.0.0-20151105152445-808ab04add26 + github.com/varlink/go v0.4.0 github.com/vincent-petithory/dataurl v1.0.0 go.etcd.io/bbolt v1.3.10 golang.org/x/exp v0.0.0-20240808152545-0cdaa3abc0fa @@ -90,7 +92,6 @@ require ( github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/josharian/native v1.1.0 // indirect github.com/klauspost/cpuid/v2 v2.2.8 // indirect - github.com/maruel/panicparse/v2 v2.3.1 // indirect github.com/mdlayher/netlink v1.7.2 // indirect github.com/mdlayher/socket v0.5.1 // indirect github.com/mitchellh/reflectwalk v1.0.2 // indirect diff --git a/go.sum b/go.sum index 50df69d64..d05bd31dc 100644 --- a/go.sum +++ b/go.sum @@ -311,6 +311,8 @@ github.com/valyala/fastrand v1.1.0 h1:f+5HkLW4rsgzdNoleUOB69hyT9IlD2ZQh9GyDMfb5G github.com/valyala/fastrand v1.1.0/go.mod h1:HWqCzkrkg6QXT8V2EXWvXCoow7vLwOFN002oeRzjapQ= github.com/valyala/histogram v1.2.0 h1:wyYGAZZt3CpwUiIb9AU/Zbllg1llXyrtApRS815OLoQ= github.com/valyala/histogram v1.2.0/go.mod h1:Hb4kBwb4UxsaNbbbh+RRz8ZR6pdodR57tzWUS3BUzXY= +github.com/varlink/go v0.4.0 h1:+/BQoUO9eJK/+MTSHwFcJch7TMsb6N6Dqp6g0qaXXRo= +github.com/varlink/go v0.4.0/go.mod h1:DKg9Y2ctoNkesREGAEak58l+jOC6JU2aqZvUYs5DynU= github.com/vincent-petithory/dataurl v1.0.0 h1:cXw+kPto8NLuJtlMsI152irrVw9fRDX8AbShPRpg2CI= github.com/vincent-petithory/dataurl v1.0.0/go.mod h1:FHafX5vmDzyP+1CQATJn7WFKc9CvnvxyvZy6I1MrG/U= github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= diff --git a/service/compat/module.go b/service/compat/module.go index 5ac97b511..62118368d 100644 --- a/service/compat/module.go +++ b/service/compat/module.go @@ -99,6 +99,12 @@ func stop() error { } func selfcheckTaskFunc(wc *mgr.WorkerCtx) error { + res := module.instance.Resolver() + if res.IsDisabled.IsSet() { + log.Debugf("compat: skipping self-check: resolver is disabled") + return nil + } + // Create tracing logger. ctx, tracer := log.AddTracer(wc.Ctx()) defer tracer.Submit() @@ -118,6 +124,8 @@ func selfcheckTaskFunc(wc *mgr.WorkerCtx) error { tracer.Warningf("compat: %s", err) case selfcheckNetworkChangedFlag.IsSet(): // The network changed, ignore the issue. + case res.IsDisabled.IsSet(): + // Portmaster resolver is disabled, ignore this issue. default: // The self-check failed. @@ -181,4 +189,5 @@ func New(instance instance) (*Compat, error) { type instance interface { NetEnv() *netenv.NetEnv + Resolver() *resolver.ResolverModule } diff --git a/service/firewall/bypassing.go b/service/firewall/bypassing.go index 415fc6c88..1c9077f02 100644 --- a/service/firewall/bypassing.go +++ b/service/firewall/bypassing.go @@ -43,6 +43,18 @@ func PreventBypassing(ctx context.Context, conn *network.Connection) (endpoints. return endpoints.NoMatch, "", nil } + // If Portmaster resolver is disabled allow requests going to system dns resolver. + // And allow all connections out of the System Resolver. + if module.instance.Resolver().IsDisabled.IsSet() { + // TODO(vladimir): Is there a more specific check that can be done? + if conn.Process().IsSystemResolver() { + return endpoints.NoMatch, "", nil + } + if conn.Entity.Port == 53 && conn.Entity.IPScope.IsLocalhost() { + return endpoints.NoMatch, "", nil + } + } + // Block bypass attempts using an (encrypted) DNS server. switch { case conn.Entity.Port == 53: diff --git a/service/firewall/module.go b/service/firewall/module.go index 131d4cacb..2ac87de2c 100644 --- a/service/firewall/module.go +++ b/service/firewall/module.go @@ -16,6 +16,7 @@ import ( "github.com/safing/portmaster/service/netquery" "github.com/safing/portmaster/service/network" "github.com/safing/portmaster/service/profile" + "github.com/safing/portmaster/service/resolver" "github.com/safing/portmaster/spn/access" "github.com/safing/portmaster/spn/captain" ) @@ -34,8 +35,7 @@ func (ss *stringSliceFlag) Set(value string) error { var allowedClients stringSliceFlag type Firewall struct { - mgr *mgr.Manager - + mgr *mgr.Manager instance instance } @@ -165,4 +165,5 @@ type instance interface { Access() *access.Access Network() *network.Network NetQuery() *netquery.NetQuery + Resolver() *resolver.ResolverModule } diff --git a/service/firewall/packet_handler.go b/service/firewall/packet_handler.go index a290182f8..4c06c9682 100644 --- a/service/firewall/packet_handler.go +++ b/service/firewall/packet_handler.go @@ -444,8 +444,9 @@ func filterHandler(conn *network.Connection, pkt packet.Packet) { filterConnection = false log.Tracer(pkt.Ctx()).Infof("filter: granting own pre-authenticated connection %s", conn) - // Redirect outbound DNS packets if enabled, + // Redirect outbound DNS packets if enabled, case dnsQueryInterception() && + module.instance.Resolver().IsDisabled.IsNotSet() && pkt.IsOutbound() && pkt.Info().DstPort == 53 && // that don't match the address of our nameserver, diff --git a/service/resolver/main.go b/service/resolver/main.go index 8a43d12be..da22b064f 100644 --- a/service/resolver/main.go +++ b/service/resolver/main.go @@ -29,6 +29,8 @@ type ResolverModule struct { //nolint failingResolverWorkerMgr *mgr.WorkerMgr suggestUsingStaleCacheTask *mgr.WorkerMgr + IsDisabled abool.AtomicBool + states *mgr.StateMgr } @@ -267,8 +269,9 @@ func New(instance instance) (*ResolverModule, error) { } m := mgr.New("Resolver") module = &ResolverModule{ - mgr: m, - instance: instance, + mgr: m, + instance: instance, + IsDisabled: *abool.New(), states: mgr.NewStateMgr(m), } diff --git a/service/resolver/resolvers.go b/service/resolver/resolvers.go index c5609a017..59abc37ad 100644 --- a/service/resolver/resolvers.go +++ b/service/resolver/resolvers.go @@ -388,7 +388,6 @@ func loadResolvers() { // Resolve module error about missing resolvers. module.states.Remove(missingResolversErrorID) - // Check if settings were changed and clear name cache when they did. newResolverConfig := configuredNameServers() if len(currentResolverConfig) > 0 && @@ -399,6 +398,14 @@ func loadResolvers() { return err }) } + + // If no resolvers are configure set the disabled state. So other modules knows that the users does not want to use Portmaster resolver. + if len(newResolverConfig) == 0 { + module.IsDisabled.Set() + } else { + module.IsDisabled.UnSet() + } + currentResolverConfig = newResolverConfig newResolvers := append( @@ -431,7 +438,7 @@ func loadResolvers() { // save resolvers globalResolvers = newResolvers - // assing resolvers to scopes + // assign resolvers to scopes setScopedResolvers(globalResolvers) // set active resolvers (for cache validation)