mirror of
https://github.com/fosrl/olm.git
synced 2026-02-28 07:46:41 +00:00
66
olm/dns_override_darwin.go
Normal file
66
olm/dns_override_darwin.go
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
//go:build darwin && !ios
|
||||||
|
|
||||||
|
package olm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
|
"github.com/fosrl/newt/logger"
|
||||||
|
"github.com/fosrl/olm/dns"
|
||||||
|
platform "github.com/fosrl/olm/dns/platform"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetupDNSOverride configures the system DNS to use the DNS proxy on macOS
|
||||||
|
// Uses scutil for DNS configuration
|
||||||
|
func SetupDNSOverride(interfaceName string, dnsProxy *dns.DNSProxy) error {
|
||||||
|
if dnsProxy == nil {
|
||||||
|
return fmt.Errorf("DNS proxy is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
configurator, err = platform.NewDarwinDNSConfigurator()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create Darwin DNS configurator: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Using Darwin scutil DNS configurator")
|
||||||
|
|
||||||
|
// Get current DNS servers before changing
|
||||||
|
currentDNS, err := configurator.GetCurrentDNS()
|
||||||
|
if err != nil {
|
||||||
|
logger.Warn("Could not get current DNS: %v", err)
|
||||||
|
} else {
|
||||||
|
logger.Info("Current DNS servers: %v", currentDNS)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set new DNS servers to point to our proxy
|
||||||
|
newDNS := []netip.Addr{
|
||||||
|
dnsProxy.GetProxyIP(),
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Setting DNS servers to: %v", newDNS)
|
||||||
|
originalDNS, err := configurator.SetDNS(newDNS)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to set DNS: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Original DNS servers backed up: %v", originalDNS)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RestoreDNSOverride restores the original DNS configuration
|
||||||
|
func RestoreDNSOverride() error {
|
||||||
|
if configurator == nil {
|
||||||
|
logger.Debug("No DNS configurator to restore")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Restoring original DNS configuration")
|
||||||
|
if err := configurator.RestoreDNS(); err != nil {
|
||||||
|
return fmt.Errorf("failed to restore DNS: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("DNS configuration restored successfully")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
102
olm/dns_override_unix.go
Normal file
102
olm/dns_override_unix.go
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
//go:build (linux && !android) || freebsd
|
||||||
|
|
||||||
|
package olm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
|
"github.com/fosrl/newt/logger"
|
||||||
|
"github.com/fosrl/olm/dns"
|
||||||
|
platform "github.com/fosrl/olm/dns/platform"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetupDNSOverride configures the system DNS to use the DNS proxy on Linux/FreeBSD
|
||||||
|
// Tries systemd-resolved, NetworkManager, resolvconf, or falls back to /etc/resolv.conf
|
||||||
|
func SetupDNSOverride(interfaceName string, dnsProxy *dns.DNSProxy) error {
|
||||||
|
if dnsProxy == nil {
|
||||||
|
return fmt.Errorf("DNS proxy is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
var err error
|
||||||
|
|
||||||
|
// Try systemd-resolved first (most modern)
|
||||||
|
if platform.IsSystemdResolvedAvailable() && interfaceName != "" {
|
||||||
|
configurator, err = platform.NewSystemdResolvedDNSConfigurator(interfaceName)
|
||||||
|
if err == nil {
|
||||||
|
logger.Info("Using systemd-resolved DNS configurator")
|
||||||
|
return setDNS(dnsProxy, configurator)
|
||||||
|
}
|
||||||
|
logger.Debug("systemd-resolved not available: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try NetworkManager (common on desktops)
|
||||||
|
if platform.IsNetworkManagerAvailable() && interfaceName != "" {
|
||||||
|
configurator, err = platform.NewNetworkManagerDNSConfigurator(interfaceName)
|
||||||
|
if err == nil {
|
||||||
|
logger.Info("Using NetworkManager DNS configurator")
|
||||||
|
return setDNS(dnsProxy, configurator)
|
||||||
|
}
|
||||||
|
logger.Debug("NetworkManager not available: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try resolvconf (common on older systems)
|
||||||
|
if platform.IsResolvconfAvailable() && interfaceName != "" {
|
||||||
|
configurator, err = platform.NewResolvconfDNSConfigurator(interfaceName)
|
||||||
|
if err == nil {
|
||||||
|
logger.Info("Using resolvconf DNS configurator")
|
||||||
|
return setDNS(dnsProxy, configurator)
|
||||||
|
}
|
||||||
|
logger.Debug("resolvconf not available: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fall back to direct file manipulation
|
||||||
|
configurator, err = platform.NewFileDNSConfigurator()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create file DNS configurator: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Using file-based DNS configurator")
|
||||||
|
return setDNS(dnsProxy, configurator)
|
||||||
|
}
|
||||||
|
|
||||||
|
// setDNS is a helper function to set DNS and log the results
|
||||||
|
func setDNS(dnsProxy *dns.DNSProxy, conf platform.DNSConfigurator) error {
|
||||||
|
// Get current DNS servers before changing
|
||||||
|
currentDNS, err := conf.GetCurrentDNS()
|
||||||
|
if err != nil {
|
||||||
|
logger.Warn("Could not get current DNS: %v", err)
|
||||||
|
} else {
|
||||||
|
logger.Info("Current DNS servers: %v", currentDNS)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set new DNS servers to point to our proxy
|
||||||
|
newDNS := []netip.Addr{
|
||||||
|
dnsProxy.GetProxyIP(),
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Setting DNS servers to: %v", newDNS)
|
||||||
|
originalDNS, err := conf.SetDNS(newDNS)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to set DNS: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Original DNS servers backed up: %v", originalDNS)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RestoreDNSOverride restores the original DNS configuration
|
||||||
|
func RestoreDNSOverride() error {
|
||||||
|
if configurator == nil {
|
||||||
|
logger.Debug("No DNS configurator to restore")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Restoring original DNS configuration")
|
||||||
|
if err := configurator.RestoreDNS(); err != nil {
|
||||||
|
return fmt.Errorf("failed to restore DNS: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("DNS configuration restored successfully")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
78
olm/dns_override_windows.go
Normal file
78
olm/dns_override_windows.go
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package olm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/netip"
|
||||||
|
|
||||||
|
"github.com/fosrl/newt/logger"
|
||||||
|
"github.com/fosrl/olm/dns"
|
||||||
|
platform "github.com/fosrl/olm/dns/platform"
|
||||||
|
)
|
||||||
|
|
||||||
|
// SetupDNSOverride configures the system DNS to use the DNS proxy on Windows
|
||||||
|
// Uses registry-based configuration (requires interface GUID)
|
||||||
|
func SetupDNSOverride(interfaceName string, dnsProxy *dns.DNSProxy) error {
|
||||||
|
if dnsProxy == nil {
|
||||||
|
return fmt.Errorf("DNS proxy is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
// On Windows, we need to get the interface GUID from the TUN device
|
||||||
|
// The interfaceName parameter is ignored on Windows
|
||||||
|
if tdev == nil {
|
||||||
|
return fmt.Errorf("TUN device is not available")
|
||||||
|
}
|
||||||
|
|
||||||
|
guid, err := GetInterfaceGUIDString(tdev)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get interface GUID: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Retrieved interface GUID: %s for interface name: %s", guid, interfaceName)
|
||||||
|
|
||||||
|
configurator, err = platform.NewWindowsDNSConfigurator(guid)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create Windows DNS configurator: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Using Windows registry DNS configurator for GUID: %s", guid)
|
||||||
|
|
||||||
|
// Get current DNS servers before changing
|
||||||
|
currentDNS, err := configurator.GetCurrentDNS()
|
||||||
|
if err != nil {
|
||||||
|
logger.Warn("Could not get current DNS: %v", err)
|
||||||
|
} else {
|
||||||
|
logger.Info("Current DNS servers: %v", currentDNS)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set new DNS servers to point to our proxy
|
||||||
|
newDNS := []netip.Addr{
|
||||||
|
dnsProxy.GetProxyIP(),
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Setting DNS servers to: %v", newDNS)
|
||||||
|
originalDNS, err := configurator.SetDNS(newDNS)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to set DNS: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Original DNS servers backed up: %v", originalDNS)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// RestoreDNSOverride restores the original DNS configuration
|
||||||
|
func RestoreDNSOverride() error {
|
||||||
|
if configurator == nil {
|
||||||
|
logger.Debug("No DNS configurator to restore")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("Restoring original DNS configuration")
|
||||||
|
if err := configurator.RestoreDNS(); err != nil {
|
||||||
|
return fmt.Errorf("failed to restore DNS: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("DNS configuration restored successfully")
|
||||||
|
return nil
|
||||||
|
}
|
||||||
15
olm/interface_guid_stub.go
Normal file
15
olm/interface_guid_stub.go
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
//go:build !windows
|
||||||
|
|
||||||
|
package olm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"golang.zx2c4.com/wireguard/tun"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetInterfaceGUIDString is only implemented for Windows
|
||||||
|
// This stub is provided for compilation on other platforms
|
||||||
|
func GetInterfaceGUIDString(tunDevice tun.Device) (string, error) {
|
||||||
|
return "", fmt.Errorf("GetInterfaceGUIDString is only supported on Windows")
|
||||||
|
}
|
||||||
69
olm/interface_guid_windows.go
Normal file
69
olm/interface_guid_windows.go
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
//go:build windows
|
||||||
|
|
||||||
|
package olm
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"unsafe"
|
||||||
|
|
||||||
|
"golang.org/x/sys/windows"
|
||||||
|
"golang.zx2c4.com/wireguard/tun"
|
||||||
|
)
|
||||||
|
|
||||||
|
// GetInterfaceGUIDString retrieves the GUID string for a Windows TUN interface
|
||||||
|
// This is required for registry-based DNS configuration on Windows
|
||||||
|
func GetInterfaceGUIDString(tunDevice tun.Device) (string, error) {
|
||||||
|
if tunDevice == nil {
|
||||||
|
return "", fmt.Errorf("TUN device is nil")
|
||||||
|
}
|
||||||
|
|
||||||
|
// The wireguard-go Windows TUN device has a LUID() method
|
||||||
|
// We need to use type assertion to access it
|
||||||
|
type nativeTun interface {
|
||||||
|
LUID() uint64
|
||||||
|
}
|
||||||
|
|
||||||
|
nativeDev, ok := tunDevice.(nativeTun)
|
||||||
|
if !ok {
|
||||||
|
return "", fmt.Errorf("TUN device does not support LUID retrieval (not a native Windows TUN device)")
|
||||||
|
}
|
||||||
|
|
||||||
|
luid := nativeDev.LUID()
|
||||||
|
|
||||||
|
// Convert LUID to GUID using Windows API
|
||||||
|
guid, err := luidToGUID(luid)
|
||||||
|
if err != nil {
|
||||||
|
return "", fmt.Errorf("failed to convert LUID to GUID: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return guid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// luidToGUID converts a Windows LUID (Locally Unique Identifier) to a GUID string
|
||||||
|
// using the Windows ConvertInterface* APIs
|
||||||
|
func luidToGUID(luid uint64) (string, error) {
|
||||||
|
var guid windows.GUID
|
||||||
|
|
||||||
|
// Load the iphlpapi.dll and get the ConvertInterfaceLuidToGuid function
|
||||||
|
iphlpapi := windows.NewLazySystemDLL("iphlpapi.dll")
|
||||||
|
convertLuidToGuid := iphlpapi.NewProc("ConvertInterfaceLuidToGuid")
|
||||||
|
|
||||||
|
// Call the Windows API
|
||||||
|
// NET_LUID is a 64-bit value on Windows
|
||||||
|
ret, _, err := convertLuidToGuid.Call(
|
||||||
|
uintptr(unsafe.Pointer(&luid)),
|
||||||
|
uintptr(unsafe.Pointer(&guid)),
|
||||||
|
)
|
||||||
|
|
||||||
|
if ret != 0 {
|
||||||
|
return "", fmt.Errorf("ConvertInterfaceLuidToGuid failed with code %d: %w", ret, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Format the GUID as a string with curly braces
|
||||||
|
guidStr := fmt.Sprintf("{%08X-%04X-%04X-%02X%02X-%02X%02X%02X%02X%02X%02X}",
|
||||||
|
guid.Data1, guid.Data2, guid.Data3,
|
||||||
|
guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3],
|
||||||
|
guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7])
|
||||||
|
|
||||||
|
return guidStr, nil
|
||||||
|
}
|
||||||
39
olm/olm.go
39
olm/olm.go
@@ -6,7 +6,6 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
|
||||||
"runtime"
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -577,35 +576,10 @@ func StartTunnel(config TunnelConfig) {
|
|||||||
|
|
||||||
peerMonitor.Start()
|
peerMonitor.Start()
|
||||||
|
|
||||||
configurator, err = platform.DetectBestConfigurator(interfaceName)
|
// Set up DNS override to use our DNS proxy
|
||||||
if err != nil {
|
if err := SetupDNSOverride(interfaceName, dnsProxy); err != nil {
|
||||||
log.Fatalf("Failed to detect DNS configurator: %v", err)
|
logger.Error("Failed to setup DNS override: %v", err)
|
||||||
}
|
return
|
||||||
|
|
||||||
fmt.Printf("Using DNS configurator: %s\n", configurator.Name())
|
|
||||||
|
|
||||||
// Get current DNS servers before changing
|
|
||||||
currentDNS, err := configurator.GetCurrentDNS()
|
|
||||||
if err != nil {
|
|
||||||
log.Printf("Warning: Could not get current DNS: %v", err)
|
|
||||||
} else {
|
|
||||||
fmt.Printf("Current DNS servers: %v\n", currentDNS)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set new DNS servers
|
|
||||||
newDNS := []netip.Addr{
|
|
||||||
dnsProxy.GetProxyIP(),
|
|
||||||
// netip.MustParseAddr("8.8.8.8"), // Google
|
|
||||||
}
|
|
||||||
|
|
||||||
fmt.Printf("Setting DNS servers to: %v\n", newDNS)
|
|
||||||
originalDNS, err := configurator.SetDNS(newDNS)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalf("Failed to set DNS: %v", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, addr := range originalDNS {
|
|
||||||
fmt.Printf("Original DNS server: %v\n", addr)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := dnsProxy.Start(); err != nil {
|
if err := dnsProxy.Start(); err != nil {
|
||||||
@@ -1202,6 +1176,11 @@ func StopTunnel() {
|
|||||||
|
|
||||||
Close()
|
Close()
|
||||||
|
|
||||||
|
// Restore original DNS configuration
|
||||||
|
if err := RestoreDNSOverride(); err != nil {
|
||||||
|
logger.Error("Failed to restore DNS: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
// Reset the connected state
|
// Reset the connected state
|
||||||
connected = false
|
connected = false
|
||||||
tunnelRunning = false
|
tunnelRunning = false
|
||||||
|
|||||||
Reference in New Issue
Block a user