From 2bf0e9875923a668e4e4300c2edcb936c6047895 Mon Sep 17 00:00:00 2001 From: uoosef Date: Thu, 23 Nov 2023 23:53:19 +0330 Subject: [PATCH] replace net/http with fastHTTP for better performance --- go.mod | 4 ++++ go.sum | 8 +++++++ main.go | 72 ++++++++++++++++++++++++++++++--------------------------- 3 files changed, 50 insertions(+), 34 deletions(-) diff --git a/go.mod b/go.mod index 92c92aa..af39aaf 100644 --- a/go.mod +++ b/go.mod @@ -4,10 +4,14 @@ go 1.21.1 require ( github.com/miekg/dns v1.1.57 + github.com/valyala/fasthttp v1.51.0 golang.org/x/time v0.4.0 ) require ( + github.com/andybalholm/brotli v1.0.5 // indirect + github.com/klauspost/compress v1.17.0 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect golang.org/x/mod v0.12.0 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/sys v0.13.0 // indirect diff --git a/go.sum b/go.sum index 367a72e..5eb5a76 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,13 @@ +github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= +github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/klauspost/compress v1.17.0 h1:Rnbp4K9EjcDuVuHtd0dgA4qNuv9yKDYKK1ulpJwgrqM= +github.com/klauspost/compress v1.17.0/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/miekg/dns v1.1.57 h1:Jzi7ApEIzwEPLHWRcafCN9LZSBbqQpxjt/wpgvg7wcM= github.com/miekg/dns v1.1.57/go.mod h1:uqRjCRUuEAA6qsOiJvDd+CFo/vW+y5WR6SNmHE55hZk= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.51.0 h1:8b30A5JlZ6C7AS81RsWjYMQmrZG6feChmgAolCl1SqA= +github.com/valyala/fasthttp v1.51.0/go.mod h1:oI2XroL+lI7vdXyYoQk03bXBThfFl2cVdIA3Xl7cH8g= golang.org/x/mod v0.12.0 h1:rmsUpXtvNzj340zd98LZ4KntptpfRHwpFOHG188oHXc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= diff --git a/main.go b/main.go index 797b4f7..ef1de35 100644 --- a/main.go +++ b/main.go @@ -7,6 +7,7 @@ import ( "encoding/json" "fmt" "github.com/miekg/dns" + "github.com/valyala/fasthttp" "golang.org/x/time/rate" "io" "log" @@ -77,31 +78,6 @@ func processDNSQuery(query []byte) ([]byte, error) { return msg.Pack() } -// handleDoHRequest processes the DoH request with rate limiting. -func handleDoHRequest(limiter *rate.Limiter) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - if !limiter.Allow() { - http.Error(w, "Rate limit exceeded", http.StatusTooManyRequests) - return - } - - body, err := io.ReadAll(r.Body) - if err != nil { - http.Error(w, "Failed to read request body", http.StatusInternalServerError) - return - } - - dnsResponse, err := processDNSQuery(body) - if err != nil { - http.Error(w, "Failed to pack DNS response", http.StatusInternalServerError) - return - } - - w.Header().Set("Content-Type", "application/dns-message") - w.Write(dnsResponse) - } -} - // handleDoTConnection handles a single DoT connection. func handleDoTConnection(conn net.Conn, limiter *rate.Limiter) { defer conn.Close() @@ -210,13 +186,13 @@ type readOnlyConn struct { } func (conn readOnlyConn) Read(p []byte) (int, error) { return conn.reader.Read(p) } -func (conn readOnlyConn) Write(p []byte) (int, error) { return 0, io.ErrClosedPipe } +func (conn readOnlyConn) Write(_ []byte) (int, error) { return 0, io.ErrClosedPipe } func (conn readOnlyConn) Close() error { return conn.Close() } func (conn readOnlyConn) LocalAddr() net.Addr { return nil } func (conn readOnlyConn) RemoteAddr() net.Addr { return nil } -func (conn readOnlyConn) SetDeadline(t time.Time) error { return nil } -func (conn readOnlyConn) SetReadDeadline(t time.Time) error { return nil } -func (conn readOnlyConn) SetWriteDeadline(t time.Time) error { return nil } +func (conn readOnlyConn) SetDeadline(t time.Time) error { return conn.SetDeadline(t) } +func (conn readOnlyConn) SetReadDeadline(t time.Time) error { return conn.SetReadDeadline(t) } +func (conn readOnlyConn) SetWriteDeadline(t time.Time) error { return conn.SetWriteDeadline(t) } func readClientHello(reader io.Reader) (*tls.ClientHelloInfo, error) { var hello *tls.ClientHelloInfo @@ -298,16 +274,44 @@ func handleConnection(clientConn net.Conn) { wg.Wait() } -func runDOHServer(limiter *rate.Limiter) { - http.HandleFunc("/dns-query", handleDoHRequest(limiter)) +// handleDoHRequest processes the DoH request with rate limiting using fasthttp. +func handleDoHRequest(ctx *fasthttp.RequestCtx, limiter *rate.Limiter) { + if !limiter.Allow() { + ctx.Error("Rate limit exceeded", fasthttp.StatusTooManyRequests) + return + } + + body := ctx.PostBody() + + dnsResponse, err := processDNSQuery(body) + if err != nil { + ctx.Error("Failed to process DNS query", fasthttp.StatusInternalServerError) + return + } + + ctx.SetContentType("application/dns-message") + ctx.SetStatusCode(fasthttp.StatusOK) + ctx.Write(dnsResponse) +} - server := &http.Server{ - Addr: "127.0.0.1:8080", +// runDOHServer starts the DNS-over-HTTPS server using fasthttp. +func runDOHServer(limiter *rate.Limiter) { + server := &fasthttp.Server{ + Handler: func(ctx *fasthttp.RequestCtx) { + switch string(ctx.Path()) { + case "/dns-query": + handleDoHRequest(ctx, limiter) + default: + ctx.Error("Unsupported path", fasthttp.StatusNotFound) + } + }, ReadTimeout: 10 * time.Second, WriteTimeout: 10 * time.Second, } - log.Println(server.ListenAndServe()) + if err := server.ListenAndServe("127.0.0.1:8080"); err != nil { + log.Fatalf("Error in DoH Server: %s", err) + } } func main() {