reject connections from banned hosts before talking with them

This commit is contained in:
Aine
2022-11-18 08:59:18 +02:00
parent e38d4b2fc5
commit 0f2683bcd0
3 changed files with 55 additions and 3 deletions

View File

@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
for i in {0..10..1}; do for i in {0..100..1}; do
echo "#${i}..." echo "#${i}..."
ssmtp test@localhost < $1 ssmtp test@localhost < $1
done done

50
smtp/listener.go Normal file
View File

@@ -0,0 +1,50 @@
package smtp
import (
"net"
"gitlab.com/etke.cc/go/logger"
)
// Listener that rejects connections from banned hosts
type Listener struct {
log *logger.Logger
listener net.Listener
isBanned func(net.Addr) bool
}
func NewListener(actual net.Listener, isBanned func(net.Addr) bool, log *logger.Logger) *Listener {
return &Listener{
log: log,
listener: actual,
isBanned: isBanned,
}
}
// Accept waits for and returns the next connection to the listener.
func (l *Listener) Accept() (net.Conn, error) {
conn, err := l.listener.Accept()
if err != nil {
return conn, err
}
if l.isBanned(conn.RemoteAddr()) {
conn.Close()
l.log.Info("rejected connection from %q (already banned)", conn.RemoteAddr())
// Due to go-smtp design, any error returned here will crash whole server,
// thus we have to forge a connection
return &net.TCPConn{}, nil
}
return conn, nil
}
// Close closes the listener.
// Any blocked Accept operations will be unblocked and return errors.
func (l *Listener) Close() error {
return l.listener.Close()
}
// Addr returns the listener's network address.
func (l *Listener) Addr() net.Addr {
return l.listener.Addr()
}

View File

@@ -30,6 +30,7 @@ type Config struct {
type Manager struct { type Manager struct {
log *logger.Logger log *logger.Logger
bot matrixbot
smtp *smtp.Server smtp *smtp.Server
errs chan error errs chan error
@@ -77,6 +78,7 @@ func NewManager(cfg *Config) *Manager {
m := &Manager{ m := &Manager{
smtp: s, smtp: s,
bot: cfg.Bot,
log: log, log: log,
port: cfg.Port, port: cfg.Port,
tlsPort: cfg.TLSPort, tlsPort: cfg.TLSPort,
@@ -118,10 +120,10 @@ func (m *Manager) listen(port string, tlsCfg *tls.Config) {
m.errs <- err m.errs <- err
return return
} }
lwrapper := NewListener(l, m.bot.IsBanned, m.log)
m.log.Info("Starting SMTP server on port %s", port) m.log.Info("Starting SMTP server on port %s", port)
err = m.smtp.Serve(l) err = m.smtp.Serve(lwrapper)
if err != nil { if err != nil {
m.log.Error("cannot start SMTP server on %s: %v", port, err) m.log.Error("cannot start SMTP server on %s: %v", port, err)
m.errs <- err m.errs <- err