diff --git a/config/config.go b/config/config.go index d7e2509..9b84577 100644 --- a/config/config.go +++ b/config/config.go @@ -135,11 +135,13 @@ type Listener struct { } `sconf:"optional" sconf-doc:"Serve /debug/pprof/ for profiling a running mox instance. Do not enable this on a public IP!"` AutoconfigHTTPS struct { Enabled bool - Port int `sconf:"optional" sconf-doc:"TLS port, 443 by default. You should only override this if you cannot listen on port 443 directly. Autoconfig requests will be made to port 443, so you'll have to add an external mechanism to get the connection here, e.g. by configuring port forwarding."` + Port int `sconf:"optional" sconf-doc:"TLS port, 443 by default. You should only override this if you cannot listen on port 443 directly. Autoconfig requests will be made to port 443, so you'll have to add an external mechanism to get the connection here, e.g. by configuring port forwarding."` + NonTLS bool `sconf:"optional" sconf-doc:"If set, plain HTTP instead of HTTPS is spoken on the configured port. Can be useful when the autoconfig domain is reverse proxied."` } `sconf:"optional" sconf-doc:"Serve autoconfiguration/autodiscovery to simplify configuring email applications, will use port 443. Requires a TLS config."` MTASTSHTTPS struct { Enabled bool - Port int `sconf:"optional" sconf-doc:"TLS port, 443 by default. You should only override this if you cannot listen on port 443 directly. MTA-STS requests will be made to port 443, so you'll have to add an external mechanism to get the connection here, e.g. by configuring port forwarding."` + Port int `sconf:"optional" sconf-doc:"TLS port, 443 by default. You should only override this if you cannot listen on port 443 directly. MTA-STS requests will be made to port 443, so you'll have to add an external mechanism to get the connection here, e.g. by configuring port forwarding."` + NonTLS bool `sconf:"optional" sconf-doc:"If set, plain HTTP instead of HTTPS is spoken on the configured port. Can be useful when the mta-sts domain is reverse proxied."` } `sconf:"optional" sconf-doc:"Serve MTA-STS policies describing SMTP TLS requirements. Requires a TLS config."` } diff --git a/config/doc.go b/config/doc.go index c4e175a..2fcfc0f 100644 --- a/config/doc.go +++ b/config/doc.go @@ -240,6 +240,10 @@ describe-static" and "mox config describe-domains": # port forwarding. (optional) Port: 0 + # If set, plain HTTP instead of HTTPS is spoken on the configured port. Can be + # useful when the autoconfig domain is reverse proxied. (optional) + NonTLS: false + # Serve MTA-STS policies describing SMTP TLS requirements. Requires a TLS config. # (optional) MTASTSHTTPS: @@ -251,6 +255,10 @@ describe-static" and "mox config describe-domains": # forwarding. (optional) Port: 0 + # If set, plain HTTP instead of HTTPS is spoken on the configured port. Can be + # useful when the mta-sts domain is reverse proxied. (optional) + NonTLS: false + # Destination for emails delivered to postmaster address. Postmaster: Account: diff --git a/http/mtasts.go b/http/mtasts.go index 3c40c94..b5c5585 100644 --- a/http/mtasts.go +++ b/http/mtasts.go @@ -1,6 +1,7 @@ package http import ( + "net" "net/http" "strings" "time" @@ -18,9 +19,14 @@ func mtastsPolicyHandle(w http.ResponseWriter, r *http.Request) { http.NotFound(w, r) return } - domain, err := dns.ParseDomain(strings.TrimPrefix(r.Host, "mta-sts.")) + host, _, err := net.SplitHostPort(strings.TrimPrefix(r.Host, "mta-sts.")) if err != nil { - log.Errorx("mtasts policy request: bad domain", err, mlog.Field("host", r.Host)) + http.NotFound(w, r) + return + } + domain, err := dns.ParseDomain(host) + if err != nil { + log.Errorx("mtasts policy request: bad domain", err, mlog.Field("host", host)) http.NotFound(w, r) return } diff --git a/http/web.go b/http/web.go index 567c187..a228706 100644 --- a/http/web.go +++ b/http/web.go @@ -110,12 +110,12 @@ func ListenAndServe() { })) } if l.AutoconfigHTTPS.Enabled { - srv := ensureServe(true, config.Port(l.AutoconfigHTTPS.Port, 443), "autoconfig-https") + srv := ensureServe(!l.AutoconfigHTTPS.NonTLS, config.Port(l.AutoconfigHTTPS.Port, 443), "autoconfig-https") srv.mux.HandleFunc("/mail/config-v1.1.xml", safeHeaders(autoconfHandle(l))) srv.mux.HandleFunc("/autodiscover/autodiscover.xml", safeHeaders(autodiscoverHandle(l))) } if l.MTASTSHTTPS.Enabled { - srv := ensureServe(true, config.Port(l.MTASTSHTTPS.Port, 443), "mtasts-https") + srv := ensureServe(!l.AutoconfigHTTPS.NonTLS, config.Port(l.MTASTSHTTPS.Port, 443), "mtasts-https") srv.mux.HandleFunc("/.well-known/mta-sts.txt", safeHeaders(mtastsPolicyHandle)) } if l.PprofHTTP.Enabled { diff --git a/mox-/config.go b/mox-/config.go index ffec949..c9d9963 100644 --- a/mox-/config.go +++ b/mox-/config.go @@ -202,8 +202,7 @@ func (c *Config) allowACMEHosts() { } m := c.Static.ACME[l.TLS.ACME].Manager for _, dom := range c.Dynamic.Domains { - - if l.AutoconfigHTTPS.Enabled { + if l.AutoconfigHTTPS.Enabled && !l.AutoconfigHTTPS.NonTLS { if d, err := dns.ParseDomain("autoconfig." + dom.Domain.ASCII); err != nil { xlog.Errorx("parsing autoconfig domain", err, mlog.Field("domain", dom.Domain)) } else { @@ -217,7 +216,7 @@ func (c *Config) allowACMEHosts() { } } - if l.MTASTSHTTPS.Enabled && dom.MTASTS != nil { + if l.MTASTSHTTPS.Enabled && dom.MTASTS != nil && !l.MTASTSHTTPS.NonTLS { d, err := dns.ParseDomain("mta-sts." + dom.Domain.ASCII) if err != nil { xlog.Errorx("parsing mta-sts domain", err, mlog.Field("domain", dom.Domain)) @@ -484,12 +483,15 @@ func PrepareStaticConfig(ctx context.Context, configFile string, config *Config, if l.TLS.ACMEConfig != nil { l.TLS.ACMEConfig.MinVersion = minVersion } - } else if l.IMAPS.Enabled || l.SMTP.Enabled && !l.SMTP.NoSTARTTLS || l.Submissions.Enabled || l.Submission.Enabled && !l.Submission.NoRequireSTARTTLS || l.AccountHTTPS.Enabled || l.AdminHTTPS.Enabled || l.AutoconfigHTTPS.Enabled || l.MTASTSHTTPS.Enabled { + } else if l.IMAPS.Enabled || l.SMTP.Enabled && !l.SMTP.NoSTARTTLS || l.Submissions.Enabled || l.Submission.Enabled && !l.Submission.NoRequireSTARTTLS || l.AccountHTTPS.Enabled || l.AdminHTTPS.Enabled || (l.AutoconfigHTTPS.Enabled && !l.AutoconfigHTTPS.NonTLS) || (l.MTASTSHTTPS.Enabled && !l.MTASTSHTTPS.NonTLS) { addErrorf("listener %q requires TLS, but does not specify tls config", name) } if l.AutoconfigHTTPS.Enabled && (!l.IMAP.Enabled && !l.IMAPS.Enabled || !l.Submission.Enabled && !l.Submissions.Enabled) { addErrorf("listener %q with autoconfig enabled must have SMTP submission or submissions and IMAP or IMAPS enabled", name) } + if l.AutoconfigHTTPS.Enabled && l.MTASTSHTTPS.Enabled && l.AutoconfigHTTPS.Port == l.MTASTSHTTPS.Port && l.AutoconfigHTTPS.NonTLS != l.MTASTSHTTPS.NonTLS { + addErrorf("listener %q tries to enable autoconfig and mta-sts enabled on same port but with both http and https", name) + } if l.SMTP.Enabled { if len(l.IPs) == 0 { haveUnspecifiedSMTPListener = true