-5

I had problems using codeberg.org/miekg/dns. When the server starts and the client requests a DNS message, the client will output an i/o timeout. I have been investigating for a long time, but still haven't found a solution. The AI analysis indicates that the windows firewall has blocked tcp. This is the server code:

package main

import (
    "context"
    "fmt"
    "log"
    "net"

    "codeberg.org/miekg/dns"
    "codeberg.org/miekg/dns/dnsutil"
)

func main() {
    handleTCP("tcp")
    select {}
}
func handleTCP(net string) {
    go func() {
        ds := dns.NewServer()
        ds.Addr = ":6553"
        ds.Net = net
        ds.Handler = dns.HandlerFunc(handleRequest)
        if err := ds.ListenAndServe(); err != nil {
            log.Fatalf("Failed to start UDP server: %v", err)
        }
    }()
    log.Println("DNS server started on TCP :53")
}

func handleRequest(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) {
    m := new(dns.Msg)
    // dnsutil.SetReply(m, r)
    fmt.Printf("%#v\n", r.Question[0])
    name, t := dnsutil.Question(r)
    if len(r.Question) > 0 && t == dns.TypeA {
        mx := &dns.A{Hdr: dns.Header{Name: name, Class: dns.ClassINET}, A: net.IPv4(192, 168, 1, 1)}
        m.Answer = append(m.Answer, mx)
    }
    if err := m.Pack(); err != nil {
        log.Fatalf("Failed to pack DNS response: %v", err)
    }
    code, err := w.Write(m.Data)
    if err != nil {
        log.Fatalf("Failed to write DNS response: %v", err)
    }
    log.Println("write bytes : ", code)
}

This is the client code:

package main

import (
    "context"
    "fmt"

    "codeberg.org/miekg/dns"
    "codeberg.org/miekg/dns/dnsutil"
)

func main() {
    ctx := context.Background()
    m := new(dns.Msg)
    dnsutil.SetQuestion(m, "miek.nl.", dns.TypeA)
    m.Pack()

    c := new(dns.Client)
    resp, rtt, err := c.Exchange(ctx, m, "tcp", "127.0.0.1:6553")
    if err != nil {
        fmt.Println(err) // !!! writeto tcp 127.0.0.1:50714->127.0.0.1:6553: read tcp 127.0.0.1:50714->127.0.0.1:6553: i/o timeout
        return
    }
    fmt.Println(rtt)
    fmt.Println(resp.Answer)
}

1 Answer 1

0

You're not returning a complete TCP DNS response, so the client is waiting for more data. You need to set the full response headers, which you can do with the commented out dnsutil.SetReply. The response should then be written with WriteTo method, because there is more to a TCP response than simply returning the packed message bytes.

func handleRequest(ctx context.Context, w dns.ResponseWriter, r *dns.Msg) {
    m := new(dns.Msg)
    dnsutil.SetReply(m, r)
    log.Printf("%#v\n", r.Question[0])
    name, t := dnsutil.Question(r)
    if len(r.Question) > 0 && t == dns.TypeA {
        mx := &dns.A{Hdr: dns.Header{Name: name, Class: dns.ClassINET}, A: net.IPv4(192, 168, 1, 1)}
        m.Answer = append(m.Answer, mx)
    }
    code, err := m.WriteTo(w)
    if err != nil {
        log.Fatalf("Failed to write DNS response: %v", err)
    }
    log.Println("write bytes : ", code)
}
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.