mirror of
https://github.com/safing/portmaster
synced 2025-09-01 10:09:11 +00:00
Fix and improve network listener system integration and check
Also, improve logging.
This commit is contained in:
parent
edf46d33c4
commit
9d35ff3192
5 changed files with 82 additions and 33 deletions
|
@ -80,7 +80,7 @@ func init() {
|
|||
"mangle INPUT -j C171",
|
||||
"filter OUTPUT -j C17",
|
||||
"filter INPUT -j C17",
|
||||
"nat OUTPUT -m mark --mark 1799 -p udp -j DNAT --to 127.0.0.1:53",
|
||||
"nat OUTPUT -m mark --mark 1799 -p udp -j DNAT --to 127.0.0.17:53",
|
||||
"nat OUTPUT -m mark --mark 1717 -p tcp -j DNAT --to 127.0.0.17:717",
|
||||
"nat OUTPUT -m mark --mark 1717 -p udp -j DNAT --to 127.0.0.17:717",
|
||||
// "nat OUTPUT -m mark --mark 1717 ! -p tcp ! -p udp -j DNAT --to 127.0.0.17",
|
||||
|
@ -115,7 +115,7 @@ func init() {
|
|||
"mangle INPUT -j C171",
|
||||
"filter OUTPUT -j C17",
|
||||
"filter INPUT -j C17",
|
||||
"nat OUTPUT -m mark --mark 1799 -p udp -j DNAT --to [::1]:53",
|
||||
"nat OUTPUT -m mark --mark 1799 -p udp -j DNAT --to [fd17::17]:53",
|
||||
"nat OUTPUT -m mark --mark 1717 -p tcp -j DNAT --to [fd17::17]:717",
|
||||
"nat OUTPUT -m mark --mark 1717 -p udp -j DNAT --to [fd17::17]:717",
|
||||
// "nat OUTPUT -m mark --mark 1717 ! -p tcp ! -p udp -j DNAT --to [fd17::17]",
|
||||
|
|
|
@ -301,15 +301,15 @@ func checkDomainHeuristics(ctx context.Context, conn *network.Connection, _ pack
|
|||
// we don't apply any checks here and let the request through
|
||||
// because a malformed domain-name will likely be dropped by
|
||||
// checks better suited for that.
|
||||
log.Tracer(ctx).Warningf("nameserver: failed to get eTLD+1: %s", err)
|
||||
log.Tracer(ctx).Warningf("filter: failed to get eTLD+1: %s", err)
|
||||
return false
|
||||
}
|
||||
|
||||
domainToCheck := strings.Split(etld1, ".")[0]
|
||||
score := dga.LmsScore(domainToCheck)
|
||||
if score < 5 {
|
||||
log.Tracer(ctx).Warningf(
|
||||
"nameserver: possible data tunnel by %s in eTLD+1 %s: %s has an lms score of %.2f, returning nxdomain",
|
||||
log.Tracer(ctx).Debugf(
|
||||
"filter: possible data tunnel by %s in eTLD+1 %s: %s has an lms score of %.2f",
|
||||
conn.Process(),
|
||||
etld1,
|
||||
domainToCheck,
|
||||
|
@ -318,7 +318,7 @@ func checkDomainHeuristics(ctx context.Context, conn *network.Connection, _ pack
|
|||
conn.Block("possible DGA domain commonly used by malware")
|
||||
return true
|
||||
}
|
||||
log.Tracer(ctx).Infof("LMS score of eTLD+1 %s is %.2f", etld1, score)
|
||||
log.Tracer(ctx).Tracef("filter: LMS score of eTLD+1 %s is %.2f", etld1, score)
|
||||
|
||||
// 100 is a somewhat arbitrary threshold to ensure we don't mess
|
||||
// around with CDN domain names to early. They use short second-level
|
||||
|
@ -328,8 +328,8 @@ func checkDomainHeuristics(ctx context.Context, conn *network.Connection, _ pack
|
|||
domainToCheck = trimmedDomain[0:len(etld1)]
|
||||
score := dga.LmsScoreOfDomain(domainToCheck)
|
||||
if score < 10 {
|
||||
log.Tracer(ctx).Warningf(
|
||||
"nameserver: possible data tunnel by %s in subdomain %s: %s has an lms score of %.2f, returning nxdomain",
|
||||
log.Tracer(ctx).Debugf(
|
||||
"filter: possible data tunnel by %s in subdomain of %s: %s has an lms score of %.2f",
|
||||
conn.Process(),
|
||||
conn.Entity.Domain,
|
||||
domainToCheck,
|
||||
|
@ -338,7 +338,7 @@ func checkDomainHeuristics(ctx context.Context, conn *network.Connection, _ pack
|
|||
conn.Block("possible data tunnel for covert communication and protection bypassing")
|
||||
return true
|
||||
}
|
||||
log.Tracer(ctx).Infof("LMS score of entire domain is %.2f", score)
|
||||
log.Tracer(ctx).Tracef("filter: LMS score of entire domain is %.2f", score)
|
||||
}
|
||||
|
||||
return false
|
||||
|
|
|
@ -138,26 +138,22 @@ func handleRequest(ctx context.Context, w dns.ResponseWriter, query *dns.Msg) er
|
|||
return nil
|
||||
}
|
||||
|
||||
// get addresses
|
||||
// get remote address
|
||||
remoteAddr, ok := w.RemoteAddr().(*net.UDPAddr)
|
||||
if !ok {
|
||||
log.Warningf("nameserver: could not get remote address of request for %s%s, ignoring", q.FQDN, q.QType)
|
||||
log.Warningf("nameserver: failed to get remote address of request for %s%s, ignoring", q.FQDN, q.QType)
|
||||
return nil
|
||||
}
|
||||
if !netutils.IPIsLocalhost(remoteAddr.IP) {
|
||||
// If request is not from a localhost address, check it it's really local.
|
||||
|
||||
localAddr, ok := w.RemoteAddr().(*net.UDPAddr)
|
||||
if !ok {
|
||||
log.Warningf("nameserver: could not get local address of request for %s%s, ignoring", q.FQDN, q.QType)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ignore external request
|
||||
if !remoteAddr.IP.Equal(localAddr.IP) {
|
||||
log.Warningf("nameserver: external request for %s%s, ignoring", q.FQDN, q.QType)
|
||||
return nil
|
||||
}
|
||||
// check if the request is local
|
||||
local, err := netenv.IsMyIP(remoteAddr.IP)
|
||||
if err != nil {
|
||||
log.Warningf("nameserver: failed to check if request for %s%s is local: %s", q.FQDN, q.QType, err)
|
||||
return nil
|
||||
}
|
||||
if !local {
|
||||
log.Warningf("nameserver: external request for %s%s, ignoring", q.FQDN, q.QType)
|
||||
return nil
|
||||
}
|
||||
|
||||
// check if valid domain name
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
package netenv
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"github.com/safing/portbase/log"
|
||||
"github.com/safing/portmaster/network/netutils"
|
||||
)
|
||||
|
||||
|
@ -14,13 +16,16 @@ func GetAssignedAddresses() (ipv4 []net.IP, ipv6 []net.IP, err error) {
|
|||
return nil, nil, err
|
||||
}
|
||||
for _, addr := range addrs {
|
||||
ip := net.ParseIP(strings.Split(addr.String(), "/")[0])
|
||||
if ip != nil {
|
||||
if ip4 := ip.To4(); ip4 != nil {
|
||||
ipv4 = append(ipv4, ip4)
|
||||
} else {
|
||||
ipv6 = append(ipv6, ip)
|
||||
}
|
||||
netAddr, ok := addr.(*net.IPNet)
|
||||
if !ok {
|
||||
log.Warningf("netenv: interface address of unexpected type %T", addr)
|
||||
continue
|
||||
}
|
||||
|
||||
if ip4 := netAddr.IP.To4(); ip4 != nil {
|
||||
ipv4 = append(ipv4, ip4)
|
||||
} else {
|
||||
ipv6 = append(ipv6, netAddr.IP)
|
||||
}
|
||||
}
|
||||
return
|
||||
|
@ -44,3 +49,50 @@ func GetAssignedGlobalAddresses() (ipv4 []net.IP, ipv6 []net.IP, err error) {
|
|||
}
|
||||
return
|
||||
}
|
||||
|
||||
var (
|
||||
myIPs []net.IP
|
||||
myIPsLock sync.Mutex
|
||||
)
|
||||
|
||||
// IsMyIP returns whether the given IP is currently configured on the local host.
|
||||
func IsMyIP(ip net.IP) (yes bool, err error) {
|
||||
if netutils.IPIsLocalhost(ip) {
|
||||
return true, nil
|
||||
}
|
||||
|
||||
myIPsLock.Lock()
|
||||
defer myIPsLock.Unlock()
|
||||
|
||||
// check
|
||||
for _, myIP := range myIPs {
|
||||
if ip.Equal(myIP) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
// refresh IPs
|
||||
myAddrs, err := net.InterfaceAddrs()
|
||||
if err != nil {
|
||||
return false, fmt.Errorf("failed to refresh interface addresses: %s", err)
|
||||
}
|
||||
myIPs = make([]net.IP, 0, len(myAddrs))
|
||||
for _, addr := range myAddrs {
|
||||
netAddr, ok := addr.(*net.IPNet)
|
||||
if !ok {
|
||||
log.Warningf("netenv: interface address of unexpected type %T", addr)
|
||||
continue
|
||||
}
|
||||
|
||||
myIPs = append(myIPs, netAddr.IP)
|
||||
}
|
||||
|
||||
// check again
|
||||
for _, myIP := range myIPs {
|
||||
if ip.Equal(myIP) {
|
||||
return true, nil
|
||||
}
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
|
|
@ -2,6 +2,7 @@ package state
|
|||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
|
@ -155,5 +156,5 @@ func (table *udpTable) cleanStates(now time.Time) {
|
|||
|
||||
func makeUDPStateKey(address socket.Address) string {
|
||||
// This could potentially go wrong, but as all IPs are created by the same source, everything should be fine.
|
||||
return string(address.IP) + string(address.Port)
|
||||
return string(address.IP) + strconv.Itoa(int(address.Port))
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue