mirror of
https://github.com/mjl-/mox.git
synced 2025-01-16 02:16:26 +03:00
Count ALPN connections separately in metrics
Also this required a new attribute on the IMAP and SMTP connection structs, and made it easier to avoid using the reflection tools.
This commit is contained in:
parent
f02e04df72
commit
f7976539ea
2 changed files with 19 additions and 14 deletions
|
@ -52,7 +52,6 @@ import (
|
||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"regexp"
|
"regexp"
|
||||||
"reflect"
|
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"slices"
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -171,6 +170,7 @@ type conn struct {
|
||||||
state state
|
state state
|
||||||
conn net.Conn
|
conn net.Conn
|
||||||
tls bool // Whether TLS has been initialized.
|
tls bool // Whether TLS has been initialized.
|
||||||
|
viaHTTPS bool // Whether this connection came in via HTTPS (using TLS ALPN).
|
||||||
br *bufio.Reader // From remote, with TLS unwrapped in case of TLS.
|
br *bufio.Reader // From remote, with TLS unwrapped in case of TLS.
|
||||||
line chan lineErr // If set, instead of reading from br, a line is read from this channel. For reading a line in IDLE while also waiting for mailbox/account updates.
|
line chan lineErr // If set, instead of reading from br, a line is read from this channel. For reading a line in IDLE while also waiting for mailbox/account updates.
|
||||||
lastLine string // For detecting if syntax error is fatal, i.e. if this ends with a literal. Without crlf.
|
lastLine string // For detecting if syntax error is fatal, i.e. if this ends with a literal. Without crlf.
|
||||||
|
@ -347,8 +347,9 @@ func Listen() http.FnALPNHelper {
|
||||||
}
|
}
|
||||||
if listener.IMAPS.EnableOnHTTPS && alpnHelper == nil {
|
if listener.IMAPS.EnableOnHTTPS && alpnHelper == nil {
|
||||||
alpnHelper = func(tc *tls.Config, conn net.Conn) {
|
alpnHelper = func(tc *tls.Config, conn net.Conn) {
|
||||||
|
protocol = protocol + "https"
|
||||||
metricIMAPConnection.WithLabelValues(protocol).Inc()
|
metricIMAPConnection.WithLabelValues(protocol).Inc()
|
||||||
serve(name, mox.Cid(), tc, conn, true, false)
|
serve(name, mox.Cid(), tc, conn, true, false, true)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -391,7 +392,7 @@ func listen1(protocol, listenerName, ip string, port int, tlsConfig *tls.Config,
|
||||||
}
|
}
|
||||||
|
|
||||||
metricIMAPConnection.WithLabelValues(protocol).Inc()
|
metricIMAPConnection.WithLabelValues(protocol).Inc()
|
||||||
go serve(listenerName, mox.Cid(), tlsConfig, conn, xtls, noRequireSTARTTLS)
|
go serve(listenerName, mox.Cid(), tlsConfig, conn, xtls, noRequireSTARTTLS, false)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -646,7 +647,7 @@ func (c *conn) xhighestModSeq(tx *bstore.Tx, mailboxID int64) store.ModSeq {
|
||||||
|
|
||||||
var cleanClose struct{} // Sentinel value for panic/recover indicating clean close of connection.
|
var cleanClose struct{} // Sentinel value for panic/recover indicating clean close of connection.
|
||||||
|
|
||||||
func serve(listenerName string, cid int64, tlsConfig *tls.Config, nc net.Conn, xtls, noRequireSTARTTLS bool) {
|
func serve(listenerName string, cid int64, tlsConfig *tls.Config, nc net.Conn, xtls, noRequireSTARTTLS, viaHTTPS bool) {
|
||||||
var remoteIP net.IP
|
var remoteIP net.IP
|
||||||
if a, ok := nc.RemoteAddr().(*net.TCPAddr); ok {
|
if a, ok := nc.RemoteAddr().(*net.TCPAddr); ok {
|
||||||
remoteIP = a.IP
|
remoteIP = a.IP
|
||||||
|
@ -659,6 +660,7 @@ func serve(listenerName string, cid int64, tlsConfig *tls.Config, nc net.Conn, x
|
||||||
cid: cid,
|
cid: cid,
|
||||||
conn: nc,
|
conn: nc,
|
||||||
tls: xtls,
|
tls: xtls,
|
||||||
|
viaHTTPS: viaHTTPS,
|
||||||
lastlog: time.Now(),
|
lastlog: time.Now(),
|
||||||
baseTLSConfig: tlsConfig,
|
baseTLSConfig: tlsConfig,
|
||||||
remoteIP: remoteIP,
|
remoteIP: remoteIP,
|
||||||
|
@ -728,8 +730,7 @@ func serve(listenerName string, cid int64, tlsConfig *tls.Config, nc net.Conn, x
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
isAlreadyTLS := reflect.TypeOf(nc) == reflect.TypeFor[*tls.Conn]()
|
if xtls && !viaHTTPS {
|
||||||
if xtls && !isAlreadyTLS {
|
|
||||||
// Start TLS on connection. We perform the handshake explicitly, so we can set a
|
// Start TLS on connection. We perform the handshake explicitly, so we can set a
|
||||||
// timeout, do client certificate authentication, log TLS details afterwards.
|
// timeout, do client certificate authentication, log TLS details afterwards.
|
||||||
c.xtlsHandshakeAndAuthenticate(c.conn)
|
c.xtlsHandshakeAndAuthenticate(c.conn)
|
||||||
|
|
|
@ -23,7 +23,6 @@ import (
|
||||||
"net"
|
"net"
|
||||||
"net/textproto"
|
"net/textproto"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
|
||||||
"runtime/debug"
|
"runtime/debug"
|
||||||
"slices"
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
|
@ -266,7 +265,7 @@ func Listen() http.FnALPNHelper {
|
||||||
alpnHelper = func(tc *tls.Config, conn net.Conn) {
|
alpnHelper = func(tc *tls.Config, conn net.Conn) {
|
||||||
log := mlog.New("smtpserver", nil)
|
log := mlog.New("smtpserver", nil)
|
||||||
resolver := dns.StrictResolver{Log: log.Logger}
|
resolver := dns.StrictResolver{Log: log.Logger}
|
||||||
serve(name, mox.Cid(), hostname, tc, conn, resolver, true, true, maxMsgSize, true, true, true, nil, 0)
|
serve(name, mox.Cid(), hostname, tc, conn, resolver, true, true, true, maxMsgSize, true, true, true, nil, 0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -310,7 +309,7 @@ func listen1(protocol, name, ip string, port int, hostname dns.Domain, tlsConfig
|
||||||
|
|
||||||
// Package is set on the resolver by the dkim/spf/dmarc/etc packages.
|
// Package is set on the resolver by the dkim/spf/dmarc/etc packages.
|
||||||
resolver := dns.StrictResolver{Log: log.Logger}
|
resolver := dns.StrictResolver{Log: log.Logger}
|
||||||
go serve(name, mox.Cid(), hostname, tlsConfig, conn, resolver, submission, xtls, maxMessageSize, requireTLSForAuth, requireTLSForDelivery, requireTLS, dnsBLs, firstTimeSenderDelay)
|
go serve(name, mox.Cid(), hostname, tlsConfig, conn, resolver, submission, xtls, false, maxMessageSize, requireTLSForAuth, requireTLSForDelivery, requireTLS, dnsBLs, firstTimeSenderDelay)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,6 +335,7 @@ type conn struct {
|
||||||
|
|
||||||
tls bool
|
tls bool
|
||||||
extRequireTLS bool // Whether to announce and allow the REQUIRETLS extension.
|
extRequireTLS bool // Whether to announce and allow the REQUIRETLS extension.
|
||||||
|
viaHTTPS bool // Whether the connection came in via the HTTPS port (using TLS ALPN).
|
||||||
resolver dns.Resolver
|
resolver dns.Resolver
|
||||||
r *bufio.Reader
|
r *bufio.Reader
|
||||||
w *bufio.Writer
|
w *bufio.Writer
|
||||||
|
@ -810,7 +810,7 @@ func (c *conn) writelinef(format string, args ...any) {
|
||||||
|
|
||||||
var cleanClose struct{} // Sentinel value for panic/recover indicating clean close of connection.
|
var cleanClose struct{} // Sentinel value for panic/recover indicating clean close of connection.
|
||||||
|
|
||||||
func serve(listenerName string, cid int64, hostname dns.Domain, tlsConfig *tls.Config, nc net.Conn, resolver dns.Resolver, submission, xtls bool, maxMessageSize int64, requireTLSForAuth, requireTLSForDelivery, requireTLS bool, dnsBLs []dns.Domain, firstTimeSenderDelay time.Duration) {
|
func serve(listenerName string, cid int64, hostname dns.Domain, tlsConfig *tls.Config, nc net.Conn, resolver dns.Resolver, submission, xtls, viaHTTPS bool, maxMessageSize int64, requireTLSForAuth, requireTLSForDelivery, requireTLS bool, dnsBLs []dns.Domain, firstTimeSenderDelay time.Duration) {
|
||||||
var localIP, remoteIP net.IP
|
var localIP, remoteIP net.IP
|
||||||
if a, ok := nc.LocalAddr().(*net.TCPAddr); ok {
|
if a, ok := nc.LocalAddr().(*net.TCPAddr); ok {
|
||||||
localIP = a.IP
|
localIP = a.IP
|
||||||
|
@ -831,6 +831,7 @@ func serve(listenerName string, cid int64, hostname dns.Domain, tlsConfig *tls.C
|
||||||
conn: nc,
|
conn: nc,
|
||||||
submission: submission,
|
submission: submission,
|
||||||
tls: xtls,
|
tls: xtls,
|
||||||
|
viaHTTPS: viaHTTPS,
|
||||||
extRequireTLS: requireTLS,
|
extRequireTLS: requireTLS,
|
||||||
resolver: resolver,
|
resolver: resolver,
|
||||||
lastlog: time.Now(),
|
lastlog: time.Now(),
|
||||||
|
@ -894,8 +895,7 @@ func serve(listenerName string, cid int64, hostname dns.Domain, tlsConfig *tls.C
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
isAlreadyTLS := reflect.TypeOf(nc) == reflect.TypeFor[*tls.Conn]()
|
if xtls && !viaHTTPS {
|
||||||
if xtls && !isAlreadyTLS {
|
|
||||||
// Start TLS on connection. We perform the handshake explicitly, so we can set a
|
// Start TLS on connection. We perform the handshake explicitly, so we can set a
|
||||||
// timeout, do client certificate authentication, log TLS details afterwards.
|
// timeout, do client certificate authentication, log TLS details afterwards.
|
||||||
c.xtlsHandshakeAndAuthenticate(c.conn)
|
c.xtlsHandshakeAndAuthenticate(c.conn)
|
||||||
|
@ -1046,10 +1046,14 @@ func command(c *conn) {
|
||||||
|
|
||||||
// For use in metric labels.
|
// For use in metric labels.
|
||||||
func (c *conn) kind() string {
|
func (c *conn) kind() string {
|
||||||
|
k := "smtp"
|
||||||
if c.submission {
|
if c.submission {
|
||||||
return "submission"
|
k = "submission"
|
||||||
}
|
}
|
||||||
return "smtp"
|
if c.viaHTTPS {
|
||||||
|
k = k + "https"
|
||||||
|
}
|
||||||
|
return k
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *conn) xneedHello() {
|
func (c *conn) xneedHello() {
|
||||||
|
|
Loading…
Reference in a new issue