[client] Redirect dns forwarder port 5353 to new listening port 22054 (#4707)

- Port dnat changes from https://github.com/netbirdio/netbird/pull/4015 (nftables/iptables/userspace)
  - For userspace: rewrite the original port to the target port
  - Remember original destination port in conntrack
  - Rewrite the source port back to the original port for replies
- Redirect incoming port 5353 to 22054 (tcp/udp)
- Revert port changes based on the network map received from management
- Adjust tracer to show NAT stages
This commit is contained in:
Viktor Liu
2025-10-28 15:12:53 +01:00
committed by GitHub
parent 4545ab9a52
commit 404cab90ba
25 changed files with 1125 additions and 196 deletions

View File

@@ -21,8 +21,8 @@ import (
)
const (
dnsForwarderPort = 22054
oldForwarderPort = 5353
dnsForwarderPort = nbdns.ForwarderServerPort
oldForwarderPort = nbdns.ForwarderClientPort
)
const dnsForwarderPortMinVersion = "v0.59.0"
@@ -196,7 +196,7 @@ func validateDNSSettings(ctx context.Context, transaction store.Store, accountID
// If all peers have the required version, it returns the new well-known port (22054), otherwise returns 0.
func computeForwarderPort(peers []*nbpeer.Peer, requiredVersion string) int64 {
if len(peers) == 0 {
return oldForwarderPort
return int64(oldForwarderPort)
}
reqVer := semver.Canonical(requiredVersion)
@@ -211,17 +211,17 @@ func computeForwarderPort(peers []*nbpeer.Peer, requiredVersion string) int64 {
peerVersion := semver.Canonical("v" + peer.Meta.WtVersion)
if peerVersion == "" {
// If any peer doesn't have version info, return 0
return oldForwarderPort
return int64(oldForwarderPort)
}
// Compare versions
if semver.Compare(peerVersion, reqVer) < 0 {
return oldForwarderPort
return int64(oldForwarderPort)
}
}
// All peers have the required version or newer
return dnsForwarderPort
return int64(dnsForwarderPort)
}
// toProtocolDNSConfig converts nbdns.Config to proto.DNSConfig using the cache

View File

@@ -394,7 +394,7 @@ func BenchmarkToProtocolDNSConfig(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
toProtocolDNSConfig(testData, cache, dnsForwarderPort)
toProtocolDNSConfig(testData, cache, int64(dnsForwarderPort))
}
})
@@ -402,7 +402,7 @@ func BenchmarkToProtocolDNSConfig(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
cache := &DNSConfigCache{}
toProtocolDNSConfig(testData, cache, dnsForwarderPort)
toProtocolDNSConfig(testData, cache, int64(dnsForwarderPort))
}
})
}
@@ -455,13 +455,13 @@ func TestToProtocolDNSConfigWithCache(t *testing.T) {
}
// First run with config1
result1 := toProtocolDNSConfig(config1, &cache, dnsForwarderPort)
result1 := toProtocolDNSConfig(config1, &cache, int64(dnsForwarderPort))
// Second run with config2
result2 := toProtocolDNSConfig(config2, &cache, dnsForwarderPort)
result2 := toProtocolDNSConfig(config2, &cache, int64(dnsForwarderPort))
// Third run with config1 again
result3 := toProtocolDNSConfig(config1, &cache, dnsForwarderPort)
result3 := toProtocolDNSConfig(config1, &cache, int64(dnsForwarderPort))
// Verify that result1 and result3 are identical
if !reflect.DeepEqual(result1, result3) {
@@ -486,7 +486,7 @@ func TestComputeForwarderPort(t *testing.T) {
// Test with empty peers list
peers := []*nbpeer.Peer{}
result := computeForwarderPort(peers, "v0.59.0")
if result != oldForwarderPort {
if result != int64(oldForwarderPort) {
t.Errorf("Expected %d for empty peers list, got %d", oldForwarderPort, result)
}
@@ -504,7 +504,7 @@ func TestComputeForwarderPort(t *testing.T) {
},
}
result = computeForwarderPort(peers, "v0.59.0")
if result != oldForwarderPort {
if result != int64(oldForwarderPort) {
t.Errorf("Expected %d for peers with old versions, got %d", oldForwarderPort, result)
}
@@ -522,7 +522,7 @@ func TestComputeForwarderPort(t *testing.T) {
},
}
result = computeForwarderPort(peers, "v0.59.0")
if result != dnsForwarderPort {
if result != int64(dnsForwarderPort) {
t.Errorf("Expected %d for peers with new versions, got %d", dnsForwarderPort, result)
}
@@ -540,7 +540,7 @@ func TestComputeForwarderPort(t *testing.T) {
},
}
result = computeForwarderPort(peers, "v0.59.0")
if result != oldForwarderPort {
if result != int64(oldForwarderPort) {
t.Errorf("Expected %d for peers with mixed versions, got %d", oldForwarderPort, result)
}
@@ -553,7 +553,7 @@ func TestComputeForwarderPort(t *testing.T) {
},
}
result = computeForwarderPort(peers, "v0.59.0")
if result != oldForwarderPort {
if result != int64(oldForwarderPort) {
t.Errorf("Expected %d for peers with empty version, got %d", oldForwarderPort, result)
}
@@ -565,7 +565,7 @@ func TestComputeForwarderPort(t *testing.T) {
},
}
result = computeForwarderPort(peers, "v0.59.0")
if result == oldForwarderPort {
if result == int64(oldForwarderPort) {
t.Errorf("Expected %d for peers with dev version, got %d", dnsForwarderPort, result)
}
@@ -578,7 +578,7 @@ func TestComputeForwarderPort(t *testing.T) {
},
}
result = computeForwarderPort(peers, "v0.59.0")
if result != oldForwarderPort {
if result != int64(oldForwarderPort) {
t.Errorf("Expected %d for peers with unknown version, got %d", oldForwarderPort, result)
}
}

View File

@@ -1161,7 +1161,7 @@ func TestToSyncResponse(t *testing.T) {
}
dnsCache := &DNSConfigCache{}
accountSettings := &types.Settings{RoutingPeerDNSResolutionEnabled: true}
response := toSyncResponse(context.Background(), config, peer, turnRelayToken, turnRelayToken, networkMap, dnsName, checks, dnsCache, accountSettings, nil, []string{}, dnsForwarderPort)
response := toSyncResponse(context.Background(), config, peer, turnRelayToken, turnRelayToken, networkMap, dnsName, checks, dnsCache, accountSettings, nil, []string{}, int64(dnsForwarderPort))
assert.NotNil(t, response)
// assert peer config