programs for edns, svcb, https support measurement
This commit is contained in:
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
||||
*.log
|
||||
12
go.mod
Normal file
12
go.mod
Normal file
@@ -0,0 +1,12 @@
|
||||
module edns_svcb
|
||||
|
||||
go 1.20
|
||||
|
||||
require github.com/miekg/dns v1.1.58
|
||||
|
||||
require (
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/net v0.20.0 // indirect
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
golang.org/x/tools v0.17.0 // indirect
|
||||
)
|
||||
11
go.sum
Normal file
11
go.sum
Normal file
@@ -0,0 +1,11 @@
|
||||
github.com/miekg/dns v1.1.58 h1:ca2Hdkz+cDg/7eNF6V56jjzuZ4aCAE+DbVkILdQWG/4=
|
||||
github.com/miekg/dns v1.1.58/go.mod h1:Ypv+3b/KadlvW9vJfXOTf300O4UqaHFzFCuHz+rPkBY=
|
||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo=
|
||||
golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU=
|
||||
golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/tools v0.17.0 h1:FvmRgNOcs3kOa+T20R1uhfP9F6HgG2mfxDv1vrx1Htc=
|
||||
golang.org/x/tools v0.17.0/go.mod h1:xsh6VxdV005rRVaS6SSAf9oiAqljS7UZUacMZ8Bnsps=
|
||||
38
main.go
Normal file
38
main.go
Normal file
@@ -0,0 +1,38 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"edns_svcb/method"
|
||||
"edns_svcb/utils"
|
||||
"flag"
|
||||
"log"
|
||||
"os"
|
||||
"sync"
|
||||
"time"
|
||||
)
|
||||
|
||||
func main() {
|
||||
var input_file string
|
||||
flag.StringVar(&input_file, "input", "", "input file name")
|
||||
flag.Parse()
|
||||
input_pool := make(chan string, 500)
|
||||
result_pool := make(chan method.CombinedResult)
|
||||
var test_tasks sync.WaitGroup
|
||||
var process_tasks sync.WaitGroup
|
||||
|
||||
logfilename := "test/" + time.Now().Format("2006-01-02_15-04-05") + ".log"
|
||||
logfile, err := os.OpenFile(logfilename, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to create log file: ", err)
|
||||
}
|
||||
defer logfile.Close()
|
||||
logger := log.New(logfile, "", log.LstdFlags)
|
||||
|
||||
go utils.RetrieveLines(input_pool, input_file)
|
||||
method.CombinedMeasurement(input_pool, result_pool, 500, &test_tasks, logger)
|
||||
process_tasks.Add(1)
|
||||
go method.CombinedResultProcess(result_pool, &process_tasks)
|
||||
test_tasks.Wait()
|
||||
close(result_pool)
|
||||
process_tasks.Wait()
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
123
method/combined.go
Normal file
123
method/combined.go
Normal file
@@ -0,0 +1,123 @@
|
||||
package method
|
||||
|
||||
import (
|
||||
"edns_svcb/utils"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
type CombinedResult struct {
|
||||
Alive bool
|
||||
EDNSSupport bool
|
||||
SVCBSupport bool
|
||||
HTTPSSupport bool
|
||||
Err error
|
||||
}
|
||||
|
||||
func CombinedMeasurement(ip_pool chan string, result_pool chan CombinedResult, routine_num int, wg *sync.WaitGroup, logger *log.Logger) {
|
||||
for i := 0; i < routine_num; i++ {
|
||||
wg.Add(1)
|
||||
go CombinedTestRoutine(ip_pool, result_pool, wg, logger)
|
||||
}
|
||||
}
|
||||
|
||||
func CombinedTestRoutine(ip_pool chan string, result_pool chan CombinedResult, wg *sync.WaitGroup, logger *log.Logger) {
|
||||
for {
|
||||
if ip, ok := <-ip_pool; ok {
|
||||
addr := ip + ":53"
|
||||
res := CombinedTest(addr)
|
||||
result_pool <- res
|
||||
if res.Err != nil {
|
||||
logger.Printf("%v : failed ( %v )", ip, res.Err)
|
||||
} else {
|
||||
logger.Printf("%v : alive %v edns %v svcb %v https %v", ip, res.Alive, res.EDNSSupport, res.SVCBSupport, res.HTTPSSupport)
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
func CombinedTest(addr string) CombinedResult {
|
||||
result := CombinedResult{}
|
||||
_, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: "www.example.com", RD: true})
|
||||
if err != nil {
|
||||
return CombinedResult{Err: err}
|
||||
}
|
||||
result.Alive = true
|
||||
|
||||
//edns support
|
||||
res, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: "www.example.com", EDNS: true, RD: true})
|
||||
if err == nil {
|
||||
if len(res.Extra) > 0 {
|
||||
if _, ok := res.Extra[0].(*dns.OPT); ok {
|
||||
result.EDNSSupport = true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result.Err = err
|
||||
return result
|
||||
}
|
||||
|
||||
// svcb support
|
||||
res, err = utils.DNSQuery(addr, utils.DNSOptions{Domain: "_dns.resolver.arpa", Qtype: dns.TypeSVCB, RD: true})
|
||||
if err == nil {
|
||||
if len(res.Answer) > 0 {
|
||||
if _, ok := res.Answer[0].(*dns.SVCB); ok {
|
||||
result.SVCBSupport = true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result.Err = err
|
||||
return result
|
||||
}
|
||||
|
||||
// https support
|
||||
res, err = utils.DNSQuery(addr, utils.DNSOptions{Domain: "blog.cloudflare.com", Qtype: dns.TypeHTTPS, RD: true})
|
||||
if err == nil {
|
||||
if len(res.Answer) > 0 {
|
||||
if _, ok := res.Answer[0].(*dns.HTTPS); ok {
|
||||
result.HTTPSSupport = true
|
||||
}
|
||||
}
|
||||
} else {
|
||||
result.Err = err
|
||||
return result
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func CombinedResultProcess(result_pool chan CombinedResult, wg *sync.WaitGroup) {
|
||||
alive_cnt := 0
|
||||
edns_cnt := 0
|
||||
svcb_cnt := 0
|
||||
https_cnt := 0
|
||||
for {
|
||||
if res, ok := <-result_pool; ok {
|
||||
if res.Err != nil {
|
||||
continue
|
||||
}
|
||||
if res.Alive {
|
||||
alive_cnt++
|
||||
}
|
||||
if res.EDNSSupport {
|
||||
edns_cnt++
|
||||
}
|
||||
if res.SVCBSupport {
|
||||
svcb_cnt++
|
||||
}
|
||||
if res.HTTPSSupport {
|
||||
https_cnt++
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
fmt.Printf("EDNS support Test: alive %v edns %v svcb %v https %v\n", alive_cnt, edns_cnt, svcb_cnt, https_cnt)
|
||||
wg.Done()
|
||||
}
|
||||
76
method/edns.go
Normal file
76
method/edns.go
Normal file
@@ -0,0 +1,76 @@
|
||||
package method
|
||||
|
||||
import (
|
||||
"edns_svcb/utils"
|
||||
"fmt"
|
||||
"log"
|
||||
"sync"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
type TestResult struct {
|
||||
Alive bool
|
||||
Support bool
|
||||
Err error
|
||||
}
|
||||
|
||||
func EDNSSupportMeasurement(ip_pool chan string, result_pool chan TestResult, routine_num int, wg *sync.WaitGroup, logger *log.Logger) {
|
||||
for i := 0; i < routine_num; i++ {
|
||||
wg.Add(1)
|
||||
go EDNSSupportTestRoutine(ip_pool, result_pool, wg, logger)
|
||||
}
|
||||
}
|
||||
|
||||
func EDNSSupportTestRoutine(ip_pool chan string, result_pool chan TestResult, wg *sync.WaitGroup, logger *log.Logger) {
|
||||
for {
|
||||
if ip, ok := <-ip_pool; ok {
|
||||
addr := ip + ":53"
|
||||
res := EDNSSupportTest(addr)
|
||||
result_pool <- res
|
||||
if res.Err != nil {
|
||||
logger.Printf("%v : failed ( %v )", ip, res.Err)
|
||||
} else {
|
||||
logger.Printf("%v : alive %v support %v", ip, res.Alive, res.Support)
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
wg.Done()
|
||||
}
|
||||
|
||||
func EDNSSupportTest(addr string) TestResult {
|
||||
_, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: "www.example.net", RD: true})
|
||||
if err != nil {
|
||||
return TestResult{Err: err}
|
||||
}
|
||||
res, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: "www.example.net", EDNS: true, RD: true})
|
||||
if err == nil {
|
||||
if len(res.Extra) == 1 {
|
||||
if _, ok := res.Extra[0].(*dns.OPT); ok {
|
||||
return TestResult{Alive: true, Support: true}
|
||||
}
|
||||
}
|
||||
}
|
||||
return TestResult{Alive: true}
|
||||
}
|
||||
|
||||
func EDNSSupportResultProcess(result_pool chan TestResult, wg *sync.WaitGroup) {
|
||||
alive_cnt := 0
|
||||
valid_cnt := 0
|
||||
for {
|
||||
if res, ok := <-result_pool; ok {
|
||||
if res.Alive {
|
||||
alive_cnt++
|
||||
}
|
||||
if res.Support {
|
||||
valid_cnt++
|
||||
}
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
fmt.Printf("EDNS support Test: alive %v support %v\n", alive_cnt, valid_cnt)
|
||||
wg.Done()
|
||||
}
|
||||
63
method/svcb.go
Normal file
63
method/svcb.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package method
|
||||
|
||||
import (
|
||||
"edns_svcb/utils"
|
||||
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
func HTTPSSupportTest(addr string) TestResult {
|
||||
_, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: "www.example.net", RD: true})
|
||||
if err != nil {
|
||||
return TestResult{Err: err}
|
||||
}
|
||||
res, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: "blog.cloudflare.com", Qtype: dns.TypeHTTPS, RD: true})
|
||||
if err == nil {
|
||||
if len(res.Answer) == 1 {
|
||||
if _, ok := res.Extra[0].(*dns.HTTPS); ok {
|
||||
return TestResult{Alive: true, Support: true}
|
||||
}
|
||||
}
|
||||
}
|
||||
return TestResult{Alive: true}
|
||||
}
|
||||
|
||||
func SVCBSupportTest(addr string) TestResult {
|
||||
_, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: "www.example.net", RD: true})
|
||||
if err != nil {
|
||||
return TestResult{Err: err}
|
||||
}
|
||||
res, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: "blog.cloudflare.com", Qtype: dns.TypeSVCB, RD: true})
|
||||
if err == nil {
|
||||
if len(res.Answer) == 1 {
|
||||
if _, ok := res.Extra[0].(*dns.SVCB); ok {
|
||||
return TestResult{Alive: true, Support: true}
|
||||
}
|
||||
}
|
||||
}
|
||||
return TestResult{Alive: true}
|
||||
}
|
||||
|
||||
func HTTPSRecordTest(addr, domain string) bool {
|
||||
res, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: domain, Qtype: dns.TypeHTTPS, RD: true})
|
||||
if err == nil {
|
||||
if len(res.Answer) > 0 {
|
||||
if _, ok := res.Answer[0].(*dns.HTTPS); ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func SVCBRecordTest(addr, domain string) bool {
|
||||
res, err := utils.DNSQuery(addr, utils.DNSOptions{Domain: domain, Qtype: dns.TypeSVCB, RD: true})
|
||||
if err == nil {
|
||||
if len(res.Answer) > 0 {
|
||||
if _, ok := res.Answer[0].(*dns.SVCB); ok {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
100
test/test-input
Normal file
100
test/test-input
Normal file
@@ -0,0 +1,100 @@
|
||||
1.0.0.1
|
||||
1.0.0.2
|
||||
1.0.0.3
|
||||
1.0.0.19
|
||||
1.0.66.192
|
||||
1.0.72.68
|
||||
1.0.77.169
|
||||
1.0.79.90
|
||||
1.0.81.135
|
||||
1.0.84.117
|
||||
1.0.91.59
|
||||
1.0.91.149
|
||||
1.0.97.194
|
||||
1.0.103.132
|
||||
1.0.106.125
|
||||
1.0.123.53
|
||||
1.0.141.2
|
||||
1.0.141.7
|
||||
1.0.141.23
|
||||
1.0.141.31
|
||||
1.0.141.32
|
||||
1.0.141.36
|
||||
1.0.141.46
|
||||
1.0.141.49
|
||||
1.0.141.54
|
||||
1.0.141.55
|
||||
1.0.141.59
|
||||
1.0.141.62
|
||||
1.0.141.64
|
||||
1.0.141.67
|
||||
1.0.141.69
|
||||
1.0.141.72
|
||||
1.0.141.75
|
||||
1.0.141.76
|
||||
1.0.141.77
|
||||
1.0.141.79
|
||||
1.0.141.85
|
||||
1.0.141.86
|
||||
1.0.141.92
|
||||
1.0.141.101
|
||||
1.0.141.103
|
||||
1.0.141.110
|
||||
1.0.141.114
|
||||
1.0.141.117
|
||||
1.0.141.126
|
||||
1.0.141.135
|
||||
1.0.141.143
|
||||
1.0.141.145
|
||||
1.0.141.152
|
||||
1.0.141.164
|
||||
1.0.141.167
|
||||
1.0.141.174
|
||||
1.0.141.177
|
||||
1.0.141.179
|
||||
1.0.141.180
|
||||
1.0.141.191
|
||||
1.0.141.203
|
||||
1.0.141.204
|
||||
1.0.141.211
|
||||
1.0.141.223
|
||||
1.0.141.238
|
||||
1.0.141.242
|
||||
1.0.141.244
|
||||
1.0.141.247
|
||||
1.0.141.250
|
||||
1.0.141.252
|
||||
1.0.141.253
|
||||
1.0.144.8
|
||||
1.0.144.27
|
||||
1.0.144.34
|
||||
1.0.144.36
|
||||
1.0.144.38
|
||||
1.0.144.47
|
||||
1.0.144.48
|
||||
1.0.144.50
|
||||
1.0.144.51
|
||||
1.0.144.52
|
||||
1.0.144.55
|
||||
1.0.144.73
|
||||
1.0.144.74
|
||||
1.0.144.78
|
||||
1.0.144.99
|
||||
1.0.144.112
|
||||
1.0.144.127
|
||||
1.0.144.130
|
||||
1.0.144.150
|
||||
1.0.144.164
|
||||
1.0.144.167
|
||||
1.0.144.172
|
||||
1.0.144.177
|
||||
1.0.144.178
|
||||
1.0.144.181
|
||||
1.0.144.182
|
||||
1.0.144.183
|
||||
1.0.144.186
|
||||
1.0.144.193
|
||||
1.0.144.197
|
||||
1.0.144.206
|
||||
1.0.144.207
|
||||
1.0.144.224
|
||||
62
utils/dns_utils.go
Normal file
62
utils/dns_utils.go
Normal file
@@ -0,0 +1,62 @@
|
||||
// dns utils
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/miekg/dns"
|
||||
)
|
||||
|
||||
type DNSOptions struct {
|
||||
Domain string
|
||||
RD bool
|
||||
Qclass uint16
|
||||
Qtype uint16
|
||||
EDNS bool
|
||||
}
|
||||
|
||||
// build the question section of a dns packet
|
||||
func questionMaker(domain string, qclass uint16, qtype uint16) *dns.Question {
|
||||
return &dns.Question{Name: dns.Fqdn(domain), Qtype: qtype, Qclass: qclass}
|
||||
}
|
||||
|
||||
// build a specific query message
|
||||
func queryMaker(domain string, rd bool, qclass uint16, qtype uint16, edns bool) *dns.Msg {
|
||||
msg := new(dns.Msg)
|
||||
msg.Id = dns.Id()
|
||||
msg.RecursionDesired = rd
|
||||
msg.Question = make([]dns.Question, 1)
|
||||
msg.Question[0] = *questionMaker(domain, qclass, qtype)
|
||||
if edns {
|
||||
msg = msg.SetEdns0(1232, false)
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
// query and receive the response
|
||||
// addr must contain dest port
|
||||
// func DNSQuery(addr string, domain string, rd bool, qclass uint16, qtype uint16, edns bool) (*dns.Msg, error) {
|
||||
func DNSQuery(addr string, opt DNSOptions) (*dns.Msg, error) {
|
||||
if opt.Qclass == 0 {
|
||||
opt.Qclass = 1
|
||||
}
|
||||
if opt.Qtype == 0 {
|
||||
opt.Qtype = 1
|
||||
}
|
||||
msg := queryMaker(opt.Domain, opt.RD, opt.Qclass, opt.Qtype, opt.EDNS)
|
||||
res, err := dns.Exchange(msg, addr)
|
||||
return res, err
|
||||
}
|
||||
|
||||
func AsyncDNSQuery(addr string, domain string, rd bool, qclass uint16, qtype uint16, edns bool) error {
|
||||
msg := queryMaker(domain, rd, qclass, qtype, edns)
|
||||
client := dns.Client{Net: "udp"}
|
||||
conn, err := client.Dial(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer conn.Close()
|
||||
err = conn.WriteMsg(msg)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
31
utils/other_utils.go
Normal file
31
utils/other_utils.go
Normal file
@@ -0,0 +1,31 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
_ "encoding/json"
|
||||
_ "fmt"
|
||||
"io"
|
||||
_ "net"
|
||||
_ "net/http"
|
||||
"os"
|
||||
_ "strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
func RetrieveLines(pool chan string, filename string) {
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
//fmt.Println("reading file ...")
|
||||
reader := bufio.NewReader(f)
|
||||
for {
|
||||
s, err := reader.ReadString('\n')
|
||||
if err == io.EOF {
|
||||
break
|
||||
}
|
||||
s = strings.Trim(s, "\n")
|
||||
pool <- s
|
||||
}
|
||||
close(pool)
|
||||
}
|
||||
Reference in New Issue
Block a user