From 3218b5fac19c9668e42ae07e830fb683ea986111 Mon Sep 17 00:00:00 2001 From: Cuong Manh Le Date: Thu, 9 Feb 2023 01:35:16 +0700 Subject: [PATCH] Add quic-free binaries in build pipeline Updates #51 --- config.go | 46 ++++++++------------------------------------- config_quic.go | 40 +++++++++++++++++++++++++++++++++++++++ config_quic_free.go | 5 +++++ doh.go | 11 ++++++++--- doq.go | 2 ++ doq_quic_free.go | 18 ++++++++++++++++++ 6 files changed, 81 insertions(+), 41 deletions(-) create mode 100644 config_quic.go create mode 100644 config_quic_free.go create mode 100644 doq_quic_free.go diff --git a/config.go b/config.go index f4fec96..1364b4e 100644 --- a/config.go +++ b/config.go @@ -2,7 +2,6 @@ package ctrld import ( "context" - "crypto/tls" "net" "net/http" "net/url" @@ -13,8 +12,6 @@ import ( "github.com/Control-D-Inc/ctrld/internal/dnsrcode" "github.com/go-playground/validator/v10" "github.com/miekg/dns" - "github.com/quic-go/quic-go" - "github.com/quic-go/quic-go/http3" "github.com/spf13/viper" ) @@ -95,14 +92,14 @@ type NetworkConfig struct { // UpstreamConfig specifies configuration for upstreams that ctrld will forward requests to. type UpstreamConfig struct { - Name string `mapstructure:"name" toml:"name,omitempty"` - Type string `mapstructure:"type" toml:"type,omitempty" validate:"oneof=doh doh3 dot doq os legacy"` - Endpoint string `mapstructure:"endpoint" toml:"endpoint,omitempty" validate:"required_unless=Type os"` - BootstrapIP string `mapstructure:"bootstrap_ip" toml:"bootstrap_ip,omitempty"` - Domain string `mapstructure:"-" toml:"-"` - Timeout int `mapstructure:"timeout" toml:"timeout,omitempty" validate:"gte=0"` - transport *http.Transport `mapstructure:"-" toml:"-"` - http3RoundTripper *http3.RoundTripper `mapstructure:"-" toml:"-"` + Name string `mapstructure:"name" toml:"name,omitempty"` + Type string `mapstructure:"type" toml:"type,omitempty" validate:"oneof=doh doh3 dot doq os legacy"` + Endpoint string `mapstructure:"endpoint" toml:"endpoint,omitempty" validate:"required_unless=Type os"` + BootstrapIP string `mapstructure:"bootstrap_ip" toml:"bootstrap_ip,omitempty"` + Domain string `mapstructure:"-" toml:"-"` + Timeout int `mapstructure:"timeout" toml:"timeout,omitempty" validate:"gte=0"` + transport *http.Transport `mapstructure:"-" toml:"-"` + http3RoundTripper http.RoundTripper `mapstructure:"-" toml:"-"` } // ListenerConfig specifies the networks configuration that ctrld will run on. @@ -179,33 +176,6 @@ func (uc *UpstreamConfig) setupDOHTransport() { uc.pingUpstream() } -func (uc *UpstreamConfig) setupDOH3Transport() { - uc.http3RoundTripper = &http3.RoundTripper{} - uc.http3RoundTripper.Dial = func(ctx context.Context, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) { - host := addr - ProxyLog.Debug().Msgf("debug dial context D0H3 %s - %s", addr, bootstrapDNS) - // if we have a bootstrap ip set, use it to avoid DNS lookup - if uc.BootstrapIP != "" { - if _, port, _ := net.SplitHostPort(addr); port != "" { - addr = net.JoinHostPort(uc.BootstrapIP, port) - } - ProxyLog.Debug().Msgf("sending doh3 request to: %s", addr) - } - remoteAddr, err := net.ResolveUDPAddr("udp", addr) - if err != nil { - return nil, err - } - - udpConn, err := net.ListenUDP("udp", nil) - if err != nil { - return nil, err - } - return quic.DialEarlyContext(ctx, udpConn, remoteAddr, host, tlsCfg, cfg) - } - - uc.pingUpstream() -} - func (uc *UpstreamConfig) pingUpstream() { // Warming up the transport by querying a test packet. dnsResolver, err := NewResolver(uc) diff --git a/config_quic.go b/config_quic.go new file mode 100644 index 0000000..72ce351 --- /dev/null +++ b/config_quic.go @@ -0,0 +1,40 @@ +//go:build !qf + +package ctrld + +import ( + "context" + "crypto/tls" + "net" + + "github.com/quic-go/quic-go" + "github.com/quic-go/quic-go/http3" +) + +func (uc *UpstreamConfig) setupDOH3Transport() { + rt := &http3.RoundTripper{} + rt.Dial = func(ctx context.Context, addr string, tlsCfg *tls.Config, cfg *quic.Config) (quic.EarlyConnection, error) { + host := addr + ProxyLog.Debug().Msgf("debug dial context D0H3 %s - %s", addr, bootstrapDNS) + // if we have a bootstrap ip set, use it to avoid DNS lookup + if uc.BootstrapIP != "" { + if _, port, _ := net.SplitHostPort(addr); port != "" { + addr = net.JoinHostPort(uc.BootstrapIP, port) + } + ProxyLog.Debug().Msgf("sending doh3 request to: %s", addr) + } + remoteAddr, err := net.ResolveUDPAddr("udp", addr) + if err != nil { + return nil, err + } + + udpConn, err := net.ListenUDP("udp", nil) + if err != nil { + return nil, err + } + return quic.DialEarlyContext(ctx, udpConn, remoteAddr, host, tlsCfg, cfg) + } + + uc.http3RoundTripper = rt + uc.pingUpstream() +} diff --git a/config_quic_free.go b/config_quic_free.go new file mode 100644 index 0000000..5f39bc6 --- /dev/null +++ b/config_quic_free.go @@ -0,0 +1,5 @@ +//go:build qf + +package ctrld + +func (uc *UpstreamConfig) setupDOH3Transport() {} diff --git a/doh.go b/doh.go index c31a3e1..433cf41 100644 --- a/doh.go +++ b/doh.go @@ -3,12 +3,12 @@ package ctrld import ( "context" "encoding/base64" + "errors" "fmt" "io" "net/http" "github.com/miekg/dns" - "github.com/quic-go/quic-go/http3" ) func newDohResolver(uc *UpstreamConfig) *dohResolver { @@ -25,7 +25,7 @@ type dohResolver struct { endpoint string isDoH3 bool transport *http.Transport - http3RoundTripper *http3.RoundTripper + http3RoundTripper http.RoundTripper } func (r *dohResolver) Resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, error) { @@ -44,12 +44,17 @@ func (r *dohResolver) Resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, erro c := http.Client{Transport: r.transport} if r.isDoH3 { + if r.http3RoundTripper == nil { + return nil, errors.New("DoH3 is not supported") + } c.Transport = r.http3RoundTripper } resp, err := c.Do(req) if err != nil { if r.isDoH3 { - r.http3RoundTripper.Close() + if closer, ok := r.http3RoundTripper.(io.Closer); ok { + closer.Close() + } } return nil, fmt.Errorf("could not perform request: %w", err) } diff --git a/doq.go b/doq.go index 21ca301..20919e3 100644 --- a/doq.go +++ b/doq.go @@ -1,3 +1,5 @@ +//go:build !qf + package ctrld import ( diff --git a/doq_quic_free.go b/doq_quic_free.go new file mode 100644 index 0000000..36fd63c --- /dev/null +++ b/doq_quic_free.go @@ -0,0 +1,18 @@ +//go:build qf + +package ctrld + +import ( + "context" + "errors" + + "github.com/miekg/dns" +) + +type doqResolver struct { + uc *UpstreamConfig +} + +func (r *doqResolver) Resolve(ctx context.Context, msg *dns.Msg) (*dns.Msg, error) { + return nil, errors.New("DoQ is not supported") +}