Skip virtual interfaces when parsing route table

Since routing through virtual interfaces may trigger DNS loop in VPN
like observing in UnifiOS Site Magic VPN.
This commit is contained in:
Cuong Manh Le
2024-10-11 17:15:47 +07:00
committed by Cuong Manh Le
parent 5ac9d17bdf
commit 9501e35c60
2 changed files with 44 additions and 1 deletions

View File

@@ -6,6 +6,7 @@ import (
"encoding/hex"
"net"
"os"
"strings"
"github.com/Control-D-Inc/ctrld/internal/dns/resolvconffile"
)
@@ -28,6 +29,7 @@ func dns4() []string {
var dns []string
seen := make(map[string]bool)
vis := virtualInterfaces()
s := bufio.NewScanner(f)
first := true
for s.Scan() {
@@ -39,7 +41,10 @@ func dns4() []string {
if len(fields) < 2 {
continue
}
// Skip virtual interfaces.
if vis.contains(string(bytes.TrimSpace(fields[0]))) {
continue
}
gw := make([]byte, net.IPv4len)
// Third fields is gateway.
if _, err := hex.Decode(gw, fields[2]); err != nil {
@@ -63,12 +68,17 @@ func dns6() []string {
defer f.Close()
var dns []string
vis := virtualInterfaces()
s := bufio.NewScanner(f)
for s.Scan() {
fields := bytes.Fields(s.Bytes())
if len(fields) < 4 {
continue
}
// Skip virtual interfaces.
if vis.contains(string(bytes.TrimSpace(fields[len(fields)-1]))) {
continue
}
gw := make([]byte, net.IPv6len)
// Fifth fields is gateway.
@@ -95,3 +105,26 @@ func dnsFromSystemdResolver() []string {
}
return ns
}
type set map[string]struct{}
func (s *set) add(e string) {
(*s)[e] = struct{}{}
}
func (s *set) contains(e string) bool {
_, ok := (*s)[e]
return ok
}
// virtualInterfaces returns a set of virtual interfaces on current machine.
func virtualInterfaces() set {
s := make(set)
entries, _ := os.ReadDir("/sys/devices/virtual/net")
for _, entry := range entries {
if entry.IsDir() {
s.add(strings.TrimSpace(entry.Name()))
}
}
return s
}

10
nameservers_linux_test.go Normal file
View File

@@ -0,0 +1,10 @@
package ctrld
import (
"testing"
)
func Test_virtualInterfaces(t *testing.T) {
vis := virtualInterfaces()
t.Log(vis)
}