From 4348caa2582e5527b9386a3795c637664d5e6256 Mon Sep 17 00:00:00 2001
From: Daniel <dhaavi@users.noreply.github.com>
Date: Fri, 25 Oct 2019 13:35:25 +0200
Subject: [PATCH] Clean up and adapt firewall package to recent changes

---
 firewall/config.go                       | 12 ++++++++----
 firewall/dialer.go                       |  2 ++
 firewall/firewall.go                     |  9 ++++++---
 firewall/interception/nfqueue/doc.go     |  2 ++
 firewall/interception/nfqueue/nfqueue.go |  2 +-
 firewall/master.go                       |  4 ++--
 firewall/ports.go                        |  4 ++--
 firewall/prompt.go                       |  2 +-
 8 files changed, 24 insertions(+), 13 deletions(-)
 create mode 100644 firewall/interception/nfqueue/doc.go

diff --git a/firewall/config.go b/firewall/config.go
index 985138c8..32653b4a 100644
--- a/firewall/config.go
+++ b/firewall/config.go
@@ -20,8 +20,9 @@ func registerConfig() error {
 		Name:           "Permanent Verdicts",
 		Key:            "firewall/permanentVerdicts",
 		Description:    "With permanent verdicts, control of a connection is fully handed back to the OS after the initial decision. This brings a great performance increase, but makes it impossible to change the decision of a link later on.",
-		ExpertiseLevel: config.ExpertiseLevelExpert,
 		OptType:        config.OptTypeBool,
+		ExpertiseLevel: config.ExpertiseLevelExpert,
+		ReleaseLevel:   config.ReleaseLevelExperimental,
 		DefaultValue:   true,
 	})
 	if err != nil {
@@ -33,8 +34,9 @@ func registerConfig() error {
 		Name:            "Filter DNS Responses by Server Scope",
 		Key:             "firewall/filterDNSByScope",
 		Description:     "This option will filter out DNS answers that are outside of the scope of the server. A server on the public Internet may not respond with a private LAN address.",
-		ExpertiseLevel:  config.ExpertiseLevelExpert,
 		OptType:         config.OptTypeInt,
+		ExpertiseLevel:  config.ExpertiseLevelExpert,
+		ReleaseLevel:    config.ReleaseLevelBeta,
 		ExternalOptType: "security level",
 		DefaultValue:    7,
 		ValidationRegex: "^(7|6|4)$",
@@ -48,8 +50,9 @@ func registerConfig() error {
 		Name:            "Filter DNS Responses by Application Profile",
 		Key:             "firewall/filterDNSByProfile",
 		Description:     "This option will filter out DNS answers that an application would not be allowed to connect, based on its profile.",
-		ExpertiseLevel:  config.ExpertiseLevelExpert,
 		OptType:         config.OptTypeInt,
+		ExpertiseLevel:  config.ExpertiseLevelExpert,
+		ReleaseLevel:    config.ReleaseLevelBeta,
 		ExternalOptType: "security level",
 		DefaultValue:    7,
 		ValidationRegex: "^(7|6|4)$",
@@ -63,8 +66,9 @@ func registerConfig() error {
 		Name:           "Timeout for prompt notifications",
 		Key:            "firewall/promptTimeout",
 		Description:    "Amount of time how long Portmaster will wait for a response when prompting about a connection via a notification. In seconds.",
-		ExpertiseLevel: config.ExpertiseLevelUser,
 		OptType:        config.OptTypeInt,
+		ExpertiseLevel: config.ExpertiseLevelUser,
+		ReleaseLevel:   config.ReleaseLevelBeta,
 		DefaultValue:   60,
 	})
 	if err != nil {
diff --git a/firewall/dialer.go b/firewall/dialer.go
index b3fab103..325f41a1 100644
--- a/firewall/dialer.go
+++ b/firewall/dialer.go
@@ -5,10 +5,12 @@ import (
 	"net"
 
 	"github.com/safing/portmaster/intel"
+	"github.com/safing/portmaster/network/environment"
 )
 
 func init() {
 	intel.SetLocalAddrFactory(PermittedAddr)
+	environment.SetLocalAddrFactory(PermittedAddr)
 }
 
 // PermittedAddr returns an already permitted local address for the given network for reliable connectivity.
diff --git a/firewall/firewall.go b/firewall/firewall.go
index 41c5c2e5..83b1840d 100644
--- a/firewall/firewall.go
+++ b/firewall/firewall.go
@@ -167,8 +167,11 @@ func handlePacket(pkt packet.Packet) {
 	// 	}
 	// }
 
-	pkt.SetCtx(log.AddTracer(context.Background()))
-	log.Tracer(pkt.Ctx()).Tracef("firewall: handling packet: %s", pkt)
+	traceCtx, tracer := log.AddTracer(context.Background())
+	if tracer != nil {
+		pkt.SetCtx(traceCtx)
+		tracer.Tracef("firewall: handling packet: %s", pkt)
+	}
 
 	// associate packet to link and handle
 	link, created := network.GetOrCreateLinkByPacket(pkt)
@@ -340,7 +343,7 @@ func issueVerdict(pkt packet.Packet, link *network.Link, verdict network.Verdict
 
 	link.Unlock()
 
-	log.InfoTracef(pkt.Ctx(), "firewall: %s %s", link.Verdict, link)
+	log.Tracer(pkt.Ctx()).Infof("firewall: %s %s", link.Verdict, link)
 }
 
 // func tunnelHandler(pkt packet.Packet) {
diff --git a/firewall/interception/nfqueue/doc.go b/firewall/interception/nfqueue/doc.go
new file mode 100644
index 00000000..c6f78c8b
--- /dev/null
+++ b/firewall/interception/nfqueue/doc.go
@@ -0,0 +1,2 @@
+// Package nfqueue provides network interception capabilites on linux via iptables nfqueue.
+package nfqueue
diff --git a/firewall/interception/nfqueue/nfqueue.go b/firewall/interception/nfqueue/nfqueue.go
index 27665240..da4b0575 100644
--- a/firewall/interception/nfqueue/nfqueue.go
+++ b/firewall/interception/nfqueue/nfqueue.go
@@ -64,7 +64,7 @@ func NewNFQueue(qid uint16) (nfq *NFQueue, err error) {
 func (this *NFQueue) init() error {
 	var err error
 	if this.h, err = C.nfq_open(); err != nil || this.h == nil {
-		fmt.Errorf("could not open nfqueue: %s", err)
+		return fmt.Errorf("could not open nfqueue: %s", err)
 	}
 
 	//if this.qh, err = C.nfq_create_queue(this.h, qid, C.get_cb(), unsafe.Pointer(nfq)); err != nil || this.qh == nil {
diff --git a/firewall/master.go b/firewall/master.go
index 8795c975..f4519f90 100644
--- a/firewall/master.go
+++ b/firewall/master.go
@@ -139,7 +139,7 @@ func DecideOnCommunicationAfterIntel(comm *network.Communication, fqdn string, r
 }
 
 // FilterDNSResponse filters a dns response according to the application profile and settings.
-func FilterDNSResponse(comm *network.Communication, fqdn string, rrCache *intel.RRCache) *intel.RRCache {
+func FilterDNSResponse(comm *network.Communication, q *intel.Query, rrCache *intel.RRCache) *intel.RRCache {
 	// do not modify own queries - this should not happen anyway
 	if comm.Process().Pid == os.Getpid() {
 		return rrCache
@@ -228,7 +228,7 @@ func FilterDNSResponse(comm *network.Communication, fqdn string, rrCache *intel.
 				}
 
 				// filter by endpoints
-				result, _ = profileSet.CheckEndpointIP(fqdn, ip, 0, 0, false)
+				result, _ = profileSet.CheckEndpointIP(q.FQDN, ip, 0, 0, false)
 				if result == profile.Denied {
 					addressesRemoved++
 					rrCache.FilteredEntries = append(rrCache.FilteredEntries, rr.String())
diff --git a/firewall/ports.go b/firewall/ports.go
index fc41727b..4271a924 100644
--- a/firewall/ports.go
+++ b/firewall/ports.go
@@ -4,8 +4,8 @@ import (
 	"sync"
 	"time"
 
-	"github.com/safing/portbase/crypto/random"
 	"github.com/safing/portbase/log"
+	"github.com/safing/portbase/rng"
 )
 
 type portStatus struct {
@@ -48,7 +48,7 @@ func GetPermittedPort() uint16 {
 
 	for i := 0; i < 1000; i++ {
 		// generate port between 10000 and 65535
-		rN, err := random.Number(55535)
+		rN, err := rng.Number(55535)
 		if err != nil {
 			log.Warningf("firewall: failed to generate random port: %s", err)
 			return 0
diff --git a/firewall/prompt.go b/firewall/prompt.go
index 274927c7..d50fe3ad 100644
--- a/firewall/prompt.go
+++ b/firewall/prompt.go
@@ -41,7 +41,7 @@ func prompt(comm *network.Communication, link *network.Link, pkt packet.Packet,
 			}
 			return
 		}
-		nID = fmt.Sprintf("firewall-prompt-%d-%s-%s", comm.Process().Pid, comm.Domain, pkt.Info().RemoteIP)
+		nID = fmt.Sprintf("firewall-prompt-%d-%s-%s", comm.Process().Pid, comm.Domain, pkt.Info().RemoteIP())
 	default: // connection to domain
 		nID = fmt.Sprintf("firewall-prompt-%d-%s", comm.Process().Pid, comm.Domain)
 	}