3 files changed,
115 insertions(+),
43 deletions(-)
Author:
Oleksandr Smirnov
olexsmir@gmail.com
Committed at:
2026-04-19 12:31:39 +0300
Authored at:
2026-04-13 16:53:32 +0300
Change ID:
vusswnxosqrkynpqvqqrnonpozwwsuxk
Parent:
6fd1757
jump to
| A | dns-server/lookup.go |
| M | dns-server/main.go |
| A | dns-server/server.go |
A
dns-server/lookup.go
··· 1 +package main 2 + 3 +import ( 4 + "bytes" 5 + "fmt" 6 + "net" 7 +) 8 + 9 +const server = "8.8.8.8:53" 10 + 11 +func Lookup(qname string, qtype QueryType) (Packet, error) { 12 + conn, _ := net.Dial("udp", server) 13 + defer conn.Close() 14 + 15 + p := Packet{} 16 + p.Header.ID = 6666 17 + p.Header.RecursionDesired = true 18 + p.Questions = append(p.Questions, Question{ 19 + Name: qname, 20 + Type: qtype, 21 + Class: 1, // IN 22 + }) 23 + 24 + buf := &bytes.Buffer{} 25 + if err := p.Write(buf); err != nil { 26 + return Packet{}, fmt.Errorf("failed to write packet: %v", err) 27 + } 28 + 29 + if _, err := conn.Write(buf.Bytes()); err != nil { 30 + fmt.Printf("failed to write to connection: %v", err) 31 + } 32 + 33 + res := make([]byte, 512) 34 + n, err := conn.Read(res) 35 + if err != nil { 36 + fmt.Printf("failed to read from connection: %v", err) 37 + } 38 + 39 + return ParsePacket(res[:n]) 40 +}
M
dns-server/main.go
··· 1 1 package main 2 2 3 3 import ( 4 - "bytes" 5 - _ "embed" 6 4 "fmt" 7 5 "net" 6 + "os" 8 7 ) 9 8 10 9 func main() { 11 - qname := "olexsmir.xyz" 12 - server := "8.8.8.8:53" 13 - 14 - conn, _ := net.Dial("udp", server) 15 - defer conn.Close() 16 - 17 - p := Packet{} 18 - p.Header.ID = 6666 19 - p.Header.RecursionDesired = true 20 - p.Questions = append(p.Questions, Question{ 21 - Name: qname, 22 - Type: AType, 23 - Class: 1, // IN 24 - }) 25 - 26 - buf := &bytes.Buffer{} 27 - if err := p.Write(buf); err != nil { 28 - fmt.Printf("failed to write packet: %v", err) 29 - } 30 - 31 - if _, err := conn.Write(buf.Bytes()); err != nil { 32 - fmt.Printf("failed to write to connection: %v", err) 33 - } 34 - 35 - res := make([]byte, 512) 36 - n, err := conn.Read(res) 10 + addr, err := net.ResolveUDPAddr("udp", "0.0.0.0:2053") 37 11 if err != nil { 38 - fmt.Printf("failed to read from connection: %v", err) 12 + fmt.Printf("%v\n", err) 39 13 } 40 14 41 - resPack, err := ParsePacket(res[:n]) 15 + conn, err := net.ListenUDP("udp", addr) 42 16 if err != nil { 43 - fmt.Printf("failed to parse packet: %v", err) 17 + fmt.Printf("%v\n", err) 44 18 } 19 + defer conn.Close() 45 20 46 - fmt.Printf("%+v\n", resPack.Header) 47 - for _, q := range resPack.Questions { 48 - fmt.Printf("%+v\n", q) 49 - } 50 - for _, r := range resPack.Answers { 51 - fmt.Printf("%+v\n", r) 52 - } 53 - for _, r := range resPack.Authorities { 54 - fmt.Printf("%+v\n", r) 55 - } 56 - for _, r := range resPack.Resources { 57 - fmt.Printf("%+v\n", r) 21 + fmt.Println("Listening on :2053") 22 + for { 23 + if err := HandleQuery(conn); err != nil { 24 + fmt.Fprintf(os.Stderr, "error: %v\n", err) 25 + } 58 26 } 59 27 }
A
dns-server/server.go
··· 1 +package main 2 + 3 +import ( 4 + "bytes" 5 + "fmt" 6 + "net" 7 +) 8 + 9 +func HandleQuery(conn *net.UDPConn) error { 10 + buf := make([]byte, 512) 11 + n, src, err := conn.ReadFromUDP(buf) 12 + if err != nil { 13 + return err 14 + } 15 + 16 + request, err := ParsePacket(buf[:n]) 17 + if err != nil { 18 + return err 19 + } 20 + 21 + response := Packet{ 22 + Header: Header{ 23 + ID: request.Header.ID, 24 + RecursionDesired: true, 25 + RecursionAvailable: true, 26 + Response: true, 27 + }, 28 + } 29 + 30 + if len(request.Questions) == 0 { 31 + response.Header.Rescode = FORMERR 32 + } else { 33 + q := request.Questions[0] 34 + fmt.Printf("Received query: %+v\n", q) 35 + 36 + res, rerr := Lookup(q.Name, q.Type) 37 + if rerr != nil { 38 + response.Header.Rescode = SERVFAIL 39 + } else { 40 + response.Questions = append(response.Questions, q) 41 + response.Header.Rescode = res.Header.Rescode 42 + for _, rec := range res.Answers { 43 + fmt.Printf("Answer: %+v\n", rec) 44 + response.Answers = append(response.Answers, rec) 45 + } 46 + for _, rec := range res.Authorities { 47 + fmt.Printf("Authority: %+v\n", rec) 48 + response.Authorities = append(response.Authorities, rec) 49 + } 50 + for _, rec := range res.Resources { 51 + fmt.Printf("Resource: %+v\n", rec) 52 + response.Resources = append(response.Resources, rec) 53 + } 54 + } 55 + } 56 + 57 + resBuf := &bytes.Buffer{} 58 + if err = response.Write(resBuf); err != nil { 59 + return err 60 + } 61 + 62 + _, err = conn.WriteToUDP(resBuf.Bytes(), src) 63 + return err 64 +}