diff --git a/firewall/master.go b/firewall/master.go index 4e2aa9db..349f7577 100644 --- a/firewall/master.go +++ b/firewall/master.go @@ -141,15 +141,34 @@ func runDeciders(ctx context.Context, selectedDeciders []deciderFn, conn *networ // checkPortmasterConnection allows all connection that originate from // portmaster itself. func checkPortmasterConnection(ctx context.Context, conn *network.Connection, _ *profile.LayeredProfile, _ packet.Packet) bool { - // Grant own outgoing connections. - if conn.Process().Pid == ownPID && !conn.Inbound { - log.Tracer(ctx).Infof("filter: granting own connection %s", conn) - conn.Accept("connection by Portmaster", noReasonOptionKey) - conn.Internal = true - return true + // Grant own outgoing or local connections. + + // Blocking our own connections can lead to a very literal deadlock. + // This can currently happen, as fast-tracked connections are also + // reset in the OS integration and might show up in the connection + // handling if a packet in the other direction hits the firewall first. + + // Ignore other processes. + if conn.Process().Pid != ownPID { + return false } - return false + // Ignore inbound connection if non-local. + if conn.Inbound { + myIP, err := netenv.IsMyIP(conn.Entity.IP) + if err != nil { + log.Tracer(ctx).Debugf("filter: failed to check if %s is own IP for granting own connection: %s", conn.Entity.IP, err) + return false + } + if !myIP { + return false + } + } + + log.Tracer(ctx).Infof("filter: granting own connection %s", conn) + conn.Accept("connection by Portmaster", noReasonOptionKey) + conn.Internal = true + return true } // checkSelfCommunication checks if the process is communicating with itself.