-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Encoding DNS Message Making request to name server Parsing Header and Question section Answer and additional sections parsing yet to include
- Loading branch information
Showing
10 changed files
with
376 additions
and
198 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
package core | ||
|
||
import "net" | ||
|
||
const MAX_PACKET_SIZE = 512 | ||
|
||
func QueryNameServer(server string, query []byte) ([]byte, error) { | ||
conn, err := net.Dial("udp", server) | ||
if err != nil { | ||
return nil, err | ||
} | ||
// Ensures that the connection is closed when the function completes, | ||
// whether it succeeds or fails. | ||
defer conn.Close() | ||
|
||
_, err = conn.Write(query) | ||
if err != nil { | ||
return nil, err | ||
} | ||
// Buffer to store the response | ||
response := make([]byte, MAX_PACKET_SIZE) | ||
n, err := conn.Read(response) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
return response[:n], nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
package dns | ||
|
||
import ( | ||
. "resolve-on-go/lib" | ||
"resolve-on-go/core" | ||
) | ||
|
||
func BuildMessage(domain string) ([]byte, error) { | ||
message := DNSMessage{ | ||
Header: NewDNSHeader(), Question: NewDNSQuestion(domain), | ||
} | ||
encodedMessage, err := message.Encode() | ||
if err != nil { | ||
return nil, err | ||
} | ||
return encodedMessage, nil | ||
} | ||
|
||
|
||
func Query(server string, query []byte) ([]byte, error){ | ||
return core.QueryNameServer(server, query) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package lib | ||
|
||
import ( | ||
"bytes" | ||
"encoding/binary" | ||
) | ||
|
||
const ( | ||
// Header Constants | ||
QR_QUERY = 0 | ||
QR_RESPONSE = 1 | ||
OPCODE_QUERY = 0 // Standard query | ||
OPCODE_IQUERY = 1 // Inverse query | ||
OPCODE_STATUS = 2 // Server status request | ||
RD = 1 // Recusion Desired | ||
AA = 0 // Authoritative Answer | ||
TC = 0 // Trucation | ||
RA = 0 // Recursion Available | ||
Z = 0 // Reserved for future use. Must be zero in all queries and responses. | ||
|
||
// Header response code types | ||
RCODE_NO_ERROR = 0 | ||
RCODE_FORMAT_ERROR = 1 | ||
RCODE_SERVER_FAILURE = 2 | ||
RCODE_NAME_ERROR = 3 | ||
RCODE_NOT_IMPLEMENTED = 4 | ||
RCODE_REFUSED = 5 | ||
) | ||
|
||
type DNSHeader struct { | ||
Id uint16 | ||
Flags uint16 | ||
QdCount uint16 // The number of entries in the question section. | ||
AnCount uint16 // The number of resource records in the answer section. | ||
NsCount uint16 // The number of name server resource records in the authority section. | ||
ArCount uint16 // The number of resource records in the additional section. | ||
} | ||
|
||
func (h *DNSHeader) Encode() ([]byte, error) { | ||
|
||
encodedHeader := new(bytes.Buffer) | ||
|
||
binary.Write(encodedHeader, binary.BigEndian, h.Id) | ||
binary.Write(encodedHeader, binary.BigEndian, h.Flags) | ||
binary.Write(encodedHeader, binary.BigEndian, h.QdCount) | ||
binary.Write(encodedHeader, binary.BigEndian, h.AnCount) | ||
binary.Write(encodedHeader, binary.BigEndian, h.NsCount) | ||
binary.Write(encodedHeader, binary.BigEndian, h.ArCount) | ||
|
||
return encodedHeader.Bytes(), nil | ||
} | ||
|
||
func DecodeHeader(data []byte) DNSHeader { | ||
var header DNSHeader | ||
reader := bytes.NewReader(data) | ||
|
||
binary.Read(reader, binary.BigEndian, &header.Id) | ||
binary.Read(reader, binary.BigEndian, &header.Flags) | ||
binary.Read(reader, binary.BigEndian, &header.QdCount) | ||
binary.Read(reader, binary.BigEndian, &header.AnCount) | ||
binary.Read(reader, binary.BigEndian, &header.NsCount) | ||
binary.Read(reader, binary.BigEndian, &header.ArCount) | ||
|
||
return header | ||
} | ||
|
||
|
||
func (h *DNSHeader) setFlags(qr, opcode, rd uint16) { | ||
h.Flags = (qr << 15) | (opcode << 11) | (rd << 8) | ||
} | ||
|
||
|
||
func NewDNSHeader() DNSHeader { | ||
header := DNSHeader{ | ||
Id: 1209, | ||
QdCount: 1, | ||
AnCount: 0, | ||
NsCount: 0, | ||
ArCount: 0, | ||
} | ||
header.setFlags(QR_QUERY, OPCODE_QUERY, RD) | ||
return header | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
package lib | ||
|
||
import ( | ||
"bytes" | ||
"encoding/binary" | ||
"resolve-on-go/util" | ||
) | ||
|
||
|
||
type DNSQuestion struct { | ||
Name []byte // A domain name represented as a sequence of labels. | ||
Type uint16 // The type of the query | ||
Class uint16 // The class of the query. | ||
} | ||
|
||
|
||
func (q *DNSQuestion) Encode() ([]byte, error) { | ||
buf := new(bytes.Buffer) | ||
|
||
buf.Write(q.Name) | ||
binary.Write(buf, binary.BigEndian, q.Type) | ||
binary.Write(buf, binary.BigEndian, q.Class) | ||
|
||
return buf.Bytes(), nil | ||
} | ||
|
||
func DecodeQuestion(data []byte) (DNSQuestion, error) { | ||
var question DNSQuestion | ||
reader := bytes.NewReader(data) | ||
|
||
// Decode the domain name | ||
var name []byte | ||
for { | ||
length, err := reader.ReadByte() | ||
if err != nil { | ||
return question, err | ||
} | ||
if length == 0 { | ||
break | ||
} | ||
|
||
label := make([]byte, length) | ||
if _, err := reader.Read(label); err != nil { | ||
return question, err | ||
} | ||
name = append(name, length) | ||
name = append(name, label...) | ||
} | ||
name = append(name, 0) // Append the null byte at the end of the name | ||
question.Name = name | ||
|
||
// Decode the type | ||
if err := binary.Read(reader, binary.BigEndian, &question.Type); err != nil { | ||
return question, err | ||
} | ||
// Decode the class | ||
if err := binary.Read(reader, binary.BigEndian, &question.Class); err != nil { | ||
return question, err | ||
} | ||
|
||
return question, nil | ||
} | ||
|
||
|
||
func NewDNSQuestion(domain string) DNSQuestion { | ||
encodedDomain := util.EncodeString(domain) | ||
return DNSQuestion{ | ||
Name: encodedDomain, | ||
Type: 1, // IPv4 | ||
Class: 1, | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
package main | ||
|
||
/* | ||
Copyright (c) 2024 s-bose7 | ||
Permission is hereby granted, free of charge, to any person obtaining a copy | ||
of this software and associated documentation files (the "Software"), to deal | ||
in the Software without restriction, including without limitation the rights | ||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
copies of the Software, and to permit persons to whom the Software is | ||
furnished to do so, subject to the following conditions: | ||
The above copyright notice and this permission notice shall be included in all | ||
copies or substantial portions of the Software. | ||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
SOFTWARE. | ||
*/ | ||
|
||
import ( | ||
"fmt" | ||
"resolve-on-go/util" | ||
"resolve-on-go/dns" | ||
"resolve-on-go/lib" | ||
) | ||
|
||
func printHeader(dnsHeader lib.DNSHeader) { | ||
fmt.Print("\n") | ||
fmt.Printf("Id: %d\n", dnsHeader.Id) | ||
fmt.Printf("Flag: %d\n", dnsHeader.Flags) | ||
fmt.Printf("QdCount: %d\n", dnsHeader.QdCount) | ||
fmt.Printf("AnCount: %d\n", dnsHeader.AnCount) | ||
fmt.Printf("NsCount: %d\n", dnsHeader.NsCount) | ||
fmt.Printf("ArCount: %d\n", dnsHeader.ArCount) | ||
} | ||
|
||
func printQuestion(dnsQuestion lib.DNSQuestion) { | ||
fmt.Print("\n") | ||
name, err := util.DecodeString(dnsQuestion.Name) | ||
if err != nil { | ||
return | ||
} | ||
fmt.Println("Name:", name) | ||
fmt.Printf("Type: %d\n", dnsQuestion.Type) | ||
fmt.Printf("Class: %d\n", dnsQuestion.Class) | ||
} | ||
|
||
func main() { | ||
|
||
domain := "dns.google.com" | ||
|
||
query, err := dns.BuildMessage(domain) | ||
if err != nil { | ||
util.PrintStackTrace("Error building query: ", err) | ||
return | ||
} | ||
util.PrintBytes("Encoded DNS Message:", query) | ||
|
||
server := "8.8.8.8:53" | ||
response, err := dns.Query(server, query) | ||
if err != nil { | ||
util.PrintStackTrace("Error Querying Google's DNS server: ", err) | ||
return | ||
} | ||
util.PrintBytes("\nGoogle's DNS server response:", response) | ||
|
||
resolvedMessage, err := lib.DecodeResponse(response) | ||
if err != nil { | ||
util.PrintStackTrace("Error parsing response: ", err) | ||
return | ||
} | ||
|
||
printHeader(resolvedMessage.Header) | ||
printQuestion(resolvedMessage.Question) | ||
} | ||
|
Oops, something went wrong.