feat(forward): add doh support (#8004)

* chore(pkg/proxy): prepare for DoH implementation

Signed-off-by: Thomas Gosteli <thomas.gosteli@protonmail.ch>

* chore(pkg/proxy): prepare for DoH implementation

Signed-off-by: Thomas Gosteli <thomas.gosteli@protonmail.ch>

* feat(proxy): implement basic DoH resolution

Signed-off-by: Thomas Gosteli <thomas.gosteli@protonmail.ch>

* feat(forward): implement DoH forwarding

Signed-off-by: Thomas Gosteli <thomas.gosteli@protonmail.ch>

* feat(proxy): add basic DoH health checker

Signed-off-by: Thomas Gosteli <thomas.gosteli@protonmail.ch>

* chore: align http transport with Go's DefaultTransport

and resolve some of the TODOs

Signed-off-by: Thomas Gosteli <thomas.gosteli@protonmail.ch>

* docs(forward): add basic documentation for DoH

Signed-off-by: Thomas Gosteli <thomas.gosteli@protonmail.ch>

* chore: add basic tests to cover DoH

Signed-off-by: Thomas Gosteli <thomas.gosteli@protonmail.ch>

* chore(health): unify default timeout to 1s

Signed-off-by: Thomas Gosteli <thomas.gosteli@protonmail.ch>

* feat(forward): make doh method configurable

Signed-off-by: Thomas Gosteli <thomas.gosteli@protonmail.ch>

* chore: remove maxIdleConnsPerHost setting & update docs

Signed-off-by: Thomas Gosteli <thomas.gosteli@protonmail.ch>

* chore(forward): reject https upstreams with path

Signed-off-by: Thomas Gosteli <thomas.gosteli@protonmail.ch>

---------

Signed-off-by: Thomas Gosteli <thomas.gosteli@protonmail.ch>
This commit is contained in:
Thomas Gosteli
2026-06-15 02:54:05 +02:00
committed by GitHub
parent 3764620726
commit f2f5b5a1cc
12 changed files with 363 additions and 36 deletions

View File

@@ -8,6 +8,7 @@ import (
"context"
"crypto/tls"
"errors"
"net/http"
"sync/atomic"
"time"
@@ -52,6 +53,7 @@ type Forward struct {
expire time.Duration
maxAge time.Duration
maxIdleConns int
dohMethod string
maxConcurrent int64
failfastUnhealthyUpstreams bool
failoverRcodes []int
@@ -74,7 +76,7 @@ type Forward struct {
// New returns a new Forward.
func New() *Forward {
f := &Forward{maxfails: 2, tlsConfig: new(tls.Config), expire: defaultExpire, p: new(random), from: ".", hcInterval: hcInterval, opts: proxyPkg.Options{ForceTCP: false, PreferUDP: false, HCRecursionDesired: true, HCDomain: "."}}
f := &Forward{maxfails: 2, tlsConfig: new(tls.Config), expire: defaultExpire, p: new(random), from: ".", hcInterval: hcInterval, dohMethod: http.MethodPost, opts: proxyPkg.Options{ForceTCP: false, PreferUDP: false, HCRecursionDesired: true, HCDomain: "."}}
return f
}