mirror of
https://github.com/fosrl/olm.git
synced 2026-02-08 05:56:41 +00:00
committed by
Owen Schwartz
parent
f8dc134210
commit
7b7eae617a
@@ -34,18 +34,18 @@ type DNSProxy struct {
|
|||||||
ep *channel.Endpoint
|
ep *channel.Endpoint
|
||||||
proxyIP netip.Addr
|
proxyIP netip.Addr
|
||||||
upstreamDNS []string
|
upstreamDNS []string
|
||||||
tunnelDNS bool // Whether to tunnel DNS queries over WireGuard or to spit them out locally
|
tunnelDNS bool // Whether to tunnel DNS queries over WireGuard or to spit them out locally
|
||||||
mtu int
|
mtu int
|
||||||
tunDevice tun.Device // Direct reference to underlying TUN device for responses
|
tunDevice tun.Device // Direct reference to underlying TUN device for responses
|
||||||
middleDevice *device.MiddleDevice // Reference to MiddleDevice for packet filtering
|
middleDevice *device.MiddleDevice // Reference to MiddleDevice for packet filtering
|
||||||
recordStore *DNSRecordStore // Local DNS records
|
recordStore *DNSRecordStore // Local DNS records
|
||||||
|
|
||||||
// Tunnel DNS fields - for sending queries over WireGuard
|
// Tunnel DNS fields - for sending queries over WireGuard
|
||||||
tunnelIP netip.Addr // WireGuard interface IP (source for tunneled queries)
|
tunnelIP netip.Addr // WireGuard interface IP (source for tunneled queries)
|
||||||
tunnelStack *stack.Stack // Separate netstack for outbound tunnel queries
|
tunnelStack *stack.Stack // Separate netstack for outbound tunnel queries
|
||||||
tunnelEp *channel.Endpoint
|
tunnelEp *channel.Endpoint
|
||||||
tunnelActivePorts map[uint16]bool
|
tunnelActivePorts map[uint16]bool
|
||||||
tunnelPortsLock sync.Mutex
|
tunnelPortsLock sync.Mutex
|
||||||
|
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
|
|||||||
@@ -322,4 +322,4 @@ func matchWildcardInternal(pattern, domain string, pi, di int) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return matchWildcardInternal(pattern, domain, pi+1, di+1)
|
return matchWildcardInternal(pattern, domain, pi+1, di+1)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ func TestWildcardMatching(t *testing.T) {
|
|||||||
domain: "autoco.internal.",
|
domain: "autoco.internal.",
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Question mark wildcard tests
|
// Question mark wildcard tests
|
||||||
{
|
{
|
||||||
name: "host-0?.autoco.internal matches host-01.autoco.internal",
|
name: "host-0?.autoco.internal matches host-01.autoco.internal",
|
||||||
@@ -63,7 +63,7 @@ func TestWildcardMatching(t *testing.T) {
|
|||||||
domain: "host-012.autoco.internal.",
|
domain: "host-012.autoco.internal.",
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Combined wildcard tests
|
// Combined wildcard tests
|
||||||
{
|
{
|
||||||
name: "*.host-0?.autoco.internal matches sub.host-01.autoco.internal",
|
name: "*.host-0?.autoco.internal matches sub.host-01.autoco.internal",
|
||||||
@@ -83,7 +83,7 @@ func TestWildcardMatching(t *testing.T) {
|
|||||||
domain: "host-01.autoco.internal.",
|
domain: "host-01.autoco.internal.",
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Multiple asterisks
|
// Multiple asterisks
|
||||||
{
|
{
|
||||||
name: "*.*. autoco.internal matches any.thing.autoco.internal",
|
name: "*.*. autoco.internal matches any.thing.autoco.internal",
|
||||||
@@ -97,7 +97,7 @@ func TestWildcardMatching(t *testing.T) {
|
|||||||
domain: "single.autoco.internal.",
|
domain: "single.autoco.internal.",
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Asterisk in middle
|
// Asterisk in middle
|
||||||
{
|
{
|
||||||
name: "host-*.autoco.internal matches host-anything.autoco.internal",
|
name: "host-*.autoco.internal matches host-anything.autoco.internal",
|
||||||
@@ -111,7 +111,7 @@ func TestWildcardMatching(t *testing.T) {
|
|||||||
domain: "host-.autoco.internal.",
|
domain: "host-.autoco.internal.",
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Multiple question marks
|
// Multiple question marks
|
||||||
{
|
{
|
||||||
name: "host-??.autoco.internal matches host-01.autoco.internal",
|
name: "host-??.autoco.internal matches host-01.autoco.internal",
|
||||||
@@ -125,7 +125,7 @@ func TestWildcardMatching(t *testing.T) {
|
|||||||
domain: "host-1.autoco.internal.",
|
domain: "host-1.autoco.internal.",
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Exact match (no wildcards)
|
// Exact match (no wildcards)
|
||||||
{
|
{
|
||||||
name: "exact.autoco.internal matches exact.autoco.internal",
|
name: "exact.autoco.internal matches exact.autoco.internal",
|
||||||
@@ -139,7 +139,7 @@ func TestWildcardMatching(t *testing.T) {
|
|||||||
domain: "other.autoco.internal.",
|
domain: "other.autoco.internal.",
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
|
|
||||||
// Edge cases
|
// Edge cases
|
||||||
{
|
{
|
||||||
name: "* matches anything",
|
name: "* matches anything",
|
||||||
@@ -154,7 +154,7 @@ func TestWildcardMatching(t *testing.T) {
|
|||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, tt := range tests {
|
for _, tt := range tests {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
result := matchWildcard(tt.pattern, tt.domain)
|
result := matchWildcard(tt.pattern, tt.domain)
|
||||||
@@ -167,21 +167,21 @@ func TestWildcardMatching(t *testing.T) {
|
|||||||
|
|
||||||
func TestDNSRecordStoreWildcard(t *testing.T) {
|
func TestDNSRecordStoreWildcard(t *testing.T) {
|
||||||
store := NewDNSRecordStore()
|
store := NewDNSRecordStore()
|
||||||
|
|
||||||
// Add wildcard records
|
// Add wildcard records
|
||||||
wildcardIP := net.ParseIP("10.0.0.1")
|
wildcardIP := net.ParseIP("10.0.0.1")
|
||||||
err := store.AddRecord("*.autoco.internal", wildcardIP)
|
err := store.AddRecord("*.autoco.internal", wildcardIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to add wildcard record: %v", err)
|
t.Fatalf("Failed to add wildcard record: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add exact record
|
// Add exact record
|
||||||
exactIP := net.ParseIP("10.0.0.2")
|
exactIP := net.ParseIP("10.0.0.2")
|
||||||
err = store.AddRecord("exact.autoco.internal", exactIP)
|
err = store.AddRecord("exact.autoco.internal", exactIP)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to add exact record: %v", err)
|
t.Fatalf("Failed to add exact record: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test exact match takes precedence
|
// Test exact match takes precedence
|
||||||
ips := store.GetRecords("exact.autoco.internal.", RecordTypeA)
|
ips := store.GetRecords("exact.autoco.internal.", RecordTypeA)
|
||||||
if len(ips) != 1 {
|
if len(ips) != 1 {
|
||||||
@@ -190,7 +190,7 @@ func TestDNSRecordStoreWildcard(t *testing.T) {
|
|||||||
if !ips[0].Equal(exactIP) {
|
if !ips[0].Equal(exactIP) {
|
||||||
t.Errorf("Expected exact IP %v, got %v", exactIP, ips[0])
|
t.Errorf("Expected exact IP %v, got %v", exactIP, ips[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test wildcard match
|
// Test wildcard match
|
||||||
ips = store.GetRecords("host.autoco.internal.", RecordTypeA)
|
ips = store.GetRecords("host.autoco.internal.", RecordTypeA)
|
||||||
if len(ips) != 1 {
|
if len(ips) != 1 {
|
||||||
@@ -199,7 +199,7 @@ func TestDNSRecordStoreWildcard(t *testing.T) {
|
|||||||
if !ips[0].Equal(wildcardIP) {
|
if !ips[0].Equal(wildcardIP) {
|
||||||
t.Errorf("Expected wildcard IP %v, got %v", wildcardIP, ips[0])
|
t.Errorf("Expected wildcard IP %v, got %v", wildcardIP, ips[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test non-match (base domain)
|
// Test non-match (base domain)
|
||||||
ips = store.GetRecords("autoco.internal.", RecordTypeA)
|
ips = store.GetRecords("autoco.internal.", RecordTypeA)
|
||||||
if len(ips) != 0 {
|
if len(ips) != 0 {
|
||||||
@@ -209,14 +209,14 @@ func TestDNSRecordStoreWildcard(t *testing.T) {
|
|||||||
|
|
||||||
func TestDNSRecordStoreComplexWildcard(t *testing.T) {
|
func TestDNSRecordStoreComplexWildcard(t *testing.T) {
|
||||||
store := NewDNSRecordStore()
|
store := NewDNSRecordStore()
|
||||||
|
|
||||||
// Add complex wildcard pattern
|
// Add complex wildcard pattern
|
||||||
ip1 := net.ParseIP("10.0.0.1")
|
ip1 := net.ParseIP("10.0.0.1")
|
||||||
err := store.AddRecord("*.host-0?.autoco.internal", ip1)
|
err := store.AddRecord("*.host-0?.autoco.internal", ip1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to add wildcard record: %v", err)
|
t.Fatalf("Failed to add wildcard record: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test matching domain
|
// Test matching domain
|
||||||
ips := store.GetRecords("sub.host-01.autoco.internal.", RecordTypeA)
|
ips := store.GetRecords("sub.host-01.autoco.internal.", RecordTypeA)
|
||||||
if len(ips) != 1 {
|
if len(ips) != 1 {
|
||||||
@@ -225,13 +225,13 @@ func TestDNSRecordStoreComplexWildcard(t *testing.T) {
|
|||||||
if len(ips) > 0 && !ips[0].Equal(ip1) {
|
if len(ips) > 0 && !ips[0].Equal(ip1) {
|
||||||
t.Errorf("Expected IP %v, got %v", ip1, ips[0])
|
t.Errorf("Expected IP %v, got %v", ip1, ips[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test non-matching domain (missing prefix)
|
// Test non-matching domain (missing prefix)
|
||||||
ips = store.GetRecords("host-01.autoco.internal.", RecordTypeA)
|
ips = store.GetRecords("host-01.autoco.internal.", RecordTypeA)
|
||||||
if len(ips) != 0 {
|
if len(ips) != 0 {
|
||||||
t.Errorf("Expected 0 IPs for domain without prefix, got %d", len(ips))
|
t.Errorf("Expected 0 IPs for domain without prefix, got %d", len(ips))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test non-matching domain (wrong ? position)
|
// Test non-matching domain (wrong ? position)
|
||||||
ips = store.GetRecords("sub.host-012.autoco.internal.", RecordTypeA)
|
ips = store.GetRecords("sub.host-012.autoco.internal.", RecordTypeA)
|
||||||
if len(ips) != 0 {
|
if len(ips) != 0 {
|
||||||
@@ -241,23 +241,23 @@ func TestDNSRecordStoreComplexWildcard(t *testing.T) {
|
|||||||
|
|
||||||
func TestDNSRecordStoreRemoveWildcard(t *testing.T) {
|
func TestDNSRecordStoreRemoveWildcard(t *testing.T) {
|
||||||
store := NewDNSRecordStore()
|
store := NewDNSRecordStore()
|
||||||
|
|
||||||
// Add wildcard record
|
// Add wildcard record
|
||||||
ip := net.ParseIP("10.0.0.1")
|
ip := net.ParseIP("10.0.0.1")
|
||||||
err := store.AddRecord("*.autoco.internal", ip)
|
err := store.AddRecord("*.autoco.internal", ip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to add wildcard record: %v", err)
|
t.Fatalf("Failed to add wildcard record: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify it exists
|
// Verify it exists
|
||||||
ips := store.GetRecords("host.autoco.internal.", RecordTypeA)
|
ips := store.GetRecords("host.autoco.internal.", RecordTypeA)
|
||||||
if len(ips) != 1 {
|
if len(ips) != 1 {
|
||||||
t.Errorf("Expected 1 IP before removal, got %d", len(ips))
|
t.Errorf("Expected 1 IP before removal, got %d", len(ips))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove wildcard record
|
// Remove wildcard record
|
||||||
store.RemoveRecord("*.autoco.internal", nil)
|
store.RemoveRecord("*.autoco.internal", nil)
|
||||||
|
|
||||||
// Verify it's gone
|
// Verify it's gone
|
||||||
ips = store.GetRecords("host.autoco.internal.", RecordTypeA)
|
ips = store.GetRecords("host.autoco.internal.", RecordTypeA)
|
||||||
if len(ips) != 0 {
|
if len(ips) != 0 {
|
||||||
@@ -267,40 +267,40 @@ func TestDNSRecordStoreRemoveWildcard(t *testing.T) {
|
|||||||
|
|
||||||
func TestDNSRecordStoreMultipleWildcards(t *testing.T) {
|
func TestDNSRecordStoreMultipleWildcards(t *testing.T) {
|
||||||
store := NewDNSRecordStore()
|
store := NewDNSRecordStore()
|
||||||
|
|
||||||
// Add multiple wildcard patterns that don't overlap
|
// Add multiple wildcard patterns that don't overlap
|
||||||
ip1 := net.ParseIP("10.0.0.1")
|
ip1 := net.ParseIP("10.0.0.1")
|
||||||
ip2 := net.ParseIP("10.0.0.2")
|
ip2 := net.ParseIP("10.0.0.2")
|
||||||
ip3 := net.ParseIP("10.0.0.3")
|
ip3 := net.ParseIP("10.0.0.3")
|
||||||
|
|
||||||
err := store.AddRecord("*.prod.autoco.internal", ip1)
|
err := store.AddRecord("*.prod.autoco.internal", ip1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to add first wildcard: %v", err)
|
t.Fatalf("Failed to add first wildcard: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = store.AddRecord("*.dev.autoco.internal", ip2)
|
err = store.AddRecord("*.dev.autoco.internal", ip2)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to add second wildcard: %v", err)
|
t.Fatalf("Failed to add second wildcard: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a broader wildcard that matches both
|
// Add a broader wildcard that matches both
|
||||||
err = store.AddRecord("*.autoco.internal", ip3)
|
err = store.AddRecord("*.autoco.internal", ip3)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to add third wildcard: %v", err)
|
t.Fatalf("Failed to add third wildcard: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test domain matching only the prod pattern and the broad pattern
|
// Test domain matching only the prod pattern and the broad pattern
|
||||||
ips := store.GetRecords("host.prod.autoco.internal.", RecordTypeA)
|
ips := store.GetRecords("host.prod.autoco.internal.", RecordTypeA)
|
||||||
if len(ips) != 2 {
|
if len(ips) != 2 {
|
||||||
t.Errorf("Expected 2 IPs (prod + broad), got %d", len(ips))
|
t.Errorf("Expected 2 IPs (prod + broad), got %d", len(ips))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test domain matching only the dev pattern and the broad pattern
|
// Test domain matching only the dev pattern and the broad pattern
|
||||||
ips = store.GetRecords("service.dev.autoco.internal.", RecordTypeA)
|
ips = store.GetRecords("service.dev.autoco.internal.", RecordTypeA)
|
||||||
if len(ips) != 2 {
|
if len(ips) != 2 {
|
||||||
t.Errorf("Expected 2 IPs (dev + broad), got %d", len(ips))
|
t.Errorf("Expected 2 IPs (dev + broad), got %d", len(ips))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test domain matching only the broad pattern
|
// Test domain matching only the broad pattern
|
||||||
ips = store.GetRecords("host.test.autoco.internal.", RecordTypeA)
|
ips = store.GetRecords("host.test.autoco.internal.", RecordTypeA)
|
||||||
if len(ips) != 1 {
|
if len(ips) != 1 {
|
||||||
@@ -310,14 +310,14 @@ func TestDNSRecordStoreMultipleWildcards(t *testing.T) {
|
|||||||
|
|
||||||
func TestDNSRecordStoreIPv6Wildcard(t *testing.T) {
|
func TestDNSRecordStoreIPv6Wildcard(t *testing.T) {
|
||||||
store := NewDNSRecordStore()
|
store := NewDNSRecordStore()
|
||||||
|
|
||||||
// Add IPv6 wildcard record
|
// Add IPv6 wildcard record
|
||||||
ip := net.ParseIP("2001:db8::1")
|
ip := net.ParseIP("2001:db8::1")
|
||||||
err := store.AddRecord("*.autoco.internal", ip)
|
err := store.AddRecord("*.autoco.internal", ip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to add IPv6 wildcard record: %v", err)
|
t.Fatalf("Failed to add IPv6 wildcard record: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test wildcard match for IPv6
|
// Test wildcard match for IPv6
|
||||||
ips := store.GetRecords("host.autoco.internal.", RecordTypeAAAA)
|
ips := store.GetRecords("host.autoco.internal.", RecordTypeAAAA)
|
||||||
if len(ips) != 1 {
|
if len(ips) != 1 {
|
||||||
@@ -330,21 +330,21 @@ func TestDNSRecordStoreIPv6Wildcard(t *testing.T) {
|
|||||||
|
|
||||||
func TestHasRecordWildcard(t *testing.T) {
|
func TestHasRecordWildcard(t *testing.T) {
|
||||||
store := NewDNSRecordStore()
|
store := NewDNSRecordStore()
|
||||||
|
|
||||||
// Add wildcard record
|
// Add wildcard record
|
||||||
ip := net.ParseIP("10.0.0.1")
|
ip := net.ParseIP("10.0.0.1")
|
||||||
err := store.AddRecord("*.autoco.internal", ip)
|
err := store.AddRecord("*.autoco.internal", ip)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("Failed to add wildcard record: %v", err)
|
t.Fatalf("Failed to add wildcard record: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test HasRecord with wildcard match
|
// Test HasRecord with wildcard match
|
||||||
if !store.HasRecord("host.autoco.internal.", RecordTypeA) {
|
if !store.HasRecord("host.autoco.internal.", RecordTypeA) {
|
||||||
t.Error("Expected HasRecord to return true for wildcard match")
|
t.Error("Expected HasRecord to return true for wildcard match")
|
||||||
}
|
}
|
||||||
|
|
||||||
// Test HasRecord with non-match
|
// Test HasRecord with non-match
|
||||||
if store.HasRecord("autoco.internal.", RecordTypeA) {
|
if store.HasRecord("autoco.internal.", RecordTypeA) {
|
||||||
t.Error("Expected HasRecord to return false for base domain")
|
t.Error("Expected HasRecord to return false for base domain")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -416,4 +416,4 @@ func (d *DarwinDNSConfigurator) clearState() error {
|
|||||||
|
|
||||||
logger.Debug("Cleared DNS state file")
|
logger.Debug("Cleared DNS state file")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -811,7 +811,7 @@ func StartTunnel(config TunnelConfig) {
|
|||||||
Endpoint: handshakeData.ExitNode.Endpoint,
|
Endpoint: handshakeData.ExitNode.Endpoint,
|
||||||
RelayPort: relayPort,
|
RelayPort: relayPort,
|
||||||
PublicKey: handshakeData.ExitNode.PublicKey,
|
PublicKey: handshakeData.ExitNode.PublicKey,
|
||||||
SiteIds: []int{siteId},
|
SiteIds: []int{siteId},
|
||||||
}
|
}
|
||||||
|
|
||||||
added := holePunchManager.AddExitNode(exitNode)
|
added := holePunchManager.AddExitNode(exitNode)
|
||||||
|
|||||||
Reference in New Issue
Block a user