hatecomputers.club/hcdns/server_test.go

255 lines
5.5 KiB
Go
Raw Normal View History

2024-04-03 17:33:02 -04:00
package hcdns_test
2024-04-02 18:26:39 -04:00
import (
"database/sql"
2024-04-02 18:51:13 -04:00
"fmt"
"math/rand"
2024-04-02 18:26:39 -04:00
"os"
"sync"
"testing"
"git.hatecomputers.club/hatecomputers/hatecomputers.club/args"
"git.hatecomputers.club/hatecomputers/hatecomputers.club/database"
"git.hatecomputers.club/hatecomputers/hatecomputers.club/hcdns"
2024-04-02 18:51:13 -04:00
"git.hatecomputers.club/hatecomputers/hatecomputers.club/utils"
2024-04-02 18:26:39 -04:00
"github.com/miekg/dns"
)
2024-04-02 18:51:13 -04:00
func randomPort() int {
2024-04-03 17:33:02 -04:00
return rand.Intn(3000) + 5192
2024-04-02 18:51:13 -04:00
}
2024-04-02 18:26:39 -04:00
2024-04-02 22:26:24 -04:00
func setup() (*sql.DB, *dns.Server, *string, *sync.Mutex, func()) {
2024-04-02 18:51:13 -04:00
randomDb := utils.RandomId()
dnsPort := randomPort()
testDb := database.MakeConn(&randomDb)
2024-04-02 18:26:39 -04:00
database.Migrate(testDb)
testUser := &database.User{
ID: "test",
}
database.FindOrSaveUser(testDb, testUser)
2024-04-02 22:26:24 -04:00
waitLock := &sync.Mutex{}
2024-04-02 18:26:39 -04:00
server := hcdns.MakeServer(&args.Arguments{
DnsPort: dnsPort,
}, testDb)
2024-04-02 22:26:24 -04:00
server.NotifyStartedFunc = func() {
waitLock.Unlock()
}
waitLock.Lock()
2024-04-02 18:26:39 -04:00
go func() {
server.ListenAndServe()
}()
2024-04-02 22:26:24 -04:00
waitLock.Lock()
2024-04-02 18:26:39 -04:00
2024-04-02 18:51:13 -04:00
address := fmt.Sprintf("127.0.0.1:%d", dnsPort)
2024-04-02 22:26:24 -04:00
return testDb, server, &address, waitLock, func() {
server.Shutdown()
2024-04-02 18:51:13 -04:00
testDb.Close()
os.Remove(randomDb)
}
2024-04-02 18:26:39 -04:00
}
func TestWhenCNAMEIsResolved(t *testing.T) {
t.Log("TestWhenCNAMEIsResolved")
2024-04-02 22:26:24 -04:00
testDb, _, addr, lock, cleanup := setup()
2024-04-02 18:51:13 -04:00
defer cleanup()
2024-04-02 22:26:24 -04:00
defer lock.Unlock()
2024-04-02 18:26:39 -04:00
2024-04-03 17:33:02 -04:00
records := []*database.DNSRecord{
{
ID: "0",
UserID: "test",
Name: "cname.internal.example.com.",
Type: "CNAME",
Content: "next.internal.example.com.",
TTL: 300,
Internal: true,
}, {
ID: "1",
UserID: "test",
Name: "next.internal.example.com.",
Type: "CNAME",
Content: "res.example.com.",
TTL: 300,
Internal: true,
},
{
ID: "2",
UserID: "test",
Name: "res.example.com.",
Type: "A",
Content: "1.2.3.2",
TTL: 300,
Internal: true,
},
}
for _, record := range records {
database.SaveDNSRecord(testDb, record)
2024-04-02 18:26:39 -04:00
}
qtype := dns.TypeA
2024-04-03 17:33:02 -04:00
domain := dns.Fqdn("cname.internal.example.com.")
2024-04-02 22:26:24 -04:00
client := &dns.Client{}
message := &dns.Msg{}
2024-04-02 18:26:39 -04:00
message.SetQuestion(domain, qtype)
2024-04-02 18:51:13 -04:00
in, _, err := client.Exchange(message, *addr)
2024-04-02 18:26:39 -04:00
if err != nil {
t.Fatal(err)
}
2024-04-03 17:33:02 -04:00
if len(in.Answer) != 3 {
t.Fatalf("expected 3 answers, got %d", len(in.Answer))
2024-04-02 18:26:39 -04:00
}
2024-04-03 17:33:02 -04:00
for i, record := range records {
if in.Answer[i].Header().Name != record.Name {
t.Fatalf("expected %s, got %s", record.Name, in.Answer[i].Header().Name)
}
2024-04-02 18:26:39 -04:00
2024-04-03 17:33:02 -04:00
if in.Answer[i].Header().Rrtype != dns.StringToType[record.Type] {
t.Fatalf("expected %s, got %d", record.Type, in.Answer[i].Header().Rrtype)
}
2024-04-02 18:26:39 -04:00
2024-04-03 17:33:02 -04:00
if int(in.Answer[i].Header().Ttl) != record.TTL {
t.Fatalf("expected %d, got %d", record.TTL, in.Answer[i].Header().Ttl)
}
2024-04-02 18:26:39 -04:00
2024-04-03 17:33:02 -04:00
if !in.Authoritative {
t.Fatalf("expected authoritative response")
}
2024-04-02 18:26:39 -04:00
}
2024-04-03 17:33:02 -04:00
if in.Answer[2].(*dns.A).A.String() != "1.2.3.2" {
t.Fatalf("expected final record to be the A record with correct IP")
2024-04-02 18:26:39 -04:00
}
}
func TestWhenNoRecordNxDomain(t *testing.T) {
t.Log("TestWhenNoRecordNxDomain")
2024-04-02 22:26:24 -04:00
_, _, addr, lock, cleanup := setup()
2024-04-02 18:51:13 -04:00
defer cleanup()
2024-04-02 22:26:24 -04:00
defer lock.Unlock()
2024-04-02 18:26:39 -04:00
qtype := dns.TypeA
domain := dns.Fqdn("nonexistant.example.com.")
2024-04-02 22:26:24 -04:00
client := &dns.Client{}
message := &dns.Msg{}
2024-04-02 18:26:39 -04:00
message.SetQuestion(domain, qtype)
2024-04-02 18:51:13 -04:00
in, _, err := client.Exchange(message, *addr)
2024-04-02 18:26:39 -04:00
if err != nil {
t.Fatal(err)
}
if len(in.Answer) != 0 {
t.Fatalf("expected 0 answers, got %d", len(in.Answer))
}
if in.Rcode != dns.RcodeNameError {
t.Fatalf("expected NXDOMAIN, got %d", in.Rcode)
}
}
func TestWhenUnresolvingCNAME(t *testing.T) {
t.Log("TestWhenUnresolvingCNAME")
2024-04-02 22:26:24 -04:00
testDb, _, addr, lock, cleanup := setup()
2024-04-02 18:51:13 -04:00
defer cleanup()
2024-04-02 22:26:24 -04:00
defer lock.Unlock()
2024-04-02 18:26:39 -04:00
cname := &database.DNSRecord{
ID: "1",
UserID: "test",
Name: "cname.internal.example.com.",
Type: "CNAME",
Content: "nonexistant.example.com.",
TTL: 300,
Internal: true,
}
database.SaveDNSRecord(testDb, cname)
qtype := dns.TypeA
domain := dns.Fqdn(cname.Name)
2024-04-02 22:26:24 -04:00
client := &dns.Client{}
message := &dns.Msg{}
2024-04-02 18:26:39 -04:00
message.SetQuestion(domain, qtype)
2024-04-02 18:51:13 -04:00
in, _, err := client.Exchange(message, *addr)
2024-04-02 18:26:39 -04:00
if err != nil {
t.Fatal(err)
}
if len(in.Answer) != 1 {
t.Fatalf("expected 1 answer, got %d", len(in.Answer))
}
if !in.Authoritative {
t.Fatalf("expected authoritative response")
}
if in.Answer[0].Header().Name != cname.Name {
t.Fatalf("expected cname.internal.example.com., got %s", in.Answer[0].Header().Name)
}
if in.Answer[0].Header().Rrtype != dns.TypeCNAME {
t.Fatalf("expected CNAME, got %d", in.Answer[0].Header().Rrtype)
}
if in.Answer[0].(*dns.CNAME).Target != cname.Content {
t.Fatalf("expected nonexistant.example.com., got %s", in.Answer[0].(*dns.CNAME).Target)
}
if in.Rcode == dns.RcodeNameError {
t.Fatalf("expected no NXDOMAIN, got %d", in.Rcode)
}
}
func TestWhenUnresolvingCNAMEWithMaxDepth(t *testing.T) {
t.Log("TestWhenUnresolvingCNAMEWithMaxDepth")
2024-04-02 22:26:24 -04:00
testDb, _, addr, lock, cleanup := setup()
2024-04-02 18:51:13 -04:00
defer cleanup()
2024-04-02 22:26:24 -04:00
defer lock.Unlock()
2024-04-02 18:26:39 -04:00
cname := &database.DNSRecord{
ID: "1",
UserID: "test",
Name: "cname.internal.example.com.",
Type: "CNAME",
Content: "cname.internal.example.com.",
TTL: 300,
Internal: true,
}
database.SaveDNSRecord(testDb, cname)
qtype := dns.TypeA
domain := dns.Fqdn(cname.Name)
2024-04-02 22:26:24 -04:00
client := &dns.Client{}
message := &dns.Msg{}
2024-04-02 18:26:39 -04:00
message.SetQuestion(domain, qtype)
2024-04-02 18:51:13 -04:00
in, _, err := client.Exchange(message, *addr)
2024-04-02 18:26:39 -04:00
if err != nil {
t.Fatal(err)
}
if len(in.Answer) > 0 {
t.Fatalf("expected 0 answers, got %d", len(in.Answer))
}
2024-04-02 22:26:24 -04:00
2024-04-02 18:26:39 -04:00
if in.Rcode != dns.RcodeServerFailure {
t.Fatalf("expected SERVFAIL, got %d", in.Rcode)
}
}