Integrate SPN route manipulation settings
This commit is contained in:
@@ -25,9 +25,6 @@ import (
|
||||
"github.com/safing/portmaster/network"
|
||||
"github.com/safing/portmaster/network/netutils"
|
||||
"github.com/safing/portmaster/network/packet"
|
||||
"github.com/safing/spn/captain"
|
||||
"github.com/safing/spn/crew"
|
||||
"github.com/safing/spn/sluice"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -335,9 +332,6 @@ func initialHandler(conn *network.Connection, pkt packet.Packet) {
|
||||
conn.Accept("connection by Portmaster", noReasonOptionKey)
|
||||
conn.Internal = true
|
||||
|
||||
// Set tunnel options.
|
||||
setCustomTunnelOptionsForPortmaster(conn)
|
||||
|
||||
// Redirect outbound DNS packests,
|
||||
case pkt.IsOutbound() &&
|
||||
pkt.Info().DstPort == 53 &&
|
||||
@@ -368,41 +362,6 @@ func initialHandler(conn *network.Connection, pkt packet.Packet) {
|
||||
conn.Accept("privacy filter disabled", noReasonOptionKey)
|
||||
}
|
||||
|
||||
// Tunnel, if enabled.
|
||||
if pkt.IsOutbound() && conn.Entity.IPScope.IsGlobal() &&
|
||||
tunnelEnabled() && conn.Verdict == network.VerdictAccept &&
|
||||
conn.Process().Profile() != nil &&
|
||||
conn.Process().Profile().UseSPN() {
|
||||
|
||||
switch {
|
||||
case captain.ClientBootstrapping() &&
|
||||
conn.Process().Pid == ownPID:
|
||||
// Exclude the Portmaster during SPN bootstrapping.
|
||||
|
||||
case captain.IsExcepted(conn.Entity.IP) &&
|
||||
conn.Process().Pid == ownPID:
|
||||
// Exclude requests of the SPN itself.
|
||||
|
||||
case captain.ClientReady():
|
||||
// Queue request in sluice.
|
||||
err := sluice.AwaitRequest(conn, crew.HandleSluiceRequest)
|
||||
if err != nil {
|
||||
log.Tracer(pkt.Ctx()).Warningf("failed to rqeuest tunneling: %s", err)
|
||||
conn.Failed("failed to request tunneling", "")
|
||||
} else {
|
||||
log.Tracer(pkt.Ctx()).Trace("filter: tunneling requested")
|
||||
conn.Verdict = network.VerdictRerouteToTunnel
|
||||
conn.Tunneled = true
|
||||
}
|
||||
|
||||
default:
|
||||
// Block connection as SPN is not ready yet.
|
||||
log.Tracer(pkt.Ctx()).Trace("SPN not ready for tunneling")
|
||||
conn.Failed("SPN not ready for tunneling", "")
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Enable inspection framework again.
|
||||
conn.Inspecting = false
|
||||
|
||||
@@ -419,6 +378,9 @@ func initialHandler(conn *network.Connection, pkt packet.Packet) {
|
||||
conn.Encrypted = true
|
||||
}
|
||||
|
||||
// Check if connection should be tunneled.
|
||||
checkTunneling(pkt.Ctx(), conn, pkt)
|
||||
|
||||
switch {
|
||||
case conn.Inspecting:
|
||||
log.Tracer(pkt.Ctx()).Trace("filter: start inspecting")
|
||||
|
||||
@@ -140,10 +140,6 @@ func checkPortmasterConnection(ctx context.Context, conn *network.Connection, _
|
||||
log.Tracer(ctx).Infof("filter: granting own connection %s", conn)
|
||||
conn.Accept("connection by Portmaster", noReasonOptionKey)
|
||||
conn.Internal = true
|
||||
|
||||
// Set tunnel options.
|
||||
setCustomTunnelOptionsForPortmaster(conn)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
@@ -1,23 +1,114 @@
|
||||
package firewall
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portmaster/network/packet"
|
||||
"github.com/safing/portmaster/profile"
|
||||
"github.com/safing/portmaster/profile/endpoints"
|
||||
|
||||
"github.com/safing/portmaster/network"
|
||||
"github.com/safing/portmaster/resolver"
|
||||
"github.com/safing/spn/captain"
|
||||
"github.com/safing/spn/crew"
|
||||
"github.com/safing/spn/navigator"
|
||||
"github.com/safing/spn/sluice"
|
||||
)
|
||||
|
||||
func setCustomTunnelOptionsForPortmaster(conn *network.Connection) {
|
||||
func checkTunneling(ctx context.Context, conn *network.Connection, pkt packet.Packet) {
|
||||
// Check if the connection should be tunneled at all.
|
||||
switch {
|
||||
case !tunnelEnabled():
|
||||
// Ignore when tunneling is not enabled.
|
||||
// Tunneling is disabled.
|
||||
return
|
||||
case !conn.Entity.IPScope.IsGlobal():
|
||||
// Ignore if destination is not in global address space.
|
||||
// Can't tunnel Local/LAN connections.
|
||||
return
|
||||
case resolver.IsResolverAddress(conn.Entity.IP, conn.Entity.Port):
|
||||
// Set custom tunnel options for DNS servers.
|
||||
conn.TunnelOpts = &navigator.Options{
|
||||
RoutingProfile: navigator.RoutingProfileHomeName,
|
||||
case conn.Inbound:
|
||||
// Can't tunnel incoming connections.
|
||||
return
|
||||
case conn.Verdict != network.VerdictAccept:
|
||||
// Connection will be blocked.
|
||||
return
|
||||
case conn.Process().Pid == ownPID:
|
||||
// Bypass tunneling for certain own connections.
|
||||
switch {
|
||||
case captain.ClientBootstrapping():
|
||||
return
|
||||
case captain.IsExcepted(conn.Entity.IP):
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// Get profile.
|
||||
layeredProfile := conn.Process().Profile()
|
||||
if layeredProfile == nil {
|
||||
conn.Failed("no profile set", "")
|
||||
return
|
||||
}
|
||||
|
||||
// Update profile.
|
||||
if layeredProfile.NeedsUpdate() {
|
||||
// Update revision counter in connection.
|
||||
conn.ProfileRevisionCounter = layeredProfile.Update()
|
||||
conn.SaveWhenFinished()
|
||||
} else {
|
||||
// Check if the revision counter of the connection needs updating.
|
||||
revCnt := layeredProfile.RevisionCnt()
|
||||
if conn.ProfileRevisionCounter != revCnt {
|
||||
conn.ProfileRevisionCounter = revCnt
|
||||
conn.SaveWhenFinished()
|
||||
}
|
||||
}
|
||||
|
||||
// Check if tunneling is enabeld for app at all.
|
||||
if !layeredProfile.UseSPN() {
|
||||
return
|
||||
}
|
||||
|
||||
// Check if tunneling is enabled for entity.
|
||||
conn.Entity.FetchData(ctx)
|
||||
result, _ := layeredProfile.MatchSPNUsagePolicy(ctx, conn.Entity)
|
||||
switch result {
|
||||
case endpoints.MatchError:
|
||||
conn.Failed("failed to check SPN rules", profile.CfgOptionSPNUsagePolicyKey)
|
||||
return
|
||||
case endpoints.Denied:
|
||||
return
|
||||
}
|
||||
|
||||
// Tunnel all the things!
|
||||
|
||||
// Check if ready.
|
||||
if !captain.ClientReady() {
|
||||
// Block connection as SPN is not ready yet.
|
||||
log.Tracer(pkt.Ctx()).Trace("SPN not ready for tunneling")
|
||||
conn.Failed("SPN not ready for tunneling", "")
|
||||
return
|
||||
}
|
||||
|
||||
// Set options.
|
||||
conn.TunnelOpts = &navigator.Options{
|
||||
HubPolicies: layeredProfile.StackedExitHubPolicies(),
|
||||
CheckHubExitPolicyWith: conn.Entity,
|
||||
RequireTrustedDestinationHubs: conn.Encrypted,
|
||||
RoutingProfile: layeredProfile.SPNRoutingAlgorithm(),
|
||||
}
|
||||
|
||||
// Special handling for the internal DNS resolver.
|
||||
if conn.Process().Pid == ownPID && resolver.IsResolverAddress(conn.Entity.IP, conn.Entity.Port) {
|
||||
conn.TunnelOpts.RoutingProfile = navigator.RoutingProfileHomeID
|
||||
}
|
||||
|
||||
// Queue request in sluice.
|
||||
err := sluice.AwaitRequest(conn, crew.HandleSluiceRequest)
|
||||
if err != nil {
|
||||
log.Tracer(pkt.Ctx()).Warningf("failed to rqeuest tunneling: %s", err)
|
||||
conn.Failed("failed to request tunneling", "")
|
||||
} else {
|
||||
log.Tracer(pkt.Ctx()).Trace("filter: tunneling requested")
|
||||
conn.Verdict = network.VerdictRerouteToTunnel
|
||||
conn.Tunneled = true
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user