From 48e21f566ef5029d8c9ab42a1c0b4afab269e872 Mon Sep 17 00:00:00 2001 From: "fox.cpp" Date: Sun, 8 Dec 2019 15:19:09 +0300 Subject: [PATCH] Extend .debug.* flags and hide them by default Allow to override DNS resolver address via the -debug.dnsoverride flag and SMTP port via -debug.smtpport. All flags are not available unless maddy is built using the 'debugflags' tag. --- docs/man/maddy.1.scd | 4 ---- internal/check/dnsbl/dnsbl.go | 2 +- internal/check/spf/spf.go | 2 +- internal/check/stateless_check.go | 3 +-- internal/dns/debugflags.go | 11 +++++++++ internal/dns/dnssec.go | 10 ++++++++ internal/dns/override.go | 36 ++++++++++++++++++++++++++++ internal/dns/resolver.go | 12 ++++++++-- internal/endpoint/smtp/smtp.go | 2 +- internal/msgpipeline/msgpipeline.go | 4 +--- internal/storage/sql/sql.go | 3 +-- internal/target/remote/debugflags.go | 9 +++++++ internal/target/remote/remote.go | 4 ++-- maddy.go | 18 +++++++++++--- maddy_debug.go | 11 +++++++++ 15 files changed, 110 insertions(+), 21 deletions(-) create mode 100644 internal/dns/debugflags.go create mode 100644 internal/dns/override.go create mode 100644 internal/target/remote/debugflags.go create mode 100644 maddy_debug.go diff --git a/docs/man/maddy.1.scd b/docs/man/maddy.1.scd index ceb74ca..307fece 100644 --- a/docs/man/maddy.1.scd +++ b/docs/man/maddy.1.scd @@ -41,10 +41,6 @@ emptor.* *-debug* Enable debug log. You want to use it when reporting bugs. -*-debug.pprof, -debug.blockprofrate, -debug.mutexproffract* - These options are meant for use by developers and are not interesting for - end users. - # Modules maddy is built of many small components called "modules". Each module does one diff --git a/internal/check/dnsbl/dnsbl.go b/internal/check/dnsbl/dnsbl.go index 010c130..4e6d574 100644 --- a/internal/check/dnsbl/dnsbl.go +++ b/internal/check/dnsbl/dnsbl.go @@ -52,7 +52,7 @@ func NewDNSBL(_, instName string, _, inlineArgs []string) (module.Module, error) instName: instName, inlineBls: inlineArgs, - resolver: net.DefaultResolver, + resolver: dns.DefaultResolver(), log: log.Logger{Name: "dnsbl"}, }, nil } diff --git a/internal/check/spf/spf.go b/internal/check/spf/spf.go index c38185d..8ec8259 100644 --- a/internal/check/spf/spf.go +++ b/internal/check/spf/spf.go @@ -215,7 +215,7 @@ func (s *state) relyOnDMARC(hdr textproto.Header) bool { return false } - policyDomain, record, err := maddydmarc.FetchRecord(net.DefaultResolver, context.Background(), fromDomain) + policyDomain, record, err := maddydmarc.FetchRecord(dns.DefaultResolver(), context.Background(), fromDomain) if err != nil { s.log.Error("DMARC fetch", err, "from_domain", fromDomain) return false diff --git a/internal/check/stateless_check.go b/internal/check/stateless_check.go index 00b43ae..a41af1c 100644 --- a/internal/check/stateless_check.go +++ b/internal/check/stateless_check.go @@ -2,7 +2,6 @@ package check import ( "fmt" - "net" "github.com/emersion/go-message/textproto" "github.com/foxcpp/maddy/internal/buffer" @@ -152,7 +151,7 @@ func RegisterStatelessCheck(name string, defaultFailAction FailAction, connCheck return &statelessCheck{ modName: modName, instName: instName, - resolver: net.DefaultResolver, + resolver: dns.DefaultResolver(), logger: log.Logger{Name: modName}, defaultFailAction: defaultFailAction, diff --git a/internal/dns/debugflags.go b/internal/dns/debugflags.go new file mode 100644 index 0000000..3a0aece --- /dev/null +++ b/internal/dns/debugflags.go @@ -0,0 +1,11 @@ +//+build debugflags + +package dns + +import ( + "flag" +) + +func init() { + flag.StringVar(&overrideServ, "debug.dnsoverride", "system-default", "replace the DNS resolver address") +} diff --git a/internal/dns/dnssec.go b/internal/dns/dnssec.go index a8ab6b3..18a18cb 100644 --- a/internal/dns/dnssec.go +++ b/internal/dns/dnssec.go @@ -174,6 +174,16 @@ func NewExtResolver() (*ExtResolver, error) { if err != nil { return nil, err } + + if overrideServ != "" && overrideServ != "system-default" { + host, port, err := net.SplitHostPort(overrideServ) + if err != nil { + panic(err) + } + cfg.Servers = []string{host} + cfg.Port = port + } + cl := new(dns.Client) cl.Dialer = &net.Dialer{ Timeout: time.Duration(cfg.Timeout) * time.Second, diff --git a/internal/dns/override.go b/internal/dns/override.go new file mode 100644 index 0000000..af28f25 --- /dev/null +++ b/internal/dns/override.go @@ -0,0 +1,36 @@ +package dns + +import ( + "context" + "net" + "time" +) + +var ( + overrideServ string +) + +// override globally overrides the used DNS server address with one provided. +// This function is meant only for testing. It should be called before any modules are +// initialized to have full effect. +// +// The server argument is in form of "IP:PORT". It is expected that the server +// will be available both using TCP and UDP on the same port. +func override(server string) { + net.DefaultResolver.Dial = func(ctx context.Context, network, address string) (net.Conn, error) { + dialer := net.Dialer{ + // This is localhost, it is either running or not. Fail quickly if + // we can't connect. + Timeout: 1 * time.Second, + } + + switch network { + case "udp", "udp4", "udp6": + return dialer.DialContext(ctx, "udp4", server) + case "tcp", "tcp4", "tcp6": + return dialer.DialContext(ctx, "tcp4", server) + default: + panic("OverrideDNS.Dial: unknown network") + } + } +} diff --git a/internal/dns/resolver.go b/internal/dns/resolver.go index 0cdeef7..826ae1c 100644 --- a/internal/dns/resolver.go +++ b/internal/dns/resolver.go @@ -2,7 +2,7 @@ // lookups. // // Currently, there is only Resolver interface which is implemented -// by net.DefaultResolver. In the future, DNSSEC-enabled stub resolver +// by dns.DefaultResolver(). In the future, DNSSEC-enabled stub resolver // implementation will be added here. package dns @@ -14,7 +14,7 @@ import ( // Resolver is an interface that describes DNS-related methods used by maddy. // -// It is implemented by net.DefaultResolver. Methods behave the same way. +// It is implemented by dns.DefaultResolver(). Methods behave the same way. type Resolver interface { LookupAddr(ctx context.Context, addr string) (names []string, err error) LookupHost(ctx context.Context, host string) (addrs []string, err error) @@ -33,3 +33,11 @@ func LookupAddr(ctx context.Context, r Resolver, ip net.IP) (string, error) { } return strings.TrimRight(names[0], "."), nil } + +func DefaultResolver() Resolver { + if overrideServ != "" && overrideServ != "system-default" { + override(overrideServ) + } + + return net.DefaultResolver +} diff --git a/internal/endpoint/smtp/smtp.go b/internal/endpoint/smtp/smtp.go index 6b753b8..1a9f581 100644 --- a/internal/endpoint/smtp/smtp.go +++ b/internal/endpoint/smtp/smtp.go @@ -451,7 +451,7 @@ func New(modName string, addrs []string) (module.Module, error) { addrs: addrs, submission: modName == "submission", lmtp: modName == "lmtp", - resolver: net.DefaultResolver, + resolver: dns.DefaultResolver(), Log: log.Logger{Name: modName}, } return endp, nil diff --git a/internal/msgpipeline/msgpipeline.go b/internal/msgpipeline/msgpipeline.go index 301f2f9..3d4af14 100644 --- a/internal/msgpipeline/msgpipeline.go +++ b/internal/msgpipeline/msgpipeline.go @@ -1,8 +1,6 @@ package msgpipeline import ( - "net" - "github.com/emersion/go-message/textproto" "github.com/emersion/go-smtp" "github.com/foxcpp/maddy/internal/address" @@ -50,7 +48,7 @@ func New(globals map[string]interface{}, cfg []config.Node) (*MsgPipeline, error parsedCfg, err := parseMsgPipelineRootCfg(globals, cfg) return &MsgPipeline{ msgpipelineCfg: parsedCfg, - Resolver: net.DefaultResolver, + Resolver: dns.DefaultResolver(), }, err } diff --git a/internal/storage/sql/sql.go b/internal/storage/sql/sql.go index 478f060..4854cbb 100644 --- a/internal/storage/sql/sql.go +++ b/internal/storage/sql/sql.go @@ -12,7 +12,6 @@ import ( "encoding/hex" "errors" "fmt" - "net" "os" "path/filepath" "strconv" @@ -145,7 +144,7 @@ func New(_, instName string, _, inlineArgs []string) (module.Module, error) { store := &Storage{ instName: instName, Log: log.Logger{Name: "sql"}, - resolver: net.DefaultResolver, + resolver: dns.DefaultResolver(), } if len(inlineArgs) != 0 { if len(inlineArgs) == 1 { diff --git a/internal/target/remote/debugflags.go b/internal/target/remote/debugflags.go new file mode 100644 index 0000000..d1242fa --- /dev/null +++ b/internal/target/remote/debugflags.go @@ -0,0 +1,9 @@ +//+build debugflags + +package remote + +import "flag" + +func init() { + flag.StringVar(&smtpPort, "debug.smtpport", "25", "SMTP port to use for connections in tests") +} diff --git a/internal/target/remote/remote.go b/internal/target/remote/remote.go index aeb46a8..50130fe 100644 --- a/internal/target/remote/remote.go +++ b/internal/target/remote/remote.go @@ -79,9 +79,9 @@ func New(_, instName string, _, inlineArgs []string) (module.Module, error) { } return &Target{ name: instName, - resolver: net.DefaultResolver, + resolver: dns.DefaultResolver(), dialer: net.Dial, - mtastsCache: mtasts.Cache{Resolver: net.DefaultResolver}, + mtastsCache: mtasts.Cache{Resolver: dns.DefaultResolver()}, Log: log.Logger{Name: "remote"}, stsCacheUpdateDone: make(chan struct{}), diff --git a/maddy.go b/maddy.go index 997de79..369da34 100644 --- a/maddy.go +++ b/maddy.go @@ -80,9 +80,10 @@ var ( // only for purposes of modification using -X linker flag. DefaultLibexecDirectory = "/usr/lib/maddy" - profileEndpoint = flag.String("debug.pprof", "", "enable live profiler HTTP endpoint and listen on the specified endpoint") - blockProfileRate = flag.Int("debug.blockprofrate", 0, "set blocking profile rate") - mutexProfileFract = flag.Int("debug.mutexproffract", 0, "set mutex profile fraction)") + enableDebugFlags = false + profileEndpoint *string + blockProfileRate *int + mutexProfileFract *int ) func BuildInfo() string { @@ -107,6 +108,13 @@ func Run() int { logTargets = flag.String("log", "stderr", "default logging target(s)") printVersion = flag.Bool("v", false, "print version and exit") ) + + if enableDebugFlags { + profileEndpoint = flag.String("debug.pprof", "", "enable live profiler HTTP endpoint and listen on the specified address") + blockProfileRate = flag.Int("debug.blockprofrate", 0, "set blocking profile rate") + mutexProfileFract = flag.Int("debug.mutexproffract", 0, "set mutex profile fraction") + } + flag.Parse() if len(flag.Args()) != 0 { @@ -156,6 +164,10 @@ func Run() int { } func initDebug() { + if !enableDebugFlags { + return + } + if *profileEndpoint != "" { go func() { log.Println("listening on", "http://"+*profileEndpoint, "for profiler requests") diff --git a/maddy_debug.go b/maddy_debug.go new file mode 100644 index 0000000..fa9cfc7 --- /dev/null +++ b/maddy_debug.go @@ -0,0 +1,11 @@ +//+build debugflags + +package maddy + +import ( + _ "net/http/pprof" +) + +func init() { + enableDebugFlags = true +}