Skip to content

net: LookupMX silently drops IP addresses #71860

@horkhe

Description

@horkhe

Go version

go version go1.24.0 darwin/amd64

Output of go env in your module/workspace:

AR='ar'
CC='clang'
CGO_CFLAGS='-O2 -g'
CGO_CPPFLAGS=''
CGO_CXXFLAGS='-O2 -g'
CGO_ENABLED='1'
CGO_FFLAGS='-O2 -g'
CGO_LDFLAGS='-O2 -g'
CXX='clang++'
GCCGO='gccgo'
GO111MODULE=''
GOAMD64='v1'
GOARCH='amd64'
GOAUTH='netrc'
GOBIN=''
GOCACHE='/Users/maxim/Library/Caches/go-build'
GOCACHEPROG=''
GODEBUG=''
GOENV='/Users/maxim/Library/Application Support/go/env'
GOEXE=''
GOEXPERIMENT=''
GOFIPS140='off'
GOFLAGS=''
GOGCCFLAGS='-fPIC -arch x86_64 -m64 -pthread -fno-caret-diagnostics -Qunused-arguments -fmessage-length=0 -ffile-prefix-map=/var/folders/vx/nqmhy3hs6z52j3k91cc254nm0000gn/T/go-build162216484=/tmp/go-build -gno-record-gcc-switches -fno-common'
GOHOSTARCH='amd64'
GOHOSTOS='darwin'
GOINSECURE=''
GOMOD='/dev/null'
GOMODCACHE='/Users/maxim/go/pkg/mod'
GONOPROXY='github.com/mailgun'
GONOSUMDB='github.com/mailgun'
GOOS='darwin'
GOPATH='/Users/maxim/go'
GOPRIVATE='github.com/mailgun'
GOPROXY='https://proxy.golang.org,direct'
GOROOT='/usr/local/go'
GOSUMDB='sum.golang.org'
GOTELEMETRY='local'
GOTELEMETRYDIR='/Users/maxim/Library/Application Support/go/telemetry'
GOTMPDIR=''
GOTOOLCHAIN='auto'
GOTOOLDIR='/usr/local/go/pkg/tool/darwin_amd64'
GOVCS=''
GOVERSION='go1.24.0'
GOWORK=''
PKG_CONFIG='pkg-config'

What did you do?

I call net.LookupMX(context.Background(), "emailct.net")

Where DNS MX records for emailct.net contain IP addresses, rather than domain name:

> dig MX emailct.net

;; ANSWER SECTION:
emailct.net.		14400	IN	MX	100 172.96.185.166.
emailct.net.		14400	IN	MX	10 172.96.185.166.
emailct.net.		14400	IN	MX	1 172.96.185.166.
emailct.net.		14400	IN	MX	1000 172.96.185.166.

What did you see happen?

The call returns an empty slice of DNS records and &DNSError{Err: errMalformedDNSRecordsDetail, Name: "emailct.net"} error

What did you expect to see?

The returned slice should contain net.MX records with IP addresses.

So net.LookupMX silently drops MX records that contain an IP address, rather than a host name. According to https://datatracker.ietf.org/doc/html/rfc1035#section-3.3.9 the content of MX record must be a domain name, so supposedly the method logic is justified, BUT we live in a real world that does not always follow the RFC to the letter. We at mailgun.com deliver tens of thousands of emails per day to hosts that have IP addresses in their MX records.

Fist we stumbled up on that issue when we migrated our application from Python to Go a few years ago. But discovered that we can just use lower level net.lookupMX that does not sanitise retrieved MX records via the go:linkname hack. But now the hack is being taken away and to upgrade to the new Go versions we will probably end up vendoring entire net.Resolver, that we obviously do not want to do. We see that either the net.LookupMX could be updated to allow IP addresses, or annotate it with go:linkname. I personally think that allowing IP addresses is a better solution because it acknowledges the reality, rather then trying to enforce the ideal view of the world.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions