1
0
Fork 0
forked from External/ergo

Add initial automated connection throttling

This commit is contained in:
Daniel Oaks 2017-01-12 17:40:01 +10:00
parent ddba5af265
commit 91d59575ce
6 changed files with 301 additions and 53 deletions

View file

@ -28,7 +28,7 @@ import (
var (
// cached because this may be used lots
tooManyClientsMsg = ircmsg.MakeMessage(nil, "", "ERROR", "Too many clients from your IP or network")
tooManyClientsMsg = ircmsg.MakeMessage(nil, "", "ERROR", "Too many clients from your network")
tooManyClientsBytes, _ = tooManyClientsMsg.Line()
bannedFromServerMsg = ircmsg.MakeMessage(nil, "", "ERROR", "You are banned from this server (%s)")
@ -72,42 +72,44 @@ type ListenerEvent struct {
// Server is the main Oragono server.
type Server struct {
accountRegistration *AccountRegistration
accounts map[string]*ClientAccount
authenticationEnabled bool
channels ChannelNameMap
checkIdent bool
clients *ClientLookupSet
commands chan Command
configFilename string
connectionLimits *ConnectionLimits
connectionLimitsMutex sync.Mutex // used when affecting the connection limiter, to make sure rehashing doesn't make things go out-of-whack
ctime time.Time
currentOpers map[*Client]bool
dlines *DLineManager
idle chan *Client
isupport *ISupportList
klines *KLineManager
limits Limits
listenerEventActMutex sync.Mutex
listeners map[string]ListenerInterface
listenerUpdateMutex sync.Mutex
monitoring map[string][]Client
motdLines []string
name string
nameCasefolded string
networkName string
newConns chan clientConn
operators map[string]Oper
operclasses map[string]OperClass
password []byte
passwords *PasswordManager
rehashMutex sync.Mutex
rehashSignal chan os.Signal
restAPI *RestAPIConfig
signals chan os.Signal
store *buntdb.DB
whoWas *WhoWasList
accountRegistration *AccountRegistration
accounts map[string]*ClientAccount
authenticationEnabled bool
channels ChannelNameMap
checkIdent bool
clients *ClientLookupSet
commands chan Command
configFilename string
connectionThrottle *ConnectionThrottle
connectionThrottleMutex sync.Mutex // used when affecting the connection limiter, to make sure rehashing doesn't make things go out-of-whack
connectionLimits *ConnectionLimits
connectionLimitsMutex sync.Mutex // used when affecting the connection limiter, to make sure rehashing doesn't make things go out-of-whack
ctime time.Time
currentOpers map[*Client]bool
dlines *DLineManager
idle chan *Client
isupport *ISupportList
klines *KLineManager
limits Limits
listenerEventActMutex sync.Mutex
listeners map[string]ListenerInterface
listenerUpdateMutex sync.Mutex
monitoring map[string][]Client
motdLines []string
name string
nameCasefolded string
networkName string
newConns chan clientConn
operators map[string]Oper
operclasses map[string]OperClass
password []byte
passwords *PasswordManager
rehashMutex sync.Mutex
rehashSignal chan os.Signal
restAPI *RestAPIConfig
signals chan os.Signal
store *buntdb.DB
whoWas *WhoWasList
}
var (
@ -157,6 +159,10 @@ func NewServer(configFilename string, config *Config) *Server {
if err != nil {
log.Fatal("Error loading connection limits:", err.Error())
}
connectionThrottle, err := NewConnectionThrottle(config.Server.ConnectionThrottle)
if err != nil {
log.Fatal("Error loading connection throttler:", err.Error())
}
server := &Server{
accounts: make(map[string]*ClientAccount),
@ -166,6 +172,7 @@ func NewServer(configFilename string, config *Config) *Server {
commands: make(chan Command),
configFilename: configFilename,
connectionLimits: connectionLimits,
connectionThrottle: connectionThrottle,
ctime: time.Now(),
currentOpers: make(map[*Client]bool),
idle: make(chan *Client),
@ -403,6 +410,27 @@ func (server *Server) Run() {
continue
}
// check connection throttle
server.connectionThrottleMutex.Lock()
err = server.connectionThrottle.AddClient(ipaddr)
server.connectionThrottleMutex.Unlock()
if err != nil {
// too many connections too quickly from client, tell them and close the connection
length := &IPRestrictTime{
Duration: server.connectionThrottle.BanDuration,
Expires: time.Now().Add(server.connectionThrottle.BanDuration),
}
server.dlines.AddIP(ipaddr, length, server.connectionThrottle.BanMessage, "Exceeded automated connection throttle")
// reset ban on connectionThrottle
server.connectionThrottle.ResetFor(ipaddr)
// this might not show up properly on some clients, but our objective here is just to close it out before it has a load impact on us
conn.Conn.Write([]byte(server.connectionThrottle.BanMessageBytes))
conn.Conn.Close()
continue
}
go NewClient(server, conn.Conn, conn.IsTLS)
continue
}
@ -1066,23 +1094,29 @@ func (server *Server) rehash() error {
config, err := LoadConfig(server.configFilename)
if err != nil {
return fmt.Errorf("Error rehashing config file: %s", err.Error())
return fmt.Errorf("Error rehashing config file config: %s", err.Error())
}
// confirm connectionLimits are fine
connectionLimits, err := NewConnectionLimits(config.Server.ConnectionLimits)
if err != nil {
return fmt.Errorf("Error rehashing config file: %s", err.Error())
return fmt.Errorf("Error rehashing config file connection-limits: %s", err.Error())
}
// confirm connectionThrottler is fine
connectionThrottle, err := NewConnectionThrottle(config.Server.ConnectionThrottle)
if err != nil {
return fmt.Errorf("Error rehashing config file connection-throttle: %s", err.Error())
}
// confirm operator stuff all exists and is fine
operclasses, err := config.OperatorClasses()
if err != nil {
return fmt.Errorf("Error rehashing config file: %s", err.Error())
return fmt.Errorf("Error rehashing config file operclasses: %s", err.Error())
}
opers, err := config.Operators(operclasses)
if err != nil {
return fmt.Errorf("Error rehashing config file: %s", err.Error())
return fmt.Errorf("Error rehashing config file opers: %s", err.Error())
}
for client := range server.currentOpers {
_, exists := opers[client.operName]
@ -1094,6 +1128,8 @@ func (server *Server) rehash() error {
// apply new connectionlimits
server.connectionLimitsMutex.Lock()
server.connectionLimits = connectionLimits
server.connectionThrottleMutex.Lock()
server.connectionThrottle = connectionThrottle
server.clients.ByNickMutex.RLock()
for _, client := range server.clients.ByNick {