add option to handle autoconfig and mta-sts requests without TLS, for when it is reverse proxied

for #5 with hints from belst & idnovic
This commit is contained in:
Mechiel Lukkien 2023-02-25 11:28:15 +01:00
parent ac3a3e496e
commit 0ede7f78c1
No known key found for this signature in database
5 changed files with 28 additions and 10 deletions

View file

@ -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."`
}

View file

@ -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:

View file

@ -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
}

View file

@ -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 {

View file

@ -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