Continue with the new profile integration
This commit is contained in:
144
network/link.go
144
network/link.go
@@ -7,6 +7,8 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/safing/portmaster/intel"
|
||||
|
||||
"github.com/safing/portbase/database/record"
|
||||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portmaster/network/packet"
|
||||
@@ -16,21 +18,22 @@ import (
|
||||
type FirewallHandler func(pkt packet.Packet, link *Link)
|
||||
|
||||
// Link describes a distinct physical connection (e.g. TCP connection) - like an instance - of a Connection.
|
||||
//nolint:maligned // TODO: fix alignment
|
||||
type Link struct {
|
||||
type Link struct { //nolint:maligned // TODO: fix alignment
|
||||
record.Base
|
||||
sync.Mutex
|
||||
lock sync.Mutex
|
||||
|
||||
ID string
|
||||
ID string
|
||||
Entity *intel.Entity
|
||||
Direction bool
|
||||
|
||||
Verdict Verdict
|
||||
Reason string
|
||||
ReasonID string // format source[:id[:id]]
|
||||
Tunneled bool
|
||||
VerdictPermanent bool
|
||||
Inspect bool
|
||||
Started int64
|
||||
Ended int64
|
||||
RemoteAddress string
|
||||
|
||||
pktQueue chan packet.Packet
|
||||
firewallHandler FirewallHandler
|
||||
@@ -41,70 +44,82 @@ type Link struct {
|
||||
saveWhenFinished bool
|
||||
}
|
||||
|
||||
// Lock locks the link and the link's Entity.
|
||||
func (link *Link) Lock() {
|
||||
link.lock.Lock()
|
||||
link.Entity.Lock()
|
||||
}
|
||||
|
||||
// Lock unlocks the link and the link's Entity.
|
||||
func (link *Link) Unlock() {
|
||||
link.Entity.Unlock()
|
||||
link.lock.Unlock()
|
||||
}
|
||||
|
||||
// Communication returns the Communication the Link is part of
|
||||
func (link *Link) Communication() *Communication {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
return link.comm
|
||||
}
|
||||
|
||||
// GetVerdict returns the current verdict.
|
||||
func (link *Link) GetVerdict() Verdict {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
return link.Verdict
|
||||
}
|
||||
|
||||
// FirewallHandlerIsSet returns whether a firewall handler is set or not
|
||||
func (link *Link) FirewallHandlerIsSet() bool {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
return link.firewallHandler != nil
|
||||
}
|
||||
|
||||
// SetFirewallHandler sets the firewall handler for this link
|
||||
func (link *Link) SetFirewallHandler(handler FirewallHandler) {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
if link.firewallHandler == nil {
|
||||
link.firewallHandler = handler
|
||||
link.pktQueue = make(chan packet.Packet, 1000)
|
||||
|
||||
// start handling
|
||||
module.StartWorker("", func(ctx context.Context) error {
|
||||
module.StartWorker("packet handler", func(ctx context.Context) error {
|
||||
link.packetHandler()
|
||||
return nil
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
link.firewallHandler = handler
|
||||
}
|
||||
|
||||
// StopFirewallHandler unsets the firewall handler
|
||||
func (link *Link) StopFirewallHandler() {
|
||||
link.Lock()
|
||||
link.lock.Lock()
|
||||
link.firewallHandler = nil
|
||||
link.Unlock()
|
||||
link.lock.Unlock()
|
||||
link.pktQueue <- nil
|
||||
}
|
||||
|
||||
// HandlePacket queues packet of Link for handling
|
||||
func (link *Link) HandlePacket(pkt packet.Packet) {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
// get handler
|
||||
link.lock.Lock()
|
||||
handler := link.firewallHandler
|
||||
link.lock.Unlock()
|
||||
|
||||
if link.firewallHandler != nil {
|
||||
// send to queue
|
||||
if handler != nil {
|
||||
link.pktQueue <- pkt
|
||||
return
|
||||
}
|
||||
|
||||
// no handler!
|
||||
log.Warningf("network: link %s does not have a firewallHandler, dropping packet", link)
|
||||
|
||||
err := pkt.Drop()
|
||||
if err != nil {
|
||||
log.Warningf("network: failed to drop packet %s: %s", pkt, err)
|
||||
@@ -119,7 +134,7 @@ func (link *Link) Accept(reason string) {
|
||||
|
||||
// Deny blocks or drops the link depending on the connection direction and adds the given reason.
|
||||
func (link *Link) Deny(reason string) {
|
||||
if link.comm != nil && link.comm.Direction {
|
||||
if link.Direction {
|
||||
link.Drop(reason)
|
||||
} else {
|
||||
link.Block(reason)
|
||||
@@ -151,8 +166,8 @@ func (link *Link) RerouteToTunnel(reason string) {
|
||||
|
||||
// UpdateVerdict sets a new verdict for this link, making sure it does not interfere with previous verdicts
|
||||
func (link *Link) UpdateVerdict(newVerdict Verdict) {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
if newVerdict > link.Verdict {
|
||||
link.Verdict = newVerdict
|
||||
@@ -166,8 +181,8 @@ func (link *Link) AddReason(reason string) {
|
||||
return
|
||||
}
|
||||
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
if link.Reason != "" {
|
||||
link.Reason += " | "
|
||||
@@ -185,9 +200,9 @@ func (link *Link) packetHandler() {
|
||||
return
|
||||
}
|
||||
// get handler
|
||||
link.Lock()
|
||||
link.lock.Lock()
|
||||
handler := link.firewallHandler
|
||||
link.Unlock()
|
||||
link.lock.Unlock()
|
||||
// execute handler or verdict
|
||||
if handler != nil {
|
||||
handler(pkt, link)
|
||||
@@ -201,8 +216,8 @@ func (link *Link) packetHandler() {
|
||||
|
||||
// ApplyVerdict appies the link verdict to a packet.
|
||||
func (link *Link) ApplyVerdict(pkt packet.Packet) {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
var err error
|
||||
|
||||
@@ -251,12 +266,12 @@ func (link *Link) SaveWhenFinished() {
|
||||
|
||||
// SaveIfNeeded saves the Link if it is marked for saving when finished.
|
||||
func (link *Link) SaveIfNeeded() {
|
||||
link.Lock()
|
||||
link.lock.Lock()
|
||||
save := link.saveWhenFinished
|
||||
if save {
|
||||
link.saveWhenFinished = false
|
||||
}
|
||||
link.Unlock()
|
||||
link.lock.Unlock()
|
||||
|
||||
if save {
|
||||
link.saveAndLog()
|
||||
@@ -274,18 +289,18 @@ func (link *Link) saveAndLog() {
|
||||
// save saves the link object in the storage and propagates the change.
|
||||
func (link *Link) save() error {
|
||||
// update link
|
||||
link.Lock()
|
||||
link.lock.Lock()
|
||||
if link.comm == nil {
|
||||
link.Unlock()
|
||||
link.lock.Unlock()
|
||||
return errors.New("cannot save link without comms")
|
||||
}
|
||||
|
||||
if !link.KeyIsSet() {
|
||||
link.SetKey(fmt.Sprintf("network:tree/%d/%s/%s", link.comm.Process().Pid, link.comm.Domain, link.ID))
|
||||
link.SetKey(fmt.Sprintf("network:tree/%d/%s/%s", link.comm.Process().Pid, link.comm.Scope, link.ID))
|
||||
link.UpdateMeta()
|
||||
}
|
||||
link.saveWhenFinished = false
|
||||
link.Unlock()
|
||||
link.lock.Unlock()
|
||||
|
||||
// save link
|
||||
linksLock.RLock()
|
||||
@@ -306,8 +321,8 @@ func (link *Link) save() error {
|
||||
func (link *Link) Delete() {
|
||||
linksLock.Lock()
|
||||
defer linksLock.Unlock()
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
delete(links, link.ID)
|
||||
|
||||
@@ -339,10 +354,15 @@ func GetOrCreateLinkByPacket(pkt packet.Packet) (*Link, bool) {
|
||||
// CreateLinkFromPacket creates a new Link based on Packet.
|
||||
func CreateLinkFromPacket(pkt packet.Packet) *Link {
|
||||
link := &Link{
|
||||
ID: pkt.GetLinkID(),
|
||||
ID: pkt.GetLinkID(),
|
||||
Entity: (&intel.Entity{
|
||||
IP: pkt.Info().RemoteIP(),
|
||||
Protocol: uint8(pkt.Info().Protocol),
|
||||
Port: pkt.Info().RemotePort(),
|
||||
}).Init(),
|
||||
Direction: pkt.IsInbound(),
|
||||
Verdict: VerdictUndecided,
|
||||
Started: time.Now().Unix(),
|
||||
RemoteAddress: pkt.FmtRemoteAddress(),
|
||||
saveWhenFinished: true,
|
||||
}
|
||||
return link
|
||||
@@ -350,59 +370,59 @@ func CreateLinkFromPacket(pkt packet.Packet) *Link {
|
||||
|
||||
// GetActiveInspectors returns the list of active inspectors.
|
||||
func (link *Link) GetActiveInspectors() []bool {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
return link.activeInspectors
|
||||
}
|
||||
|
||||
// SetActiveInspectors sets the list of active inspectors.
|
||||
func (link *Link) SetActiveInspectors(new []bool) {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
link.activeInspectors = new
|
||||
}
|
||||
|
||||
// GetInspectorData returns the list of inspector data.
|
||||
func (link *Link) GetInspectorData() map[uint8]interface{} {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
return link.inspectorData
|
||||
}
|
||||
|
||||
// SetInspectorData set the list of inspector data.
|
||||
func (link *Link) SetInspectorData(new map[uint8]interface{}) {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
link.inspectorData = new
|
||||
}
|
||||
|
||||
// String returns a string representation of Link.
|
||||
func (link *Link) String() string {
|
||||
link.Lock()
|
||||
defer link.Unlock()
|
||||
link.lock.Lock()
|
||||
defer link.lock.Unlock()
|
||||
|
||||
if link.comm == nil {
|
||||
return fmt.Sprintf("? <-> %s", link.RemoteAddress)
|
||||
return fmt.Sprintf("? <-> %s", link.Entity.IP.String())
|
||||
}
|
||||
switch link.comm.Domain {
|
||||
case "I":
|
||||
switch link.comm.Scope {
|
||||
case IncomingHost, IncomingLAN, IncomingInternet, IncomingInvalid:
|
||||
if link.comm.process == nil {
|
||||
return fmt.Sprintf("? <- %s", link.RemoteAddress)
|
||||
return fmt.Sprintf("? <- %s", link.Entity.IP.String())
|
||||
}
|
||||
return fmt.Sprintf("%s <- %s", link.comm.process.String(), link.RemoteAddress)
|
||||
case "D":
|
||||
return fmt.Sprintf("%s <- %s", link.comm.process.String(), link.Entity.IP.String())
|
||||
case PeerHost, PeerLAN, PeerInternet, PeerInvalid:
|
||||
if link.comm.process == nil {
|
||||
return fmt.Sprintf("? -> %s", link.RemoteAddress)
|
||||
return fmt.Sprintf("? -> %s", link.Entity.IP.String())
|
||||
}
|
||||
return fmt.Sprintf("%s -> %s", link.comm.process.String(), link.RemoteAddress)
|
||||
return fmt.Sprintf("%s -> %s", link.comm.process.String(), link.Entity.IP.String())
|
||||
default:
|
||||
if link.comm.process == nil {
|
||||
return fmt.Sprintf("? -> %s (%s)", link.comm.Domain, link.RemoteAddress)
|
||||
return fmt.Sprintf("? -> %s (%s)", link.comm.Scope, link.Entity.IP.String())
|
||||
}
|
||||
return fmt.Sprintf("%s to %s (%s)", link.comm.process.String(), link.comm.Domain, link.RemoteAddress)
|
||||
return fmt.Sprintf("%s to %s (%s)", link.comm.process.String(), link.comm.Scope, link.Entity.IP.String())
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user