forked from 0xERR0R/blocky
-
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.
feat: allow configuring DoH separately from other HTTP endpoints
- Loading branch information
1 parent
80e0cad
commit 13798e0
Showing
8 changed files
with
192 additions
and
105 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
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,18 @@ | ||
package config | ||
|
||
type DoHService struct { | ||
Addrs DoHAddrs `yaml:"addrs"` | ||
} | ||
|
||
type DoHAddrs struct { | ||
HTTPAddrs `yaml:",inline"` | ||
HTTPSAddrs `yaml:",inline"` | ||
} | ||
|
||
type HTTPAddrs struct { | ||
HTTP ListenConfig `yaml:"http"` | ||
} | ||
|
||
type HTTPSAddrs struct { | ||
HTTPS ListenConfig `yaml:"https"` | ||
} |
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,137 @@ | ||
package server | ||
|
||
import ( | ||
"encoding/base64" | ||
"io" | ||
"net/http" | ||
|
||
"github.com/0xERR0R/blocky/config" | ||
"github.com/0xERR0R/blocky/service" | ||
"github.com/0xERR0R/blocky/util" | ||
"github.com/go-chi/chi/v5" | ||
"github.com/miekg/dns" | ||
) | ||
|
||
type dohService struct { | ||
service.HTTPInfo | ||
|
||
handler dnsHandler | ||
} | ||
|
||
func newDoHService(cfg config.DoHService, handler dnsHandler) *dohService { | ||
endpoints := util.ConcatSlices( | ||
service.EndpointsFromAddrs(httpProtocol, cfg.Addrs.HTTP), | ||
service.EndpointsFromAddrs(httpsProtocol, cfg.Addrs.HTTPS), | ||
) | ||
|
||
s := &dohService{ | ||
HTTPInfo: service.HTTPInfo{ | ||
Info: service.Info{ | ||
Name: "DoH", | ||
Endpoints: endpoints, | ||
}, | ||
|
||
Mux: chi.NewMux(), | ||
}, | ||
|
||
handler: handler, | ||
} | ||
|
||
s.Mux.Route("/dns-query", func(mux chi.Router) { | ||
// Handlers for / also handle /dns-query without trailing slash | ||
|
||
mux.Get("/", s.handleGET) | ||
mux.Get("/{clientID}", s.handleGET) | ||
|
||
mux.Post("/", s.handlePOST) | ||
mux.Post("/{clientID}", s.handlePOST) | ||
}) | ||
|
||
return s | ||
} | ||
|
||
func (s *dohService) Merge(other service.Service) (service.Merger, error) { | ||
return service.MergeHTTP(s, other) | ||
} | ||
|
||
func (s *dohService) handleGET(rw http.ResponseWriter, req *http.Request) { | ||
dnsParam, ok := req.URL.Query()["dns"] | ||
if !ok || len(dnsParam[0]) < 1 { | ||
http.Error(rw, "dns param is missing", http.StatusBadRequest) | ||
|
||
return | ||
} | ||
|
||
rawMsg, err := base64.RawURLEncoding.DecodeString(dnsParam[0]) | ||
if err != nil { | ||
http.Error(rw, "wrong message format", http.StatusBadRequest) | ||
|
||
return | ||
} | ||
|
||
if len(rawMsg) > dohMessageLimit { | ||
http.Error(rw, "URI Too Long", http.StatusRequestURITooLong) | ||
|
||
return | ||
} | ||
|
||
s.processDohMessage(rawMsg, rw, req) | ||
} | ||
|
||
func (s *dohService) handlePOST(rw http.ResponseWriter, req *http.Request) { | ||
contentType := req.Header.Get("Content-type") | ||
if contentType != dnsContentType { | ||
http.Error(rw, "unsupported content type", http.StatusUnsupportedMediaType) | ||
|
||
return | ||
} | ||
|
||
rawMsg, err := io.ReadAll(req.Body) | ||
if err != nil { | ||
http.Error(rw, err.Error(), http.StatusBadRequest) | ||
|
||
return | ||
} | ||
|
||
if len(rawMsg) > dohMessageLimit { | ||
http.Error(rw, "Payload Too Large", http.StatusRequestEntityTooLarge) | ||
|
||
return | ||
} | ||
|
||
s.processDohMessage(rawMsg, rw, req) | ||
} | ||
|
||
func (s *dohService) processDohMessage(rawMsg []byte, rw http.ResponseWriter, httpReq *http.Request) { | ||
msg := new(dns.Msg) | ||
if err := msg.Unpack(rawMsg); err != nil { | ||
logger().Error("can't deserialize message: ", err) | ||
http.Error(rw, err.Error(), http.StatusBadRequest) | ||
|
||
return | ||
} | ||
|
||
ctx, dnsReq := newRequestFromHTTP(httpReq.Context(), httpReq, msg) | ||
|
||
s.handler(ctx, dnsReq, httpMsgWriter{rw}) | ||
} | ||
|
||
type httpMsgWriter struct { | ||
rw http.ResponseWriter | ||
} | ||
|
||
func (r httpMsgWriter) WriteMsg(msg *dns.Msg) error { | ||
b, err := msg.Pack() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
r.rw.Header().Set("content-type", dnsContentType) | ||
|
||
// https://www.rfc-editor.org/rfc/rfc8484#section-4.2.1 | ||
r.rw.WriteHeader(http.StatusOK) | ||
|
||
_, err = r.rw.Write(b) | ||
|
||
return err | ||
} |
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
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
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