tailscale/tailscale

NetworkManager IPv4 DNS addresses encoded with native endianness instead of network byte order

Summary

  • Context: The NetworkManager DNS integration code encodes IPv4 addresses as uint32 values for NetworkManager's DBus API.

  • Bug: The code uses binary.NativeEndian instead of binary.BigEndian to convert IPv4 addresses to uint32.

  • Actual vs. expected: On little-endian systems (x86/AMD64), IPv4 addresses are byte-swapped, causing NetworkManager to receive incorrect DNS server addresses instead of network byte order (big-endian) values as specified in its API documentation.

  • Impact: DNS queries are sent to incorrect IP addresses, causing resolution failures for users with custom DNS configurations on NetworkManager-managed Linux systems.

Code with bug

File: net/dns/nm.go

dnsv4 = append(
    dnsv4,
    binary.NativeEndian.Uint32(b[12:]), // <-- BUG 🔴 should be BigEndian for network byte order
)

NetworkManager's DBus API documentation at developer.gnome.org/NetworkManager/stable/settings-ipv4.html explicitly states that IPv4 addresses must be "in network byte order" (big-endian).

Example

On little-endian systems (x86/AMD64), the byte-swapping produces incorrect addresses:

Input IP

Bytes

Current (NativeEndian)

Expected (BigEndian)

NetworkManager Interprets As

192.168.1.1

0xc0 0xa8 0x01 0x01

0x0101A8C0 ❌

0xC0A80101 ✓

1.1.168.192 (wrong)

10.0.0.1

0x0a 0x00 0x00 0x01

0x0100000A ❌

0x0A000001 ✓

1.0.0.10 (wrong)

100.100.100.100

0x64 0x64 0x64 0x64

0x64646464 ✓

0x64646464 ✓

100.100.100.100 (correct)

The bug has remained undetected because the most commonly used Tailscale DNS server IP (100.100.100.100) is a palindrome that produces the same encoding regardless of byte order. Additionally, NetworkManager mode is less common than other DNS management modes like systemd-resolved.

Recommended fix

Change binary.NativeEndian to binary.BigEndian:

dnsv4 = append(
    dnsv4,
    binary.BigEndian.Uint32(b[12:]), // <-- FIX 🟢 ensures network byte order
)

This aligns with NetworkManager's API requirements and the consistent pattern used throughout the codebase for network protocol encoding (e.g., net/packet/ip4.go).