Skip to content

macos: UDP server rebinds to *:port after first query #941

@vavrusa

Description

@vavrusa

I was looking at an odd bug report and it looks like the PacketConn server always rebinds to any address after first query. Here's a simple program:

package main

import (
	"net"

	"github.com/miekg/dns"
)

func main() {
	pc, err := net.ListenPacket("udp", "127.0.0.1:1053")
	if err != nil {
		panic(err)
	}

	server := &dns.Server{PacketConn: pc}
	server.ActivateAndServe()
}

When I run it it binds to 127.0.0.1:1053 correctly:

$ go run bug.go &
$ lsof -p 10509 -n | grep UDP
bug     10509 vavrusa    3u    IPv4 0x52525d6e93c51cd9      0t0         UDP 127.0.0.1:remote-as

Cool. When I query it it answers, but the binding changes to *:1053:

$ kdig @127.0.0.1 -p 1053 +short
$ lsof -p 10509 -n | grep UDP
bug     10509 vavrusa    3u    IPv4 0x52525d6e93c51cd9      0t0         UDP *:remote-as

It also answers on any interface now:

$ kdig @192.168.86.110 -p 1053
;; ->>HEADER<<- opcode: QUERY; status: SERVFAIL; id: 16510
;; Flags: qr rd; QUERY: 1; ANSWER: 0; AUTHORITY: 0; ADDITIONAL: 0

;; QUESTION SECTION:
;; .                   		IN	NS

;; Received 17 B
;; Time 2019-03-17 20:03:06 PDT
;; From 192.168.86.110@1053(UDP) in 2.8 ms

I traced the problem to https://github.com/miekg/dns/blob/master/server.go#L326 which seems to have been added in #594. The problematic part is https://github.com/miekg/dns/blob/master/udp.go#L60:

// Try setting the flags for both families and ignore the errors unless they
// both error.
err6 := ipv6.NewPacketConn(conn).SetControlMessage(ipv6.FlagDst|ipv6.FlagInterface, true)
err4 := ipv4.NewPacketConn(conn).SetControlMessage(ipv4.FlagDst|ipv4.FlagInterface, true)

It does what it says (converts it into a raw socket). I'm not sure why was it added in the first place, but it is probably not what you want, as it opens up a DNS server using this library to any interface without user's control. Like CoreDNS:

$ cat Corefile
.:1053 {
    bind 127.0.0.1
    forward . 8.8.8.8:53
    log
}
$ coredns &
$ lsof -p $(ps ax | grep coredns | grep -v grep | awk '{print $1}') | grep UDP
coredns 16303 vavrusa    6u    IPv4 0x52525d6e9d492501      0t0         UDP localhost:remote-as
$ kdig @127.0.0.1 -p 1053 google.com +short
216.58.194.206
$ lsof -p $(ps ax | grep coredns | grep -v grep | awk '{print $1}') | grep UDP
coredns 16303 vavrusa    6u    IPv4 0x52525d6e9d492501      0t0         UDP *:remote-as

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions