mirror of
https://github.com/safing/portmaster
synced 2025-04-19 10:29:11 +00:00
* Move portbase into monorepo * Add new simple module mgr * [WIP] Switch to new simple module mgr * Add StateMgr and more worker variants * [WIP] Switch more modules * [WIP] Switch more modules * [WIP] swtich more modules * [WIP] switch all SPN modules * [WIP] switch all service modules * [WIP] Convert all workers to the new module system * [WIP] add new task system to module manager * [WIP] Add second take for scheduling workers * [WIP] Add FIXME for bugs in new scheduler * [WIP] Add minor improvements to scheduler * [WIP] Add new worker scheduler * [WIP] Fix more bug related to new module system * [WIP] Fix start handing of the new module system * [WIP] Improve startup process * [WIP] Fix minor issues * [WIP] Fix missing subsystem in settings * [WIP] Initialize managers in constructor * [WIP] Move module event initialization to constrictors * [WIP] Fix setting for enabling and disabling the SPN module * [WIP] Move API registeration into module construction * [WIP] Update states mgr for all modules * [WIP] Add CmdLine operation support * Add state helper methods to module group and instance * Add notification and module status handling to status package * Fix starting issues * Remove pilot widget and update security lock to new status data * Remove debug logs * Improve http server shutdown * Add workaround for cleanly shutting down firewall+netquery * Improve logging * Add syncing states with notifications for new module system * Improve starting, stopping, shutdown; resolve FIXMEs/TODOs * [WIP] Fix most unit tests * Review new module system and fix minor issues * Push shutdown and restart events again via API * Set sleep mode via interface * Update example/template module * [WIP] Fix spn/cabin unit test * Remove deprecated UI elements * Make log output more similar for the logging transition phase * Switch spn hub and observer cmds to new module system * Fix log sources * Make worker mgr less error prone * Fix tests and minor issues * Fix observation hub * Improve shutdown and restart handling * Split up big connection.go source file * Move varint and dsd packages to structures repo * Improve expansion test * Fix linter warnings * Fix interception module on windows * Fix linter errors --------- Co-authored-by: Vladimir Stoilov <vladimir@safing.io>
211 lines
5 KiB
Go
211 lines
5 KiB
Go
package netenv
|
|
|
|
import (
|
|
"bufio"
|
|
"encoding/hex"
|
|
"net"
|
|
"os"
|
|
"strings"
|
|
"sync"
|
|
|
|
"github.com/miekg/dns"
|
|
|
|
"github.com/safing/portmaster/base/log"
|
|
"github.com/safing/portmaster/service/network/netutils"
|
|
)
|
|
|
|
var (
|
|
gateways = make([]net.IP, 0)
|
|
gatewaysLock sync.Mutex
|
|
gatewaysNetworkChangedFlag = GetNetworkChangedFlag()
|
|
|
|
nameservers = make([]Nameserver, 0)
|
|
nameserversLock sync.Mutex
|
|
nameserversNetworkChangedFlag = GetNetworkChangedFlag()
|
|
)
|
|
|
|
// Gateways returns the currently active gateways.
|
|
func Gateways() []net.IP {
|
|
gatewaysLock.Lock()
|
|
defer gatewaysLock.Unlock()
|
|
// Check if the network changed, if not, return cache.
|
|
if !gatewaysNetworkChangedFlag.IsSet() {
|
|
return gateways
|
|
}
|
|
gatewaysNetworkChangedFlag.Refresh()
|
|
|
|
gateways = make([]net.IP, 0)
|
|
var decoded []byte
|
|
|
|
// open file
|
|
route, err := os.Open("/proc/net/route")
|
|
if err != nil {
|
|
log.Warningf("environment: could not read /proc/net/route: %s", err)
|
|
return gateways
|
|
}
|
|
defer func() {
|
|
_ = route.Close()
|
|
}()
|
|
|
|
// file scanner
|
|
scanner := bufio.NewScanner(route)
|
|
scanner.Split(bufio.ScanLines)
|
|
|
|
// parse
|
|
for scanner.Scan() {
|
|
line := strings.SplitN(scanner.Text(), "\t", 4)
|
|
if len(line) < 4 {
|
|
continue
|
|
}
|
|
if line[1] == "00000000" {
|
|
decoded, err = hex.DecodeString(line[2])
|
|
if err != nil {
|
|
log.Warningf("environment: could not parse gateway %s from /proc/net/route: %s", line[2], err)
|
|
continue
|
|
}
|
|
if len(decoded) != 4 {
|
|
log.Warningf("environment: decoded gateway %s from /proc/net/route has wrong length", decoded)
|
|
continue
|
|
}
|
|
gate := net.IPv4(decoded[3], decoded[2], decoded[1], decoded[0])
|
|
gateways = append(gateways, gate)
|
|
}
|
|
}
|
|
|
|
// open file
|
|
v6route, err := os.Open("/proc/net/ipv6_route")
|
|
if err != nil {
|
|
log.Warningf("environment: could not read /proc/net/ipv6_route: %s", err)
|
|
return gateways
|
|
}
|
|
defer func() {
|
|
_ = v6route.Close()
|
|
}()
|
|
|
|
// file scanner
|
|
scanner = bufio.NewScanner(v6route)
|
|
scanner.Split(bufio.ScanLines)
|
|
|
|
// parse
|
|
for scanner.Scan() {
|
|
line := strings.SplitN(scanner.Text(), " ", 6)
|
|
if len(line) < 6 {
|
|
continue
|
|
}
|
|
if line[0] == "00000000000000000000000000000000" && line[4] != "00000000000000000000000000000000" {
|
|
decoded, err := hex.DecodeString(line[4])
|
|
if err != nil {
|
|
log.Warningf("environment: could not parse gateway %s from /proc/net/ipv6_route: %s", line[2], err)
|
|
continue
|
|
}
|
|
if len(decoded) != 16 {
|
|
log.Warningf("environment: decoded gateway %s from /proc/net/ipv6_route has wrong length", decoded)
|
|
continue
|
|
}
|
|
gate := net.IP(decoded)
|
|
gateways = append(gateways, gate)
|
|
}
|
|
}
|
|
|
|
return gateways
|
|
}
|
|
|
|
// Nameservers returns the currently active nameservers.
|
|
func Nameservers() []Nameserver {
|
|
nameserversLock.Lock()
|
|
defer nameserversLock.Unlock()
|
|
// Check if the network changed, if not, return cache.
|
|
if !nameserversNetworkChangedFlag.IsSet() {
|
|
return nameservers
|
|
}
|
|
nameserversNetworkChangedFlag.Refresh()
|
|
|
|
// logic
|
|
// TODO: try:
|
|
// 1. NetworkManager DBUS
|
|
// 2. /etc/resolv.conf
|
|
// 2.1. if /etc/resolv.conf has localhost nameserver, check for dnsmasq config (are there others?)
|
|
nameservers = make([]Nameserver, 0)
|
|
|
|
// get nameservers from DBUS
|
|
dbusNameservers, err := getNameserversFromDbus()
|
|
if err != nil {
|
|
log.Warningf("environment: could not get nameservers from dbus: %s", err)
|
|
} else {
|
|
nameservers = addNameservers(nameservers, dbusNameservers)
|
|
}
|
|
|
|
// get nameservers from /etc/resolv.conf
|
|
resolvconfNameservers, err := getNameserversFromResolvconf()
|
|
if err != nil {
|
|
log.Warningf("environment: could not get nameservers from resolvconf: %s", err)
|
|
} else {
|
|
nameservers = addNameservers(nameservers, resolvconfNameservers)
|
|
}
|
|
|
|
return nameservers
|
|
}
|
|
|
|
func getNameserversFromResolvconf() ([]Nameserver, error) {
|
|
// open file
|
|
resolvconf, err := os.Open("/etc/resolv.conf")
|
|
if err != nil {
|
|
log.Warningf("environment: could not read /etc/resolv.conf: %s", err)
|
|
return nil, err
|
|
}
|
|
defer func() {
|
|
_ = resolvconf.Close()
|
|
}()
|
|
|
|
// file scanner
|
|
scanner := bufio.NewScanner(resolvconf)
|
|
scanner.Split(bufio.ScanLines)
|
|
|
|
var searchDomains []string
|
|
var servers []net.IP
|
|
|
|
// parse
|
|
for scanner.Scan() {
|
|
line := strings.SplitN(scanner.Text(), " ", 3)
|
|
if len(line) < 2 {
|
|
continue
|
|
}
|
|
switch line[0] {
|
|
case "search":
|
|
if netutils.IsValidFqdn(dns.Fqdn(line[1])) {
|
|
searchDomains = append(searchDomains, line[1])
|
|
}
|
|
case "nameserver":
|
|
ip := net.ParseIP(line[1])
|
|
if ip != nil {
|
|
servers = append(servers, ip)
|
|
}
|
|
}
|
|
}
|
|
|
|
// build array
|
|
nameservers := make([]Nameserver, 0, len(servers))
|
|
for _, server := range servers {
|
|
nameservers = append(nameservers, Nameserver{
|
|
IP: server,
|
|
Search: searchDomains,
|
|
})
|
|
}
|
|
return nameservers, nil
|
|
}
|
|
|
|
func addNameservers(nameservers, newNameservers []Nameserver) []Nameserver {
|
|
for _, newNameserver := range newNameservers {
|
|
found := false
|
|
for _, nameserver := range nameservers {
|
|
if nameserver.IP.Equal(newNameserver.IP) {
|
|
found = true
|
|
break
|
|
}
|
|
}
|
|
if !found {
|
|
nameservers = append(nameservers, newNameserver)
|
|
}
|
|
}
|
|
return nameservers
|
|
}
|