@@ -22,7 +22,6 @@ import (
22
22
"github.com/safing/portmaster/service/network"
23
23
"github.com/safing/portmaster/service/network/netutils"
24
24
"github.com/safing/portmaster/service/network/packet"
25
- "github.com/safing/portmaster/service/network/reference"
26
25
"github.com/safing/portmaster/service/process"
27
26
"github.com/safing/portmaster/spn/access"
28
27
)
@@ -227,7 +226,6 @@ func fastTrackedPermit(conn *network.Connection, pkt packet.Packet) (verdict net
227
226
meta .Src .Equal (meta .Dst ) {
228
227
log .Tracer (pkt .Ctx ()).Debugf ("filter: fast-track network self-check: %s" , pkt )
229
228
return network .VerdictAccept , true
230
-
231
229
}
232
230
233
231
switch meta .Protocol { //nolint:exhaustive // Checking for specific values only.
@@ -374,6 +372,8 @@ func fastTrackedPermit(conn *network.Connection, pkt packet.Packet) (verdict net
374
372
}
375
373
376
374
func fastTrackHandler (conn * network.Connection , pkt packet.Packet ) {
375
+ conn .SaveWhenFinished ()
376
+
377
377
fastTrackedVerdict , permanent := fastTrackedPermit (conn , pkt )
378
378
if fastTrackedVerdict != network .VerdictUndecided {
379
379
// Set verdict on connection.
@@ -402,6 +402,8 @@ func fastTrackHandler(conn *network.Connection, pkt packet.Packet) {
402
402
}
403
403
404
404
func gatherDataHandler (conn * network.Connection , pkt packet.Packet ) {
405
+ conn .SaveWhenFinished ()
406
+
405
407
// Get process info
406
408
_ = conn .GatherConnectionInfo (pkt )
407
409
// Errors are informational and are logged to the context.
@@ -412,11 +414,20 @@ func gatherDataHandler(conn *network.Connection, pkt packet.Packet) {
412
414
}
413
415
414
416
// Continue to filter handler, when connection data is complete.
415
- conn .UpdateFirewallHandler (filterHandler )
416
- filterHandler (conn , pkt )
417
+ switch conn .IPProtocol { //nolint:exhaustive
418
+ case packet .ICMP , packet .ICMPv6 :
419
+ conn .UpdateFirewallHandler (icmpFilterHandler )
420
+ icmpFilterHandler (conn , pkt )
421
+
422
+ default :
423
+ conn .UpdateFirewallHandler (filterHandler )
424
+ filterHandler (conn , pkt )
425
+ }
417
426
}
418
427
419
428
func filterHandler (conn * network.Connection , pkt packet.Packet ) {
429
+ conn .SaveWhenFinished ()
430
+
420
431
// Skip if data is not complete or packet is info-only.
421
432
if ! conn .DataIsComplete () || pkt .InfoOnly () {
422
433
return
@@ -469,11 +480,12 @@ func filterHandler(conn *network.Connection, pkt packet.Packet) {
469
480
switch {
470
481
case conn .Inspecting :
471
482
log .Tracer (pkt .Ctx ()).Trace ("filter: start inspecting" )
472
- conn .SetFirewallHandler (inspectAndVerdictHandler )
483
+ conn .UpdateFirewallHandler (inspectAndVerdictHandler )
473
484
inspectAndVerdictHandler (conn , pkt )
485
+
474
486
default :
475
487
conn .StopFirewallHandler ()
476
- issueVerdict (conn , pkt , 0 , true )
488
+ verdictHandler (conn , pkt )
477
489
}
478
490
}
479
491
@@ -529,6 +541,18 @@ func FilterConnection(ctx context.Context, conn *network.Connection, pkt packet.
529
541
}
530
542
}
531
543
544
+ // defaultFirewallHandler is used when no other firewall handler is set on a connection.
545
+ func defaultFirewallHandler (conn * network.Connection , pkt packet.Packet ) {
546
+ switch conn .IPProtocol { //nolint:exhaustive
547
+ case packet .ICMP , packet .ICMPv6 :
548
+ // Always use the ICMP handler for ICMP connections.
549
+ icmpFilterHandler (conn , pkt )
550
+
551
+ default :
552
+ verdictHandler (conn , pkt )
553
+ }
554
+ }
555
+
532
556
func verdictHandler (conn * network.Connection , pkt packet.Packet ) {
533
557
// Ignore info-only packets in this handler.
534
558
if pkt .InfoOnly () {
@@ -556,24 +580,83 @@ func inspectAndVerdictHandler(conn *network.Connection, pkt packet.Packet) {
556
580
issueVerdict (conn , pkt , 0 , true )
557
581
}
558
582
583
+ func icmpFilterHandler (conn * network.Connection , pkt packet.Packet ) {
584
+ // Load packet data.
585
+ err := pkt .LoadPacketData ()
586
+ if err != nil {
587
+ log .Tracer (pkt .Ctx ()).Debugf ("filter: failed to load ICMP packet data: %s" , err )
588
+ issueVerdict (conn , pkt , network .VerdictDrop , false )
589
+ return
590
+ }
591
+
592
+ // Submit to ICMP listener.
593
+ submitted := netenv .SubmitPacketToICMPListener (pkt )
594
+ if submitted {
595
+ issueVerdict (conn , pkt , network .VerdictDrop , false )
596
+ return
597
+ }
598
+
599
+ // Handle echo request and replies regularly.
600
+ // Other ICMP packets are considered system business.
601
+ icmpLayers := pkt .Layers ().LayerClass (layers .LayerClassIPControl )
602
+ switch icmpLayer := icmpLayers .(type ) {
603
+ case * layers.ICMPv4 :
604
+ switch icmpLayer .TypeCode .Type () {
605
+ case layers .ICMPv4TypeEchoRequest ,
606
+ layers .ICMPv4TypeEchoReply :
607
+ // Continue
608
+ default :
609
+ issueVerdict (conn , pkt , network .VerdictAccept , false )
610
+ return
611
+ }
612
+
613
+ case * layers.ICMPv6 :
614
+ switch icmpLayer .TypeCode .Type () {
615
+ case layers .ICMPv6TypeEchoRequest ,
616
+ layers .ICMPv6TypeEchoReply :
617
+ // Continue
618
+
619
+ default :
620
+ issueVerdict (conn , pkt , network .VerdictAccept , false )
621
+ return
622
+ }
623
+ }
624
+
625
+ // Check if we already have a verdict.
626
+ switch conn .Verdict { //nolint:exhaustive
627
+ case network .VerdictUndecided , network .VerdictUndeterminable :
628
+ // Apply privacy filter and check tunneling.
629
+ FilterConnection (pkt .Ctx (), conn , pkt , true , false )
630
+
631
+ // Save and propagate changes.
632
+ conn .SaveWhenFinished ()
633
+ }
634
+
635
+ // Outbound direction has priority.
636
+ if conn .Inbound && conn .Ended == 0 && pkt .IsOutbound () {
637
+ // Change direction from inbound to outbound on first outbound ICMP packet.
638
+ conn .Inbound = false
639
+
640
+ // Apply privacy filter and check tunneling.
641
+ FilterConnection (pkt .Ctx (), conn , pkt , true , false )
642
+
643
+ // Save and propagate changes.
644
+ conn .SaveWhenFinished ()
645
+ }
646
+
647
+ issueVerdict (conn , pkt , 0 , false )
648
+ }
649
+
559
650
func issueVerdict (conn * network.Connection , pkt packet.Packet , verdict network.Verdict , allowPermanent bool ) {
560
651
// Check if packed was already fast-tracked by the OS integration.
561
652
if pkt .FastTrackedByIntegration () {
562
653
return
563
654
}
564
655
565
656
// Enable permanent verdict.
566
- if allowPermanent && ! conn .VerdictPermanent {
567
- switch {
568
- case ! permanentVerdicts ():
569
- // Permanent verdicts are disabled by configuration.
570
- case conn .Entity != nil && reference .IsICMP (conn .Entity .Protocol ):
571
- case pkt != nil && reference .IsICMP (uint8 (pkt .Info ().Protocol )):
572
- // ICMP is handled differently based on payload, so we cannot use persistent verdicts.
573
- default :
574
- conn .VerdictPermanent = true
575
- conn .SaveWhenFinished ()
576
- }
657
+ if allowPermanent && ! conn .VerdictPermanent && permanentVerdicts () {
658
+ conn .VerdictPermanent = true
659
+ conn .SaveWhenFinished ()
577
660
}
578
661
579
662
// do not allow to circumvent decision: e.g. to ACCEPT packets from a DROP-ed connection
0 commit comments