Skip to content

Commit

Permalink
feat(netsim): add DNS-over-TCP to scenario (#42)
Browse files Browse the repository at this point in the history
We're now able to create scenarios featuring DNS-over-TCP servers.
  • Loading branch information
bassosimone authored Nov 27, 2024
1 parent a5c6348 commit d7affec
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 0 deletions.
62 changes: 62 additions & 0 deletions netsim/example_dns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,3 +73,65 @@ func Example_dnsOverUDP() {
// Output:
// 8.8.8.8
}

// This example shows how to use [netsim] to simulate a DNS
// server that listens for incoming requests over TCP.
func Example_dnsOverTCP() {
// Create a new scenario using the given directory to cache
// the certificates used by the simulated PKI
scenario := netsim.NewScenario("testdata")
defer scenario.Close()

// Create server stack emulating dns.google.
//
// This includes:
//
// 1. creating, attaching, and enabling routing for a server stack
//
// 2. registering the proper domain names and addresses
//
// 3. updating the PKI database to include the server's certificate
scenario.Attach(scenario.MustNewGoogleDNSStack())

// Create and attach the client stack.
clientStack := scenario.MustNewClientStack()
scenario.Attach(clientStack)

// Create a context with a watchdog timeout.
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()

// Create the client connection with the DNS server.
conn, err := clientStack.DialContext(ctx, "tcp", "8.8.8.8:53")
if err != nil {
log.Fatal(err)
}
defer conn.Close()

// Create the query to send
query := new(dns.Msg)
query.Id = dns.Id()
query.RecursionDesired = true
query.Question = []dns.Question{{
Name: "dns.google.",
Qtype: dns.TypeA,
Qclass: dns.ClassINET,
}}

// Perform the DNS round trip
clientDNS := &dns.Client{Net: "tcp"}
resp, _, err := clientDNS.ExchangeWithConnContext(ctx, query, &dns.Conn{Conn: conn})
if err != nil {
log.Fatal(err)
}

// Print the responses
for _, ans := range resp.Answer {
if a, ok := ans.(*dns.A); ok {
fmt.Printf("%s\n", a.A.String())
}
}

// Output:
// 8.8.8.8
}
3 changes: 3 additions & 0 deletions netsim/scenario.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,9 @@ func (s *Scenario) MustNewStack(config *StackConfig) *Stack {
if config.DNSOverUDPHandler != nil {
s.mustSetupDNSOverUDP(stack, config)
}
if config.DNSOverTCPHandler != nil {
s.mustSetupDNSOverTCP(stack, config)
}

// Start HTTP handlers.
if config.HTTPHandler != nil {
Expand Down
14 changes: 14 additions & 0 deletions netsim/setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@ type StackConfig struct {
// DNSOverUDPHandler optionally specifies a handler for DNS-over-UDP.
DNSOverUDPHandler DNSHandler

// DNSOverTCPHandler optionally specifies a handler for DNS-over-TCP.
DNSOverTCPHandler DNSHandler

// DomainNames contains the optional domain names associated with this stack.
//
// If there are associated domain names, we will configure the DNS and
Expand Down Expand Up @@ -107,6 +110,17 @@ func (s *Scenario) mustSetupDNSOverUDP(stack *Stack, cfg *StackConfig) {
s.pool.Add(server)
}

// mustSetupDNSOverTCP configures the DNS-over-TCP handler for the stack.
func (s *Scenario) mustSetupDNSOverTCP(stack *Stack, cfg *StackConfig) {
server := &dnscoretest.Server{
Listen: func(network, address string) (net.Listener, error) {
return stack.Listen(context.Background(), network, "[::]:53")
},
}
<-server.StartTCP(cfg.DNSOverTCPHandler)
s.pool.Add(server)
}

// mustSetupHTTPOverTCP configures the HTTP-over-TCP handler for the stack.
func (s *Scenario) mustSetupHTTPOverTCP(stack *Stack, cfg *StackConfig) {
listener := runtimex.Try1(stack.Listen(context.Background(), "tcp", "[::]:80"))
Expand Down
1 change: 1 addition & 0 deletions netsim/wellknown.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ func (s *Scenario) MustNewGoogleDNSStack() *Stack {
"8.8.8.8",
},
DNSOverUDPHandler: s.DNSHandler(),
DNSOverTCPHandler: s.DNSHandler(),
HTTPHandler: handler,
HTTPSHandler: handler,
})
Expand Down

0 comments on commit d7affec

Please sign in to comment.