Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UDP DNS: Bind to specific IP is not retained #724

Closed
jolakeng opened this issue Aug 14, 2018 · 7 comments
Closed

UDP DNS: Bind to specific IP is not retained #724

jolakeng opened this issue Aug 14, 2018 · 7 comments

Comments

@jolakeng
Copy link

jolakeng commented Aug 14, 2018

On MAC, we used the code

    dns.HandleFunc(".", handleDNSRequest)
    defer dns.HandleRemove(".")
    // start serverUDP
    serverUDP := &dns.Server{Addr: "127.0.0.1:53", Net: "udp"}
    go serverUDP.ListenAndServe()
    defer serverUDP.Shutdown()

It bound properly on specific IP and PORT as shown below:

udp4 0 0 127.0.0.1.53 .

But as soon as we write DNS response from handler function like

    msg.Authoritative = true
    domain := msg.Question[0].Name
    msg.Answer = append(msg.Answer, &dns.A{
        Hdr: dns.RR_Header{Name: domain, Rrtype: dns.TypeA, Class: dns.ClassINET, Ttl: 60},
        A:   net.ParseIP("1.2.3.4"),
    })
    w.WriteMsg(&msg)

Binding changes to as shown below:

udp4 0 0 *.53 .

This impacts other DNS server which is running on another interface.

I debugged the UDP DNS code and figured out that after the below line is executed the binding changes

conn.WriteMsgUDP(b, oob, session.raddr)

Please let me know any more information is required such that this great code can be useful in case we wanted to bind to specific IP address and retain the binding

cc: @fastest963

@miekg
Copy link
Owner

miekg commented Aug 16, 2018 via email

@jameshartig
Copy link
Collaborator

@jolakeng what IP address is the server receiving requests on? Is it 127.0.0.1? I assume so but maybe if it's receiving requests on something else and it tries to use a source IP that isn't 127.0.0.1 then Mac automatically changes the listen address? Seems insane, but that's all I can think of.

Can you try adding a print line to correctSource in udp.go and printing out the dst variable so we can see what it's trying to set the Src address to?

@jolakeng
Copy link
Author

This issue is reproducible with below sample UDP program, which I made similar to what is been used in DNS code

package main

import (
"fmt"
"golang.org/x/net/ipv4"
"net"
"os"
)

func changeOOB(oob []byte) []byte {
var dst net.IP
cm4 := new(ipv4.ControlMessage)
if cm4.Parse(oob) == nil {
dst = cm4.Dst
cm4.Dst = cm4.Src
cm4.Src = dst
oob = cm4.Marshal()
}
return oob
}

func checkError(err error) {
if err != nil {
fmt.Println("Error: ", err)
os.Exit(0)
}
}

func main() {
ServerAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:53")
checkError(err)
ServerConn, err := net.ListenUDP("udp", ServerAddr)
checkError(err)
fmt.Println("listening on :127.0.0.1:53")

    ipv4.NewPacketConn(ServerConn).SetControlMessage(ipv4.FlagDst|ipv4.FlagInterface, true)
    defer ServerConn.Close()

    b := make([]byte, 1024)

    for {
            oob := make([]byte, 40)
            _, oobn, _, raddr, err := ServerConn.ReadMsgUDP(b, oob)
            checkError(err)
            fmt.Println("recieve OOB:", oob[:oobn])
            newOOB := changeOOB(oob[:oobn])
            fmt.Println("new OOB:", newOOB, " raddr:", raddr)
            _, _, err = ServerConn.WriteMsgUDP(b, newOOB, raddr)
            checkError(err)
    }

}

Output :

listening on :127.0.0.1:53
recieve OOB: [24 0 0 0 0 0 0 0 26 0 0 0 1 0 0 0 0 0 0 0 127 0 0 1]
new OOB: [24 0 0 0 0 0 0 0 26 0 0 0 1 0 0 0 127 0 0 1 0 0 0 0] raddr: 127.0.0.1:57731

Bind before:

udp4 0 0 127.0.0.1.53 .
Bind after:

udp4 0 0 *.53 .

If don't give newOOB to WriteMsgUDP then binding is retained.
So WriteMsgUDP with OOB is causing the issue.

@jolakeng
Copy link
Author

jolakeng commented Aug 17, 2018 via email

@tmthrgd
Copy link
Collaborator

tmthrgd commented Aug 17, 2018

WriteMsgUDP ends up in the sendmsg system call. I can find no mention of any darwin-specific bugs related to this system call.

I'll try and do some more testing on a darwin system shortly, but I'm kind of stumped. It sounds like maybe it's a kernel bug. 🤷‍♂️

@ghost
Copy link

ghost commented Sep 19, 2018

Do you think this could be related to #743?

@miekg
Copy link
Owner

miekg commented Feb 21, 2019

I don't believe this is an issue with this library, as such I'm closing this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants