mirror of
https://github.com/safing/portmaster
synced 2025-09-01 18:19:12 +00:00
Merge pull request #821 from safing/feature/spn-improvements
SPN Routing Improvements (and housekeeping)
This commit is contained in:
commit
636c0dc228
32 changed files with 255 additions and 164 deletions
8
.github/workflows/go.yml
vendored
8
.github/workflows/go.yml
vendored
|
@ -20,14 +20,14 @@ jobs:
|
|||
|
||||
- uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '^1.18'
|
||||
go-version: '^1.19'
|
||||
|
||||
- name: Run golangci-lint
|
||||
uses: golangci/golangci-lint-action@v3
|
||||
with:
|
||||
version: v1.45.1
|
||||
version: v1.49.0
|
||||
only-new-issues: true
|
||||
args: -c ./.golangci.yml
|
||||
args: -c ./.golangci.yml --timeout 15m
|
||||
|
||||
- name: Get dependencies
|
||||
run: go mod download
|
||||
|
@ -45,7 +45,7 @@ jobs:
|
|||
- name: Setup Go
|
||||
uses: actions/setup-go@v3
|
||||
with:
|
||||
go-version: '^1.18'
|
||||
go-version: '^1.19'
|
||||
|
||||
- name: Get dependencies
|
||||
run: go mod download
|
||||
|
|
|
@ -8,6 +8,7 @@ linters:
|
|||
- contextcheck
|
||||
- cyclop
|
||||
- exhaustivestruct
|
||||
- exhaustruct
|
||||
- forbidigo
|
||||
- funlen
|
||||
- gochecknoglobals
|
||||
|
@ -17,6 +18,7 @@ linters:
|
|||
- goerr113
|
||||
- gomnd
|
||||
- ifshort
|
||||
- interfacebloat
|
||||
- interfacer
|
||||
- ireturn
|
||||
- lll
|
||||
|
@ -24,6 +26,9 @@ linters:
|
|||
- nilnil
|
||||
- nlreturn
|
||||
- noctx
|
||||
- nolintlint
|
||||
- nonamedreturns
|
||||
- nosnakecase
|
||||
- revive
|
||||
- tagliatelle
|
||||
- testpackage
|
||||
|
@ -31,7 +36,6 @@ linters:
|
|||
- whitespace
|
||||
- wrapcheck
|
||||
- wsl
|
||||
- nolintlint
|
||||
|
||||
linters-settings:
|
||||
revive:
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
//nolint:gci,nolintlint
|
||||
package main
|
||||
|
||||
import ( //nolint:gci,nolintlint
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/safing/portbase/info"
|
||||
|
|
|
@ -2,18 +2,17 @@
|
|||
//
|
||||
// Usage:
|
||||
//
|
||||
// package name
|
||||
// package name
|
||||
//
|
||||
// import (
|
||||
// "testing"
|
||||
// import (
|
||||
// "testing"
|
||||
//
|
||||
// "github.com/safing/portmaster/core/pmtesting"
|
||||
// )
|
||||
//
|
||||
// func TestMain(m *testing.M) {
|
||||
// pmtesting.TestMain(m, module)
|
||||
// }
|
||||
// "github.com/safing/portmaster/core/pmtesting"
|
||||
// )
|
||||
//
|
||||
// func TestMain(m *testing.M) {
|
||||
// pmtesting.TestMain(m, module)
|
||||
// }
|
||||
package pmtesting
|
||||
|
||||
import (
|
||||
|
|
|
@ -1,10 +1,9 @@
|
|||
package firewall
|
||||
|
||||
import (
|
||||
"github.com/safing/portbase/api"
|
||||
"github.com/safing/portbase/config"
|
||||
"github.com/safing/portbase/notifications"
|
||||
"github.com/safing/portmaster/core"
|
||||
"github.com/safing/spn/captain"
|
||||
)
|
||||
|
||||
// Configuration Keys.
|
||||
|
@ -26,9 +25,6 @@ var (
|
|||
CfgOptionDNSQueryInterceptionKey = "filter/dnsQueryInterception"
|
||||
cfgOptionDNSQueryInterceptionOrder = 97
|
||||
dnsQueryInterception config.BoolOption
|
||||
|
||||
devMode config.BoolOption
|
||||
apiListenAddress config.StringOption
|
||||
)
|
||||
|
||||
func registerConfig() error {
|
||||
|
@ -108,8 +104,17 @@ func registerConfig() error {
|
|||
}
|
||||
askTimeout = config.Concurrent.GetAsInt(CfgOptionAskTimeoutKey, 60)
|
||||
|
||||
devMode = config.Concurrent.GetAsBool(core.CfgDevModeKey, false)
|
||||
apiListenAddress = config.GetAsString(api.CfgDefaultListenAddressKey, "")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var (
|
||||
filterEnabled config.BoolOption
|
||||
tunnelEnabled config.BoolOption
|
||||
useCommunityNodes config.BoolOption
|
||||
)
|
||||
|
||||
func getConfig() {
|
||||
filterEnabled = config.Concurrent.GetAsBool(CfgOptionEnableFilterKey, true)
|
||||
tunnelEnabled = config.Concurrent.GetAsBool(captain.CfgOptionEnableSPNKey, false)
|
||||
useCommunityNodes = config.Concurrent.GetAsBool(captain.CfgOptionUseCommunityNodesKey, true)
|
||||
}
|
||||
|
|
|
@ -2,22 +2,12 @@ package firewall
|
|||
|
||||
import (
|
||||
"github.com/safing/portbase/config"
|
||||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portbase/modules"
|
||||
"github.com/safing/portbase/modules/subsystems"
|
||||
_ "github.com/safing/portmaster/core"
|
||||
"github.com/safing/portmaster/intel/filterlists"
|
||||
"github.com/safing/spn/captain"
|
||||
)
|
||||
|
||||
var (
|
||||
filterModule *modules.Module
|
||||
filterEnabled config.BoolOption
|
||||
tunnelEnabled config.BoolOption
|
||||
|
||||
unbreakFilterListIDs = []string{"UNBREAK"}
|
||||
resolvedUnbreakFilterListIDs []string
|
||||
)
|
||||
var filterModule *modules.Module
|
||||
|
||||
func init() {
|
||||
filterModule = modules.Register("filter", filterPrep, filterStart, nil, "core", "intel")
|
||||
|
@ -48,18 +38,11 @@ func filterPrep() (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
filterEnabled = config.Concurrent.GetAsBool(CfgOptionEnableFilterKey, true)
|
||||
tunnelEnabled = config.Concurrent.GetAsBool(captain.CfgOptionEnableSPNKey, false)
|
||||
return nil
|
||||
}
|
||||
|
||||
func filterStart() error {
|
||||
// TODO: Re-resolve IDs when filterlist index changes.
|
||||
resolvedIDs, err := filterlists.ResolveListIDs(unbreakFilterListIDs)
|
||||
if err != nil {
|
||||
log.Warningf("filter: failed to resolve unbreak filter list IDs: %s", err)
|
||||
} else {
|
||||
resolvedUnbreakFilterListIDs = resolvedIDs
|
||||
}
|
||||
getConfig()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -13,9 +13,12 @@ import (
|
|||
"github.com/tevino/abool"
|
||||
"golang.org/x/sync/singleflight"
|
||||
|
||||
"github.com/safing/portbase/api"
|
||||
"github.com/safing/portbase/config"
|
||||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portbase/modules"
|
||||
"github.com/safing/portmaster/compat"
|
||||
"github.com/safing/portmaster/core"
|
||||
_ "github.com/safing/portmaster/core/base"
|
||||
"github.com/safing/portmaster/firewall/inspection"
|
||||
"github.com/safing/portmaster/firewall/interception"
|
||||
|
@ -43,7 +46,14 @@ var (
|
|||
ownPID = os.Getpid()
|
||||
)
|
||||
|
||||
// Config variables for interception module.
|
||||
var (
|
||||
devMode config.BoolOption
|
||||
apiListenAddress config.StringOption
|
||||
)
|
||||
|
||||
func init() {
|
||||
// TODO: Move interception module to own package (dir).
|
||||
interceptionModule = modules.Register("interception", interceptionPrep, interceptionStart, interceptionStop, "base", "updates", "network", "notifications")
|
||||
|
||||
network.SetDefaultFirewallHandler(defaultHandler)
|
||||
|
@ -54,6 +64,9 @@ func interceptionPrep() error {
|
|||
}
|
||||
|
||||
func interceptionStart() error {
|
||||
devMode = config.Concurrent.GetAsBool(core.CfgDevModeKey, false)
|
||||
apiListenAddress = config.GetAsString(api.CfgDefaultListenAddressKey, "")
|
||||
|
||||
if err := registerMetrics(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
@ -71,15 +71,15 @@ func (pkt *packet) LoadPacketData() error {
|
|||
}
|
||||
|
||||
// TODO(ppacher): revisit the following behavior:
|
||||
// The legacy implementation of nfqueue (and the interception) module
|
||||
// always accept a packet but may mark it so that a subsequent rule in
|
||||
// the C17 chain drops, rejects or modifies it.
|
||||
//
|
||||
// For drop/return we could use the actual nfQueue verdicts Drop and Stop.
|
||||
// Re-routing to local NS or SPN can be done by modifying the packet here
|
||||
// and using SetVerdictModPacket and reject can be implemented using a simple
|
||||
// raw-socket.
|
||||
// The legacy implementation of nfqueue (and the interception) module
|
||||
// always accept a packet but may mark it so that a subsequent rule in
|
||||
// the C17 chain drops, rejects or modifies it.
|
||||
//
|
||||
// For drop/return we could use the actual nfQueue verdicts Drop and Stop.
|
||||
// Re-routing to local NS or SPN can be done by modifying the packet here
|
||||
// and using SetVerdictModPacket and reject can be implemented using a simple
|
||||
// raw-socket.
|
||||
func (pkt *packet) mark(mark int) (err error) {
|
||||
if pkt.verdictPending.SetToIf(false, true) {
|
||||
defer close(pkt.verdictSet)
|
||||
|
|
|
@ -14,6 +14,7 @@ import (
|
|||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portmaster/detection/dga"
|
||||
"github.com/safing/portmaster/intel/customlists"
|
||||
"github.com/safing/portmaster/intel/filterlists"
|
||||
"github.com/safing/portmaster/netenv"
|
||||
"github.com/safing/portmaster/network"
|
||||
"github.com/safing/portmaster/network/netutils"
|
||||
|
@ -435,6 +436,7 @@ func checkFilterLists(ctx context.Context, conn *network.Connection, p *profile.
|
|||
switch result {
|
||||
case endpoints.Denied:
|
||||
// If the connection matches a filter list, check if the "unbreak" list matches too and abort blocking.
|
||||
resolvedUnbreakFilterListIDs := filterlists.GetUnbreakFilterListIDs()
|
||||
for _, blockedListID := range conn.Entity.BlockedByLists {
|
||||
for _, unbreakListID := range resolvedUnbreakFilterListIDs {
|
||||
if blockedListID == unbreakListID {
|
||||
|
|
|
@ -114,6 +114,11 @@ func checkTunneling(ctx context.Context, conn *network.Connection, pkt packet.Pa
|
|||
RoutingProfile: layeredProfile.SPNRoutingAlgorithm(),
|
||||
}
|
||||
|
||||
// Add required verified owners if community nodes should not be used.
|
||||
if !useCommunityNodes() {
|
||||
conn.TunnelOpts.RequireVerifiedOwners = captain.NonCommunityVerifiedOwners
|
||||
}
|
||||
|
||||
// If we have any exit hub policies, we need to raise the routing algorithm at least to single-hop.
|
||||
if conn.TunnelOpts.RoutingProfile == navigator.RoutingProfileHomeID &&
|
||||
conn.TunnelOpts.HubPoliciesAreSet() {
|
||||
|
|
17
go.mod
17
go.mod
|
@ -1,10 +1,9 @@
|
|||
module github.com/safing/portmaster
|
||||
|
||||
go 1.18
|
||||
go 1.19
|
||||
|
||||
require (
|
||||
github.com/agext/levenshtein v1.2.3
|
||||
github.com/cookieo9/resources-go v0.0.0-20150225115733-d27c04069d0d
|
||||
github.com/coreos/go-iptables v0.6.0
|
||||
github.com/florianl/go-nfqueue v1.3.1
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
|
@ -16,16 +15,17 @@ require (
|
|||
github.com/miekg/dns v1.1.50
|
||||
github.com/oschwald/maxminddb-golang v1.10.0
|
||||
github.com/safing/portbase v0.15.1
|
||||
github.com/safing/spn v0.4.15
|
||||
github.com/safing/spn v0.5.0
|
||||
github.com/shirou/gopsutil v3.21.11+incompatible
|
||||
github.com/spf13/cobra v1.5.0
|
||||
github.com/spkg/zipfs v0.7.1
|
||||
github.com/stretchr/testify v1.8.0
|
||||
github.com/tannerryan/ring v1.1.2
|
||||
github.com/tevino/abool v1.2.0
|
||||
github.com/umahmood/haversine v0.0.0-20151105152445-808ab04add26
|
||||
golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b
|
||||
golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde
|
||||
golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
|
||||
zombiezen.com/go/sqlite v0.10.1
|
||||
)
|
||||
|
||||
|
@ -47,7 +47,6 @@ require (
|
|||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.0.1 // indirect
|
||||
github.com/josharian/native v1.0.0 // indirect
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
github.com/mdlayher/netlink v1.6.0 // indirect
|
||||
github.com/mdlayher/socket v0.2.3 // indirect
|
||||
|
@ -76,13 +75,13 @@ require (
|
|||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||
go.etcd.io/bbolt v1.3.6 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 // indirect
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
|
||||
golang.org/x/tools v0.1.12 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
modernc.org/libc v1.17.0 // indirect
|
||||
modernc.org/libc v1.17.1 // indirect
|
||||
modernc.org/mathutil v1.5.0 // indirect
|
||||
modernc.org/memory v1.2.0 // indirect
|
||||
modernc.org/memory v1.2.1 // indirect
|
||||
modernc.org/sqlite v1.18.1 // indirect
|
||||
)
|
||||
|
|
27
go.sum
27
go.sum
|
@ -236,7 +236,6 @@ github.com/containerd/fifo v0.0.0-20190226154929-a9fb20d87448/go.mod h1:ODA38xgv
|
|||
github.com/containerd/go-runc v0.0.0-20180907222934-5a6d9f37cfa3/go.mod h1:IV7qH3hrUgRmyYrtgEeGWJfWbgcHL9CSRruz2Vqcph0=
|
||||
github.com/containerd/ttrpc v0.0.0-20190828154514-0e0f228740de/go.mod h1:PvCDdDGpgqzQIzDW1TphrGLssLDZp2GuS+X5DkEJB8o=
|
||||
github.com/containerd/typeurl v0.0.0-20180627222232-a93fcdb778cd/go.mod h1:Cm3kwCdlkCfMSHURc+r6fwoGH6/F1hH3S4sg0rLFWPc=
|
||||
github.com/cookieo9/resources-go v0.0.0-20150225115733-d27c04069d0d h1:O+gcIbHv8EocDRI8swPGYI6XPJDbdZ66jeXqfoXifLE=
|
||||
github.com/cookieo9/resources-go v0.0.0-20150225115733-d27c04069d0d/go.mod h1:Da90oEbCMTyeoWRBoWQHAmajIlLPjji2U2w7HJGAnuY=
|
||||
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
|
@ -602,7 +601,6 @@ github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1
|
|||
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
|
||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kevinburke/ssh_config v0.0.0-20201106050909-4977a11b4351/go.mod h1:CT57kijsi8u/K/BOFA39wgDQJ9CxiF4nAY/ojJ6r6mM=
|
||||
|
@ -832,7 +830,6 @@ github.com/safing/portbase v0.14.2/go.mod h1:z9sRR/vqohAGdYSSx2B+o8tND4WVvcxPL6X
|
|||
github.com/safing/portbase v0.14.3/go.mod h1:z9sRR/vqohAGdYSSx2B+o8tND4WVvcxPL6XBBtN3bDI=
|
||||
github.com/safing/portbase v0.14.4/go.mod h1:z9sRR/vqohAGdYSSx2B+o8tND4WVvcxPL6XBBtN3bDI=
|
||||
github.com/safing/portbase v0.14.5/go.mod h1:z9sRR/vqohAGdYSSx2B+o8tND4WVvcxPL6XBBtN3bDI=
|
||||
github.com/safing/portbase v0.15.0 h1:WwJpnERbNfzqDkEHt39l1TbBhnvf/oB2ZKj6fkaMSTM=
|
||||
github.com/safing/portbase v0.15.0/go.mod h1:BinbSUlbOdsHTBSE8+WkKbR1bXNMlsbhhAW12EBxsUo=
|
||||
github.com/safing/portbase v0.15.1 h1:s4AzyMSF26/b0CPmyHvKJSG9nW+u42+eIxlIKyp+J1U=
|
||||
github.com/safing/portbase v0.15.1/go.mod h1:5bHi99fz7Hh/wOsZUOI631WF9ePSHk57c4fdlOMS91Y=
|
||||
|
@ -878,6 +875,8 @@ github.com/safing/spn v0.4.13/go.mod h1:rBeimIc1FHQOhX7lTh/LaFGRotmnwZIDWUSsPyeI
|
|||
github.com/safing/spn v0.4.14/go.mod h1:GwGVU+GSmPQQXorKVDXIgieJZ16e70aBV5CcG0nAVRg=
|
||||
github.com/safing/spn v0.4.15 h1:hiGAQgkfxm3yfakkt7mVmkUfYxtE0pgODH9LyloEr/o=
|
||||
github.com/safing/spn v0.4.15/go.mod h1:mgVGd4sUdem78irl/pSx/JqOM/Ow85pJqKKqPpj1Ikk=
|
||||
github.com/safing/spn v0.5.0 h1:gOkcz1io7/4A4rZislqlm3w+gzVqO5861tbbib0EBUM=
|
||||
github.com/safing/spn v0.5.0/go.mod h1:BGzLv966GfYZXc4EUFk04QfrfkpzDdaNObkKTRPbdpk=
|
||||
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
|
||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||
|
@ -935,6 +934,8 @@ github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DM
|
|||
github.com/spf13/viper v1.7.0/go.mod h1:8WkrPz2fc9jxqZNCJI/76HCieCp4Q8HaLFoCha5qpdg=
|
||||
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
|
||||
github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM=
|
||||
github.com/spkg/zipfs v0.7.1 h1:+2X5lvNHTybnDMQZAIHgedRXZK1WXdc+94R/P5v2XWE=
|
||||
github.com/spkg/zipfs v0.7.1/go.mod h1:48LW+/Rh1G7aAav1ew1PdlYn52T+LM+ARmSHfDNJvg8=
|
||||
github.com/stoewer/go-strcase v1.2.0/go.mod h1:IBiWB2sKIp3wVVQ3Y035++gc+knqhUQag1KpM8ahLw8=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
|
@ -1120,8 +1121,8 @@ golang.org/x/crypto v0.0.0-20220507011949-2cf3adece122/go.mod h1:IxCIyHEi3zRg3s0
|
|||
golang.org/x/crypto v0.0.0-20220513210258-46612604a0f9/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 h1:GIAS/yBem/gq2MUqgNIzUHW7cJMmx3TGZOrnyYaNQ6c=
|
||||
golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
|
||||
golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
|
||||
|
@ -1246,8 +1247,8 @@ golang.org/x/net v0.0.0-20220513224357-95641704303c/go.mod h1:CfG3xpIq0wQ8r1q4Su
|
|||
golang.org/x/net v0.0.0-20220708220712-1185a9018129/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.0.0-20220728211354-c7608f3a8462/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c h1:JVAXQ10yGGVbSyoer5VILysz6YKjdNT2bsvlayjqhes=
|
||||
golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b h1:ZmngSVLe/wycRns9MKikG9OWIEjGcGAkacif7oYQaUY=
|
||||
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
|
@ -1415,8 +1416,8 @@ golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24 h1:TyKJRhyo17yWxOMCTHKWrc5rddHORMlnZ/j57umaUd8=
|
||||
golang.org/x/sys v0.0.0-20220823224334-20c2bfdbfe24/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
|
||||
golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
|
@ -1750,15 +1751,15 @@ modernc.org/libc v1.16.1/go.mod h1:JjJE0eu4yeK7tab2n4S1w8tlWd9MxXLRzheaRnAKymU=
|
|||
modernc.org/libc v1.16.7/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU=
|
||||
modernc.org/libc v1.16.17/go.mod h1:hYIV5VZczAmGZAnG15Vdngn5HSF5cSkbvfz2B7GRuVU=
|
||||
modernc.org/libc v1.16.19/go.mod h1:p7Mg4+koNjc8jkqwcoFBJx7tXkpj00G77X7A72jXPXA=
|
||||
modernc.org/libc v1.17.0 h1:nbL2Lv0I323wLc1GmTh/AqVtI9JeBVc7Nhapdg9EONs=
|
||||
modernc.org/libc v1.17.0/go.mod h1:XsgLldpP4aWlPlsjqKRdHPqCxCjISdHfM/yeWC5GyW0=
|
||||
modernc.org/libc v1.17.1 h1:Q8/Cpi36V/QBfuQaFVeisEBs3WqoGAJprZzmf7TfEYI=
|
||||
modernc.org/libc v1.17.1/go.mod h1:FZ23b+8LjxZs7XtFMbSzL/EhPxNbfZbErxEHc7cbD9s=
|
||||
modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.4.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||
modernc.org/memory v1.1.1/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
|
||||
modernc.org/memory v1.2.0 h1:zXehBrt9n+Pjn+4RoRCZ0KqRA/0ePFqcecxZ/hXCIVw=
|
||||
modernc.org/memory v1.2.0/go.mod h1:/0wo5ibyrQiaoUoH7f9D8dnglAmILJ5/cxZlRECf+Nw=
|
||||
modernc.org/memory v1.2.1 h1:dkRh86wgmq/bJu2cAS2oqBCz/KsMZU7TUM4CibQ7eBs=
|
||||
modernc.org/memory v1.2.1/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
||||
modernc.org/sqlite v1.17.3/go.mod h1:10hPVYar9C0kfXuTWGz8s0XtB8uAGymUy51ZzStYe3k=
|
||||
modernc.org/sqlite v1.18.0/go.mod h1:B9fRWZacNxJBHoCJZQr1R54zhVn3fjfl0aszflrTSxY=
|
||||
|
|
|
@ -237,8 +237,8 @@ func (e *Entity) GetIP() (net.IP, bool) {
|
|||
|
||||
func (e *Entity) getLocation(ctx context.Context) {
|
||||
e.fetchLocationOnce.Do(func() {
|
||||
// need IP!
|
||||
if e.IP == nil {
|
||||
// Only check if we have a global IP address.
|
||||
if e.IP == nil || !e.IPScope.IsGlobal() {
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -254,6 +254,31 @@ func (e *Entity) getLocation(ctx context.Context) {
|
|||
e.Coordinates = &loc.Coordinates
|
||||
e.ASN = loc.AutonomousSystemNumber
|
||||
e.ASOrg = loc.AutonomousSystemOrganization
|
||||
|
||||
// Log result.
|
||||
if log.GetLogLevel() == log.TraceLevel {
|
||||
// Build flags
|
||||
var flags string
|
||||
if loc.IsAnycast {
|
||||
flags += " anycast"
|
||||
}
|
||||
if loc.IsSatelliteProvider {
|
||||
flags += " satellite"
|
||||
}
|
||||
if loc.IsAnonymousProxy {
|
||||
flags += " anonymous"
|
||||
}
|
||||
|
||||
// Log location
|
||||
log.Tracer(ctx).Tracef(
|
||||
"intel: located %s in %s (AS%d by %s)%s",
|
||||
e.IP,
|
||||
loc.Country.ISOCode,
|
||||
loc.AutonomousSystemNumber,
|
||||
loc.AutonomousSystemOrganization,
|
||||
flags,
|
||||
)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -318,7 +343,6 @@ func (e *Entity) getDomainLists(ctx context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
log.Tracer(ctx).Tracef("intel: loading domain list for %s", domain)
|
||||
e.loadDomainListOnce.Do(func() {
|
||||
domainsToInspect := []string{domain}
|
||||
|
||||
|
@ -347,7 +371,10 @@ func (e *Entity) getDomainLists(ctx context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
e.mergeList(d, list)
|
||||
if len(list) > 0 {
|
||||
log.Tracer(ctx).Tracef("intel: loaded domain lists for %s: %s", d, strings.Join(list, ", "))
|
||||
e.mergeList(d, list)
|
||||
}
|
||||
}
|
||||
e.domainListLoaded = true
|
||||
})
|
||||
|
@ -389,7 +416,6 @@ func (e *Entity) getASNLists(ctx context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
log.Tracer(ctx).Tracef("intel: loading ASN list for %d", asn)
|
||||
e.loadAsnListOnce.Do(func() {
|
||||
asnStr := fmt.Sprintf("%d", asn)
|
||||
list, err := filterlists.LookupASNString(asnStr)
|
||||
|
@ -399,8 +425,12 @@ func (e *Entity) getASNLists(ctx context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if len(list) > 0 {
|
||||
log.Tracer(ctx).Tracef("intel: loaded ASN lists for %s: %s", asnStr, strings.Join(list, ", "))
|
||||
e.mergeList(asnStr, list)
|
||||
}
|
||||
|
||||
e.asnListLoaded = true
|
||||
e.mergeList(asnStr, list)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -414,7 +444,6 @@ func (e *Entity) getCountryLists(ctx context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
log.Tracer(ctx).Tracef("intel: loading country list for %s", country)
|
||||
e.loadCountryListOnce.Do(func() {
|
||||
list, err := filterlists.LookupCountry(country)
|
||||
if err != nil {
|
||||
|
@ -423,8 +452,12 @@ func (e *Entity) getCountryLists(ctx context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if len(list) > 0 {
|
||||
log.Tracer(ctx).Tracef("intel: loaded country lists for %s: %s", country, strings.Join(list, ", "))
|
||||
e.mergeList(country, list)
|
||||
}
|
||||
|
||||
e.countryListLoaded = true
|
||||
e.mergeList(country, list)
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -443,7 +476,6 @@ func (e *Entity) getIPLists(ctx context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
log.Tracer(ctx).Tracef("intel: loading IP list for %s", ip)
|
||||
e.loadIPListOnce.Do(func() {
|
||||
list, err := filterlists.LookupIP(ip)
|
||||
if err != nil {
|
||||
|
@ -452,8 +484,12 @@ func (e *Entity) getIPLists(ctx context.Context) {
|
|||
return
|
||||
}
|
||||
|
||||
if len(list) > 0 {
|
||||
log.Tracer(ctx).Tracef("intel: loaded IP lists for %s: %s", ip.String(), strings.Join(list, ", "))
|
||||
e.mergeList(ip.String(), list)
|
||||
}
|
||||
|
||||
e.ipListLoaded = true
|
||||
e.mergeList(ip.String(), list)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -196,8 +196,12 @@ func updateListIndex() error {
|
|||
listIndexUpdate.Version(),
|
||||
)
|
||||
default:
|
||||
log.Debug("filterlists: index is up to date")
|
||||
// List is in cache and current, there is nothing to do.
|
||||
log.Debug("filterlists: index is up to date")
|
||||
|
||||
// Update the unbreak filter list IDs on initial load.
|
||||
updateUnbreakFilterListIDs()
|
||||
|
||||
return nil
|
||||
}
|
||||
case listIndexUpdate.UpgradeAvailable():
|
||||
|
@ -225,6 +229,9 @@ func updateListIndex() error {
|
|||
}
|
||||
log.Debugf("intel/filterlists: updated list index in cache to %s", index.Version)
|
||||
|
||||
// Update the unbreak filter list IDs after an update.
|
||||
updateUnbreakFilterListIDs()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
|
@ -252,3 +259,30 @@ func ResolveListIDs(ids []string) ([]string, error) {
|
|||
|
||||
return resolved, nil
|
||||
}
|
||||
|
||||
var (
|
||||
unbreakCategoryIDs = []string{"UNBREAK"}
|
||||
|
||||
unbreakIDs []string
|
||||
unbreakIDsLock sync.Mutex
|
||||
)
|
||||
|
||||
// GetUnbreakFilterListIDs returns the resolved list of all unbreak filter lists.
|
||||
func GetUnbreakFilterListIDs() []string {
|
||||
unbreakIDsLock.Lock()
|
||||
defer unbreakIDsLock.Unlock()
|
||||
|
||||
return unbreakIDs
|
||||
}
|
||||
|
||||
func updateUnbreakFilterListIDs() {
|
||||
unbreakIDsLock.Lock()
|
||||
defer unbreakIDsLock.Unlock()
|
||||
|
||||
resolvedIDs, err := ResolveListIDs(unbreakCategoryIDs)
|
||||
if err != nil {
|
||||
log.Warningf("filter: failed to resolve unbreak filter list IDs: %s", err)
|
||||
} else {
|
||||
unbreakIDs = resolvedIDs
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,9 @@ type Location struct {
|
|||
Coordinates Coordinates `maxminddb:"location"`
|
||||
AutonomousSystemNumber uint `maxminddb:"autonomous_system_number"`
|
||||
AutonomousSystemOrganization string `maxminddb:"autonomous_system_organization"`
|
||||
IsAnycast bool `maxminddb:"is_anycast"`
|
||||
IsSatelliteProvider bool `maxminddb:"is_satellite_provider"`
|
||||
IsAnonymousProxy bool `maxminddb:"is_anonymous_proxy"`
|
||||
}
|
||||
|
||||
// Coordinates holds geographic coordinates and their estimated accuracy.
|
||||
|
|
|
@ -468,7 +468,7 @@ func checkOnlineStatus(ctx context.Context) {
|
|||
}
|
||||
|
||||
request := (&http.Request{
|
||||
Method: "GET",
|
||||
Method: http.MethodGet,
|
||||
URL: parsedPortalTestURL,
|
||||
Close: true,
|
||||
}).WithContext(ctx)
|
||||
|
@ -495,7 +495,7 @@ func checkOnlineStatus(ctx context.Context) {
|
|||
}
|
||||
|
||||
// direct response
|
||||
if response.StatusCode == 200 {
|
||||
if response.StatusCode == http.StatusOK {
|
||||
updateOnlineStatus(StatusPortal, &url.URL{
|
||||
Scheme: "http",
|
||||
Host: SpecialCaptivePortalDomain,
|
||||
|
|
|
@ -10,10 +10,10 @@ import (
|
|||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/jackc/puddle/v2"
|
||||
"zombiezen.com/go/sqlite"
|
||||
"zombiezen.com/go/sqlite/sqlitex"
|
||||
|
||||
"github.com/jackc/puddle/v2"
|
||||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portmaster/netquery/orm"
|
||||
"github.com/safing/portmaster/network"
|
||||
|
@ -108,7 +108,6 @@ type (
|
|||
// (see Execute). To perform database writes use either Save() or ExecuteWrite().
|
||||
// Note that write connections are serialized by the Database object before being
|
||||
// handed over to SQLite.
|
||||
//
|
||||
func New(path string) (*Database, error) {
|
||||
constructor := func(ctx context.Context) (*sqlite.Conn, error) {
|
||||
c, err := sqlite.OpenConn(
|
||||
|
@ -331,7 +330,7 @@ func (db *Database) Save(ctx context.Context, conn Conn) error {
|
|||
for key := range connMap {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Sort(sort.StringSlice(keys))
|
||||
sort.Strings(keys)
|
||||
|
||||
for _, key := range keys {
|
||||
value := connMap[key]
|
||||
|
|
|
@ -63,7 +63,6 @@ type (
|
|||
// Decoding hooks configured in cfg are executed before trying to decode basic types and may
|
||||
// be specified to provide support for special types.
|
||||
// See DatetimeDecoder() for an example of a DecodeHook that handles graceful time.Time conversion.
|
||||
//
|
||||
func DecodeStmt(ctx context.Context, schema *TableSchema, stmt Stmt, result interface{}, cfg DecodeConfig) error {
|
||||
// make sure we got something to decode into ...
|
||||
if result == nil {
|
||||
|
|
|
@ -94,13 +94,12 @@ func WithDecodeConfig(cfg DecodeConfig) QueryOption {
|
|||
//
|
||||
// Example:
|
||||
//
|
||||
// var result []struct{
|
||||
// Count int `sqlite:"rowCount"`
|
||||
// }
|
||||
//
|
||||
// err := RunQuery(ctx, conn, "SELECT COUNT(*) AS rowCount FROM table", WithResult(&result))
|
||||
// fmt.Println(result[0].Count)
|
||||
// var result []struct{
|
||||
// Count int `sqlite:"rowCount"`
|
||||
// }
|
||||
//
|
||||
// err := RunQuery(ctx, conn, "SELECT COUNT(*) AS rowCount FROM table", WithResult(&result))
|
||||
// fmt.Println(result[0].Count)
|
||||
func RunQuery(ctx context.Context, conn *sqlite.Conn, sql string, modifiers ...QueryOption) error {
|
||||
args := queryOpts{
|
||||
DecodeConfig: DefaultDecodeConfig,
|
||||
|
|
|
@ -17,6 +17,7 @@ import (
|
|||
// Collection of Query and Matcher types.
|
||||
// NOTE: whenever adding support for new operators make sure
|
||||
// to update UnmarshalJSON as well.
|
||||
//
|
||||
//nolint:golint
|
||||
type (
|
||||
Query map[string][]Matcher
|
||||
|
|
|
@ -125,10 +125,12 @@ func (pkt *Base) createConnectionID() {
|
|||
// MatchesAddress checks if a the packet matches a given endpoint (remote or local) in protocol, network and port.
|
||||
//
|
||||
// Comparison matrix:
|
||||
// IN OUT
|
||||
//
|
||||
// ====== IN OUT
|
||||
//
|
||||
// Local Dst Src
|
||||
// Remote Src Dst
|
||||
//.
|
||||
// .
|
||||
func (pkt *Base) MatchesAddress(remote bool, protocol IPProtocol, network *net.IPNet, port uint16) bool {
|
||||
if pkt.info.Protocol != protocol {
|
||||
return false
|
||||
|
@ -154,10 +156,12 @@ func (pkt *Base) MatchesAddress(remote bool, protocol IPProtocol, network *net.I
|
|||
// MatchesIP checks if a the packet matches a given endpoint (remote or local) IP.
|
||||
//
|
||||
// Comparison matrix:
|
||||
// IN OUT
|
||||
//
|
||||
// ====== IN OUT
|
||||
//
|
||||
// Local Dst Src
|
||||
// Remote Src Dst
|
||||
//.
|
||||
// .
|
||||
func (pkt *Base) MatchesIP(endpoint bool, network *net.IPNet) bool {
|
||||
if pkt.info.Inbound != endpoint {
|
||||
if network.Contains(pkt.info.Src) {
|
||||
|
|
|
@ -1,7 +1,3 @@
|
|||
/*
|
||||
|
||||
Package process fetches process and socket information from the operating system.
|
||||
It can find the process owning a network connection.
|
||||
|
||||
*/
|
||||
// Package process fetches process and socket information from the operating system.
|
||||
// It can find the process owning a network connection.
|
||||
package process
|
||||
|
|
|
@ -1,22 +1,22 @@
|
|||
/*
|
||||
Package resolver is responsible for querying DNS.
|
||||
|
||||
DNS Servers
|
||||
# DNS Servers
|
||||
|
||||
Internal lists of resolvers to use are built on start and rebuilt on every config or network change.
|
||||
Configured DNS servers are prioritized over servers assigned by dhcp. Domain and search options (here referred to as "search scopes") are being considered.
|
||||
|
||||
Security
|
||||
# Security
|
||||
|
||||
Usage of DNS Servers can be regulated using the configuration:
|
||||
|
||||
DoNotUseAssignedDNS // Do not use DNS servers assigned by DHCP
|
||||
DoNotUseMDNS // Do not use mDNS
|
||||
DoNotForwardSpecialDomains // Do not forward special domains to local resolvers, except if they have a search scope for it
|
||||
DoNotUseAssignedDNS // Do not use DNS servers assigned by DHCP
|
||||
DoNotUseMDNS // Do not use mDNS
|
||||
DoNotForwardSpecialDomains // Do not forward special domains to local resolvers, except if they have a search scope for it
|
||||
|
||||
Note: The DHCP options "domain" and "search" are ignored for servers assigned by DHCP that do not reside within local address space.
|
||||
|
||||
Resolving DNS
|
||||
# Resolving DNS
|
||||
|
||||
Various different queries require the resolver to behave in different manner:
|
||||
|
||||
|
@ -24,6 +24,5 @@ Queries for "localhost." are immediately responded with 127.0.0.1 and ::1, for A
|
|||
Reverse lookups on local address ranges (10/8, 172.16/12, 192.168/16, fe80::/7) will be tried against every local resolver and finally mDNS until a successful, non-NXDomain answer is received.
|
||||
Special domains ("example.", "example.com.", "example.net.", "example.org.", "invalid.", "test.", "onion.") are resolved using search scopes and local resolvers.
|
||||
All other domains are resolved using search scopes and all available resolvers.
|
||||
|
||||
*/
|
||||
package resolver
|
||||
|
|
|
@ -90,7 +90,9 @@ func (hr *HTTPSResolver) Query(ctx context.Context, q *Query) (*RRCache, error)
|
|||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
defer func() {
|
||||
_ = resp.Body.Close()
|
||||
}()
|
||||
|
||||
// Try to read the result
|
||||
body, err := ioutil.ReadAll(resp.Body)
|
||||
|
|
|
@ -30,7 +30,7 @@ const (
|
|||
ServerSourceEnv = "env"
|
||||
)
|
||||
|
||||
// DNS Resolver alias
|
||||
// DNS resolver scheme aliases.
|
||||
const (
|
||||
HTTPSProtocol = "https"
|
||||
TLSProtocol = "tls"
|
||||
|
@ -117,14 +117,14 @@ func (info *ResolverInfo) ID() string {
|
|||
case ServerTypeEnv:
|
||||
info.id = ServerTypeEnv
|
||||
case ServerTypeDoH:
|
||||
info.id = fmt.Sprintf(
|
||||
info.id = fmt.Sprintf( //nolint:nosprintfhostport // Not used as URL.
|
||||
"https://%s:%d#%s",
|
||||
info.Domain,
|
||||
info.Port,
|
||||
info.Source,
|
||||
)
|
||||
case ServerTypeDoT:
|
||||
info.id = fmt.Sprintf(
|
||||
info.id = fmt.Sprintf( //nolint:nosprintfhostport // Not used as URL.
|
||||
"dot://%s:%d#%s",
|
||||
info.Domain,
|
||||
info.Port,
|
||||
|
|
|
@ -10,9 +10,9 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
"golang.org/x/net/publicsuffix"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portbase/utils"
|
||||
"github.com/safing/portmaster/netenv"
|
||||
|
|
|
@ -16,7 +16,8 @@ import (
|
|||
// RRCache is a single-use structure to hold a DNS response.
|
||||
// Persistence is handled through NameRecords because of a limitation of the
|
||||
// underlying dns library.
|
||||
//nolint:maligned // TODO
|
||||
//
|
||||
//nolint:maligned
|
||||
type RRCache struct {
|
||||
// Respnse Header
|
||||
Domain string
|
||||
|
|
|
@ -37,14 +37,13 @@ type ThreatPayload struct {
|
|||
//
|
||||
// Example:
|
||||
//
|
||||
// threat := NewThreat("portscan", "Someone is scanning you").
|
||||
// SetData(portscanResult).
|
||||
// SetMitigationLevel(SecurityLevelExtreme).
|
||||
// Publish()
|
||||
//
|
||||
// // Once you're done, delete the threat
|
||||
// threat.Delete().Publish()
|
||||
// threat := NewThreat("portscan", "Someone is scanning you").
|
||||
// SetData(portscanResult).
|
||||
// SetMitigationLevel(SecurityLevelExtreme).
|
||||
// Publish()
|
||||
//
|
||||
// Once you're done, delete the threat
|
||||
// threat.Delete().Publish()
|
||||
func NewThreat(id, title, msg string) *Threat {
|
||||
t := &Threat{
|
||||
Notification: ¬ifications.Notification{
|
||||
|
|
16
ui/api.go
16
ui/api.go
|
@ -1,8 +1,6 @@
|
|||
package ui
|
||||
|
||||
import (
|
||||
resources "github.com/cookieo9/resources-go"
|
||||
|
||||
"github.com/safing/portbase/api"
|
||||
"github.com/safing/portbase/log"
|
||||
)
|
||||
|
@ -22,16 +20,18 @@ func reloadUI(_ *api.Request) (msg string, err error) {
|
|||
appsLock.Lock()
|
||||
defer appsLock.Unlock()
|
||||
|
||||
// close all bundles.
|
||||
for id, bundle := range apps {
|
||||
err := bundle.Close()
|
||||
// Close all archives.
|
||||
for id, archiveFS := range apps {
|
||||
err := archiveFS.Close()
|
||||
if err != nil {
|
||||
log.Warningf("ui: failed to close bundle %s: %s", id, err)
|
||||
log.Warningf("ui: failed to close archive %s: %s", id, err)
|
||||
}
|
||||
}
|
||||
|
||||
// Reset index.
|
||||
apps = make(map[string]*resources.BundleSequence)
|
||||
for key := range apps {
|
||||
delete(apps, key)
|
||||
}
|
||||
|
||||
return "all ui bundles successfully reloaded", nil
|
||||
return "all ui archives successfully reloaded", nil
|
||||
}
|
||||
|
|
52
ui/serve.go
52
ui/serve.go
|
@ -6,11 +6,12 @@ import (
|
|||
"io"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
resources "github.com/cookieo9/resources-go"
|
||||
"github.com/spkg/zipfs"
|
||||
|
||||
"github.com/safing/portbase/api"
|
||||
"github.com/safing/portbase/log"
|
||||
|
@ -20,7 +21,7 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
apps = make(map[string]*resources.BundleSequence)
|
||||
apps = make(map[string]*zipfs.FileSystem)
|
||||
appsLock sync.RWMutex
|
||||
)
|
||||
|
||||
|
@ -28,7 +29,7 @@ func registerRoutes() error {
|
|||
// Server assets.
|
||||
api.RegisterHandler(
|
||||
"/assets/{resPath:[a-zA-Z0-9/\\._-]+}",
|
||||
&bundleServer{defaultModuleName: "assets"},
|
||||
&archiveServer{defaultModuleName: "assets"},
|
||||
)
|
||||
|
||||
// Add slash to plain module namespaces.
|
||||
|
@ -38,7 +39,7 @@ func registerRoutes() error {
|
|||
)
|
||||
|
||||
// Serve modules.
|
||||
srv := &bundleServer{}
|
||||
srv := &archiveServer{}
|
||||
api.RegisterHandler("/ui/modules/{moduleName:[a-z]+}/", srv)
|
||||
api.RegisterHandler("/ui/modules/{moduleName:[a-z]+}/{resPath:[a-zA-Z0-9/\\._-]+}", srv)
|
||||
|
||||
|
@ -51,17 +52,17 @@ func registerRoutes() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
type bundleServer struct {
|
||||
type archiveServer struct {
|
||||
defaultModuleName string
|
||||
}
|
||||
|
||||
func (bs *bundleServer) BelongsTo() *modules.Module { return module }
|
||||
func (bs *archiveServer) BelongsTo() *modules.Module { return module }
|
||||
|
||||
func (bs *bundleServer) ReadPermission(*http.Request) api.Permission { return api.PermitAnyone }
|
||||
func (bs *archiveServer) ReadPermission(*http.Request) api.Permission { return api.PermitAnyone }
|
||||
|
||||
func (bs *bundleServer) WritePermission(*http.Request) api.Permission { return api.NotSupported }
|
||||
func (bs *archiveServer) WritePermission(*http.Request) api.Permission { return api.NotSupported }
|
||||
|
||||
func (bs *bundleServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
func (bs *archiveServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// Get request context.
|
||||
ar := api.GetAPIRequest(r)
|
||||
if ar == nil {
|
||||
|
@ -85,10 +86,10 @@ func (bs *bundleServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
appsLock.RLock()
|
||||
bundle, ok := apps[moduleName]
|
||||
archiveFS, ok := apps[moduleName]
|
||||
appsLock.RUnlock()
|
||||
if ok {
|
||||
ServeFileFromBundle(w, r, moduleName, bundle, resPath)
|
||||
ServeFileFromArchive(w, r, moduleName, archiveFS, resPath)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -105,39 +106,38 @@ func (bs *bundleServer) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
|
||||
// open bundle
|
||||
newBundle, err := resources.OpenZip(zipFile.Path())
|
||||
// Open archive from disk.
|
||||
archiveFS, err = zipfs.New(zipFile.Path())
|
||||
if err != nil {
|
||||
log.Tracef("ui: error prepping module %s: %s", moduleName, err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
bundle = &resources.BundleSequence{newBundle}
|
||||
appsLock.Lock()
|
||||
apps[moduleName] = bundle
|
||||
apps[moduleName] = archiveFS
|
||||
appsLock.Unlock()
|
||||
|
||||
ServeFileFromBundle(w, r, moduleName, bundle, resPath)
|
||||
ServeFileFromArchive(w, r, moduleName, archiveFS, resPath)
|
||||
}
|
||||
|
||||
// ServeFileFromBundle serves a file from the given bundle.
|
||||
func ServeFileFromBundle(w http.ResponseWriter, r *http.Request, bundleName string, bundle *resources.BundleSequence, path string) {
|
||||
readCloser, err := bundle.Open(path)
|
||||
// ServeFileFromArchive serves a file from the given archive.
|
||||
func ServeFileFromArchive(w http.ResponseWriter, r *http.Request, archiveName string, archiveFS *zipfs.FileSystem, path string) {
|
||||
readCloser, err := archiveFS.Open(path)
|
||||
if err != nil {
|
||||
if errors.Is(err, resources.ErrNotFound) {
|
||||
if os.IsNotExist(err) {
|
||||
// Check if there is a base index.html file we can serve instead.
|
||||
var indexErr error
|
||||
path = "index.html"
|
||||
readCloser, indexErr = bundle.Open(path)
|
||||
readCloser, indexErr = archiveFS.Open(path)
|
||||
if indexErr != nil {
|
||||
// If we cannot get an index, continue with handling the original error.
|
||||
log.Tracef("ui: requested resource \"%s\" not found in bundle %s: %s", path, bundleName, err)
|
||||
log.Tracef("ui: requested resource \"%s\" not found in archive %s: %s", path, archiveName, err)
|
||||
http.Error(w, err.Error(), http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
log.Tracef("ui: error opening module %s: %s", bundleName, err)
|
||||
log.Tracef("ui: error opening module %s: %s", archiveName, err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
@ -152,12 +152,8 @@ func ServeFileFromBundle(w http.ResponseWriter, r *http.Request, bundleName stri
|
|||
}
|
||||
}
|
||||
|
||||
// TODO: Set content security policy
|
||||
// For some reason, this breaks the ui client
|
||||
// w.Header().Set("Content-Security-Policy", "default-src 'self'")
|
||||
|
||||
w.WriteHeader(http.StatusOK)
|
||||
if r.Method != "HEAD" {
|
||||
if r.Method != http.MethodHead {
|
||||
_, err = io.Copy(w, readCloser)
|
||||
if err != nil {
|
||||
log.Errorf("ui: failed to serve file: %s", err)
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"flag"
|
||||
"fmt"
|
||||
"runtime"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/safing/portbase/database"
|
||||
|
@ -209,6 +210,8 @@ func DisableUpdateSchedule() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
var updateFailedCnt = new(atomic.Int32)
|
||||
|
||||
func checkForUpdates(ctx context.Context) (err error) {
|
||||
if !forceUpdate.SetToIf(true, false) && !enableUpdates() {
|
||||
log.Warningf("updates: automatic updates are disabled")
|
||||
|
@ -216,7 +219,9 @@ func checkForUpdates(ctx context.Context) (err error) {
|
|||
}
|
||||
|
||||
defer func() {
|
||||
// Resolve any error and and send succes notification.
|
||||
if err == nil {
|
||||
updateFailedCnt.Store(0)
|
||||
log.Infof("updates: successfully checked for updates")
|
||||
module.Resolve(updateFailed)
|
||||
notifications.Notify(¬ifications.Notification{
|
||||
|
@ -232,7 +237,14 @@ func checkForUpdates(ctx context.Context) (err error) {
|
|||
},
|
||||
},
|
||||
})
|
||||
} else {
|
||||
return
|
||||
}
|
||||
|
||||
// Log error in any case.
|
||||
log.Errorf("updates: check failed: %s", err)
|
||||
|
||||
// Do not alert user if update failed for only a few times.
|
||||
if updateFailedCnt.Add(1) > 3 {
|
||||
notifications.NotifyWarn(
|
||||
updateFailed,
|
||||
"Update Check Failed",
|
||||
|
|
|
@ -35,8 +35,7 @@ var (
|
|||
pmCtrlUpdate *updater.File
|
||||
pmCoreUpdate *updater.File
|
||||
|
||||
spnHubUpdate *updater.File
|
||||
hubUpgradeStarted bool
|
||||
spnHubUpdate *updater.File
|
||||
|
||||
rawVersionRegex = regexp.MustCompile(`^[0-9]+\.[0-9]+\.[0-9]+b?\*?$`)
|
||||
)
|
||||
|
|
Loading…
Add table
Reference in a new issue