diff --git a/irc/client.go b/irc/client.go index 340c298c..5c1298bd 100644 --- a/irc/client.go +++ b/irc/client.go @@ -542,7 +542,7 @@ func (client *Client) destroy() { ipaddr := client.IP() // this check shouldn't be required but eh if ipaddr != nil { - client.server.connectionLimits.RemoveClient(ipaddr) + client.server.connectionLimiter.RemoveClient(ipaddr) } // alert monitors diff --git a/irc/config.go b/irc/config.go index 92e98ab0..6eaa2be4 100644 --- a/irc/config.go +++ b/irc/config.go @@ -15,7 +15,7 @@ import ( "time" "code.cloudfoundry.org/bytefmt" - "github.com/oragono/oragono/irc/connection_limiting" + "github.com/oragono/oragono/irc/connection_limits" "github.com/oragono/oragono/irc/custime" "github.com/oragono/oragono/irc/logger" "github.com/oragono/oragono/irc/passwd" @@ -151,19 +151,19 @@ type Config struct { Server struct { PassConfig - Password string - Name string - Listen []string - TLSListeners map[string]*TLSListenConfig `yaml:"tls-listeners"` - STS STSConfig - CheckIdent bool `yaml:"check-ident"` - MOTD string - MOTDFormatting bool `yaml:"motd-formatting"` - ProxyAllowedFrom []string `yaml:"proxy-allowed-from"` - MaxSendQString string `yaml:"max-sendq"` - MaxSendQBytes uint64 - ConnectionLimits connection_limiting.ConnectionLimitsConfig `yaml:"connection-limits"` - ConnectionThrottle connection_limiting.ConnectionThrottleConfig `yaml:"connection-throttling"` + Password string + Name string + Listen []string + TLSListeners map[string]*TLSListenConfig `yaml:"tls-listeners"` + STS STSConfig + CheckIdent bool `yaml:"check-ident"` + MOTD string + MOTDFormatting bool `yaml:"motd-formatting"` + ProxyAllowedFrom []string `yaml:"proxy-allowed-from"` + MaxSendQString string `yaml:"max-sendq"` + MaxSendQBytes uint64 + ConnectionLimiter connection_limits.LimiterConfig `yaml:"connection-limits"` + ConnectionThrottler connection_limits.ThrottlerConfig `yaml:"connection-throttling"` } Datastore struct { @@ -383,12 +383,12 @@ func LoadConfig(filename string) (config *Config, err error) { return nil, fmt.Errorf("STS port is incorrect, should be 0 if disabled: %d", config.Server.STS.Port) } } - if config.Server.ConnectionThrottle.Enabled { - config.Server.ConnectionThrottle.Duration, err = time.ParseDuration(config.Server.ConnectionThrottle.DurationString) + if config.Server.ConnectionThrottler.Enabled { + config.Server.ConnectionThrottler.Duration, err = time.ParseDuration(config.Server.ConnectionThrottler.DurationString) if err != nil { return nil, fmt.Errorf("Could not parse connection-throttle duration: %s", err.Error()) } - config.Server.ConnectionThrottle.BanDuration, err = time.ParseDuration(config.Server.ConnectionThrottle.BanDurationString) + config.Server.ConnectionThrottler.BanDuration, err = time.ParseDuration(config.Server.ConnectionThrottler.BanDurationString) if err != nil { return nil, fmt.Errorf("Could not parse connection-throttle ban-duration: %s", err.Error()) } diff --git a/irc/connection_limiting/limits.go b/irc/connection_limits/limiter.go similarity index 83% rename from irc/connection_limiting/limits.go rename to irc/connection_limits/limiter.go index 3402a452..11d1d666 100644 --- a/irc/connection_limiting/limits.go +++ b/irc/connection_limits/limiter.go @@ -1,7 +1,7 @@ // Copyright (c) 2016-2017 Daniel Oaks // released under the MIT license -package connection_limiting +package connection_limits import ( "errors" @@ -10,8 +10,8 @@ import ( "sync" ) -// ConnectionLimitsConfig controls the automated connection limits. -type ConnectionLimitsConfig struct { +// LimiterConfig controls the automated connection limits. +type LimiterConfig struct { Enabled bool CidrLenIPv4 int `yaml:"cidr-len-ipv4"` CidrLenIPv6 int `yaml:"cidr-len-ipv6"` @@ -23,8 +23,8 @@ var ( errTooManyClients = errors.New("Too many clients in subnet") ) -// ConnectionLimits manages the automated client connection limits. -type ConnectionLimits struct { +// Limiter manages the automated client connection limits. +type Limiter struct { sync.Mutex enabled bool @@ -42,7 +42,7 @@ type ConnectionLimits struct { } // maskAddr masks the given IPv4/6 address with our cidr limit masks. -func (cl *ConnectionLimits) maskAddr(addr net.IP) net.IP { +func (cl *Limiter) maskAddr(addr net.IP) net.IP { if addr.To4() == nil { // IPv6 addr addr = addr.Mask(cl.ipv6Mask) @@ -56,7 +56,7 @@ func (cl *ConnectionLimits) maskAddr(addr net.IP) net.IP { // AddClient adds a client to our population if possible. If we can't, throws an error instead. // 'force' is used to add already-existing clients (i.e. ones that are already on the network). -func (cl *ConnectionLimits) AddClient(addr net.IP, force bool) error { +func (cl *Limiter) AddClient(addr net.IP, force bool) error { cl.Lock() defer cl.Unlock() @@ -89,7 +89,7 @@ func (cl *ConnectionLimits) AddClient(addr net.IP, force bool) error { } // RemoveClient removes the given address from our population -func (cl *ConnectionLimits) RemoveClient(addr net.IP) { +func (cl *Limiter) RemoveClient(addr net.IP) { cl.Lock() defer cl.Unlock() @@ -106,10 +106,10 @@ func (cl *ConnectionLimits) RemoveClient(addr net.IP) { } } -// NewConnectionLimits returns a new connection limit handler. +// NewLimiter returns a new connection limit handler. // The handler is functional, but disabled; it can be enabled via `ApplyConfig`. -func NewConnectionLimits() *ConnectionLimits { - var cl ConnectionLimits +func NewLimiter() *Limiter { + var cl Limiter // initialize empty population; all other state is configurable cl.population = make(map[string]int) @@ -118,7 +118,7 @@ func NewConnectionLimits() *ConnectionLimits { } // ApplyConfig atomically applies a config update to a connection limit handler -func (cl *ConnectionLimits) ApplyConfig(config ConnectionLimitsConfig) error { +func (cl *Limiter) ApplyConfig(config LimiterConfig) error { // assemble exempted nets exemptedIPs := make(map[string]bool) var exemptedNets []net.IPNet diff --git a/irc/connection_limiting/throttle.go b/irc/connection_limits/throttler.go similarity index 82% rename from irc/connection_limiting/throttle.go rename to irc/connection_limits/throttler.go index 91925217..aa29d241 100644 --- a/irc/connection_limiting/throttle.go +++ b/irc/connection_limits/throttler.go @@ -1,7 +1,7 @@ // Copyright (c) 2016-2017 Daniel Oaks // released under the MIT license -package connection_limiting +package connection_limits import ( "fmt" @@ -10,8 +10,8 @@ import ( "time" ) -// ConnectionThrottleConfig controls the automated connection throttling. -type ConnectionThrottleConfig struct { +// ThrottlerConfig controls the automated connection throttling. +type ThrottlerConfig struct { Enabled bool CidrLenIPv4 int `yaml:"cidr-len-ipv4"` CidrLenIPv6 int `yaml:"cidr-len-ipv6"` @@ -30,8 +30,8 @@ type ThrottleDetails struct { ClientCount int } -// ConnectionThrottle manages automated client connection throttling. -type ConnectionThrottle struct { +// Throttler manages automated client connection throttling. +type Throttler struct { sync.RWMutex enabled bool @@ -52,7 +52,7 @@ type ConnectionThrottle struct { } // maskAddr masks the given IPv4/6 address with our cidr limit masks. -func (ct *ConnectionThrottle) maskAddr(addr net.IP) net.IP { +func (ct *Throttler) maskAddr(addr net.IP) net.IP { if addr.To4() == nil { // IPv6 addr addr = addr.Mask(ct.ipv6Mask) @@ -65,7 +65,7 @@ func (ct *ConnectionThrottle) maskAddr(addr net.IP) net.IP { } // ResetFor removes any existing count for the given address. -func (ct *ConnectionThrottle) ResetFor(addr net.IP) { +func (ct *Throttler) ResetFor(addr net.IP) { ct.Lock() defer ct.Unlock() @@ -80,7 +80,7 @@ func (ct *ConnectionThrottle) ResetFor(addr net.IP) { } // AddClient introduces a new client connection if possible. If we can't, throws an error instead. -func (ct *ConnectionThrottle) AddClient(addr net.IP) error { +func (ct *Throttler) AddClient(addr net.IP) error { ct.Lock() defer ct.Unlock() @@ -119,24 +119,24 @@ func (ct *ConnectionThrottle) AddClient(addr net.IP) error { return nil } -func (ct *ConnectionThrottle) BanDuration() time.Duration { +func (ct *Throttler) BanDuration() time.Duration { ct.RLock() defer ct.RUnlock() return ct.banDuration } -func (ct *ConnectionThrottle) BanMessage() string { +func (ct *Throttler) BanMessage() string { ct.RLock() defer ct.RUnlock() return ct.banMessage } -// NewConnectionThrottle returns a new client connection throttler. +// NewThrottler returns a new client connection throttler. // The throttler is functional, but disabled; it can be enabled via `ApplyConfig`. -func NewConnectionThrottle() *ConnectionThrottle { - var ct ConnectionThrottle +func NewThrottler() *Throttler { + var ct Throttler // initialize empty population; all other state is configurable ct.population = make(map[string]ThrottleDetails) @@ -145,7 +145,7 @@ func NewConnectionThrottle() *ConnectionThrottle { } // ApplyConfig atomically applies a config update to a throttler -func (ct *ConnectionThrottle) ApplyConfig(config ConnectionThrottleConfig) error { +func (ct *Throttler) ApplyConfig(config ThrottlerConfig) error { // assemble exempted nets exemptedIPs := make(map[string]bool) var exemptedNets []net.IPNet diff --git a/irc/server.go b/irc/server.go index bf1fe26c..c419b190 100644 --- a/irc/server.go +++ b/irc/server.go @@ -24,7 +24,7 @@ import ( "github.com/goshuirc/irc-go/ircfmt" "github.com/goshuirc/irc-go/ircmsg" "github.com/oragono/oragono/irc/caps" - "github.com/oragono/oragono/irc/connection_limiting" + "github.com/oragono/oragono/irc/connection_limits" "github.com/oragono/oragono/irc/isupport" "github.com/oragono/oragono/irc/logger" "github.com/oragono/oragono/irc/passwd" @@ -87,8 +87,8 @@ type Server struct { commands chan Command configFilename string configurableStateMutex sync.RWMutex // generic protection for server state modified by rehash() - connectionLimits *connection_limiting.ConnectionLimits - connectionThrottle *connection_limiting.ConnectionThrottle + connectionLimiter *connection_limits.Limiter + connectionThrottler *connection_limits.Throttler ctime time.Time defaultChannelModes Modes dlines *DLineManager @@ -144,21 +144,21 @@ func NewServer(config *Config, logger *logger.Manager) (*Server, error) { // initialize data structures server := &Server{ - accounts: make(map[string]*ClientAccount), - channels: *NewChannelNameMap(), - clients: NewClientLookupSet(), - commands: make(chan Command), - connectionLimits: connection_limiting.NewConnectionLimits(), - connectionThrottle: connection_limiting.NewConnectionThrottle(), - listeners: make(map[string]*ListenerWrapper), - logger: logger, - monitorManager: NewMonitorManager(), - newConns: make(chan clientConn), - registeredChannels: make(map[string]*RegisteredChannel), - rehashSignal: make(chan os.Signal, 1), - signals: make(chan os.Signal, len(ServerExitSignals)), - snomasks: NewSnoManager(), - whoWas: NewWhoWasList(config.Limits.WhowasEntries), + accounts: make(map[string]*ClientAccount), + channels: *NewChannelNameMap(), + clients: NewClientLookupSet(), + commands: make(chan Command), + connectionLimiter: connection_limits.NewLimiter(), + connectionThrottler: connection_limits.NewThrottler(), + listeners: make(map[string]*ListenerWrapper), + logger: logger, + monitorManager: NewMonitorManager(), + newConns: make(chan clientConn), + registeredChannels: make(map[string]*RegisteredChannel), + rehashSignal: make(chan os.Signal, 1), + signals: make(chan os.Signal, len(ServerExitSignals)), + snomasks: NewSnoManager(), + whoWas: NewWhoWasList(config.Limits.WhowasEntries), } if err := server.applyConfig(config, true); err != nil { @@ -303,7 +303,7 @@ func (server *Server) checkBans(ipaddr net.IP) (banned bool, message string) { } // check connection limits - err := server.connectionLimits.AddClient(ipaddr, false) + err := server.connectionLimiter.AddClient(ipaddr, false) if err != nil { // too many connections from one client, tell the client and close the connection server.logger.Info("localconnect-ip", fmt.Sprintf("Client from %v rejected for connection limit", ipaddr)) @@ -311,25 +311,25 @@ func (server *Server) checkBans(ipaddr net.IP) (banned bool, message string) { } // check connection throttle - err = server.connectionThrottle.AddClient(ipaddr) + err = server.connectionThrottler.AddClient(ipaddr) if err != nil { // too many connections too quickly from client, tell them and close the connection - duration := server.connectionThrottle.BanDuration() + duration := server.connectionThrottler.BanDuration() length := &IPRestrictTime{ Duration: duration, Expires: time.Now().Add(duration), } - server.dlines.AddIP(ipaddr, length, server.connectionThrottle.BanMessage(), "Exceeded automated connection throttle") + server.dlines.AddIP(ipaddr, length, server.connectionThrottler.BanMessage(), "Exceeded automated connection throttle") // they're DLINE'd for 15 minutes or whatever, so we can reset the connection throttle now, // and once their temporary DLINE is finished they can fill up the throttler again - server.connectionThrottle.ResetFor(ipaddr) + server.connectionThrottler.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 server.logger.Info( "localconnect-ip", fmt.Sprintf("Client from %v exceeded connection throttle, d-lining for %v", ipaddr, duration)) - return true, server.connectionThrottle.BanMessage() + return true, server.connectionThrottler.BanMessage() } return false, "" @@ -1263,12 +1263,12 @@ func (server *Server) applyConfig(config *Config, initial bool) error { // apply new PROXY command restrictions server.proxyAllowedFrom = config.Server.ProxyAllowedFrom - err = server.connectionLimits.ApplyConfig(config.Server.ConnectionLimits) + err = server.connectionLimiter.ApplyConfig(config.Server.ConnectionLimiter) if err != nil { return err } - err = server.connectionThrottle.ApplyConfig(config.Server.ConnectionThrottle) + err = server.connectionThrottler.ApplyConfig(config.Server.ConnectionThrottler) if err != nil { return err }