|
@@ -28,7 +28,7 @@ import (
|
28
|
28
|
|
29
|
29
|
var (
|
30
|
30
|
// cached because this may be used lots
|
31
|
|
- tooManyClientsMsg = ircmsg.MakeMessage(nil, "", "ERROR", "Too many clients from your IP or network")
|
|
31
|
+ tooManyClientsMsg = ircmsg.MakeMessage(nil, "", "ERROR", "Too many clients from your network")
|
32
|
32
|
tooManyClientsBytes, _ = tooManyClientsMsg.Line()
|
33
|
33
|
|
34
|
34
|
bannedFromServerMsg = ircmsg.MakeMessage(nil, "", "ERROR", "You are banned from this server (%s)")
|
|
@@ -72,42 +72,44 @@ type ListenerEvent struct {
|
72
|
72
|
|
73
|
73
|
// Server is the main Oragono server.
|
74
|
74
|
type Server struct {
|
75
|
|
- accountRegistration *AccountRegistration
|
76
|
|
- accounts map[string]*ClientAccount
|
77
|
|
- authenticationEnabled bool
|
78
|
|
- channels ChannelNameMap
|
79
|
|
- checkIdent bool
|
80
|
|
- clients *ClientLookupSet
|
81
|
|
- commands chan Command
|
82
|
|
- configFilename string
|
83
|
|
- connectionLimits *ConnectionLimits
|
84
|
|
- connectionLimitsMutex sync.Mutex // used when affecting the connection limiter, to make sure rehashing doesn't make things go out-of-whack
|
85
|
|
- ctime time.Time
|
86
|
|
- currentOpers map[*Client]bool
|
87
|
|
- dlines *DLineManager
|
88
|
|
- idle chan *Client
|
89
|
|
- isupport *ISupportList
|
90
|
|
- klines *KLineManager
|
91
|
|
- limits Limits
|
92
|
|
- listenerEventActMutex sync.Mutex
|
93
|
|
- listeners map[string]ListenerInterface
|
94
|
|
- listenerUpdateMutex sync.Mutex
|
95
|
|
- monitoring map[string][]Client
|
96
|
|
- motdLines []string
|
97
|
|
- name string
|
98
|
|
- nameCasefolded string
|
99
|
|
- networkName string
|
100
|
|
- newConns chan clientConn
|
101
|
|
- operators map[string]Oper
|
102
|
|
- operclasses map[string]OperClass
|
103
|
|
- password []byte
|
104
|
|
- passwords *PasswordManager
|
105
|
|
- rehashMutex sync.Mutex
|
106
|
|
- rehashSignal chan os.Signal
|
107
|
|
- restAPI *RestAPIConfig
|
108
|
|
- signals chan os.Signal
|
109
|
|
- store *buntdb.DB
|
110
|
|
- whoWas *WhoWasList
|
|
75
|
+ accountRegistration *AccountRegistration
|
|
76
|
+ accounts map[string]*ClientAccount
|
|
77
|
+ authenticationEnabled bool
|
|
78
|
+ channels ChannelNameMap
|
|
79
|
+ checkIdent bool
|
|
80
|
+ clients *ClientLookupSet
|
|
81
|
+ commands chan Command
|
|
82
|
+ configFilename string
|
|
83
|
+ connectionThrottle *ConnectionThrottle
|
|
84
|
+ connectionThrottleMutex sync.Mutex // used when affecting the connection limiter, to make sure rehashing doesn't make things go out-of-whack
|
|
85
|
+ connectionLimits *ConnectionLimits
|
|
86
|
+ connectionLimitsMutex sync.Mutex // used when affecting the connection limiter, to make sure rehashing doesn't make things go out-of-whack
|
|
87
|
+ ctime time.Time
|
|
88
|
+ currentOpers map[*Client]bool
|
|
89
|
+ dlines *DLineManager
|
|
90
|
+ idle chan *Client
|
|
91
|
+ isupport *ISupportList
|
|
92
|
+ klines *KLineManager
|
|
93
|
+ limits Limits
|
|
94
|
+ listenerEventActMutex sync.Mutex
|
|
95
|
+ listeners map[string]ListenerInterface
|
|
96
|
+ listenerUpdateMutex sync.Mutex
|
|
97
|
+ monitoring map[string][]Client
|
|
98
|
+ motdLines []string
|
|
99
|
+ name string
|
|
100
|
+ nameCasefolded string
|
|
101
|
+ networkName string
|
|
102
|
+ newConns chan clientConn
|
|
103
|
+ operators map[string]Oper
|
|
104
|
+ operclasses map[string]OperClass
|
|
105
|
+ password []byte
|
|
106
|
+ passwords *PasswordManager
|
|
107
|
+ rehashMutex sync.Mutex
|
|
108
|
+ rehashSignal chan os.Signal
|
|
109
|
+ restAPI *RestAPIConfig
|
|
110
|
+ signals chan os.Signal
|
|
111
|
+ store *buntdb.DB
|
|
112
|
+ whoWas *WhoWasList
|
111
|
113
|
}
|
112
|
114
|
|
113
|
115
|
var (
|
|
@@ -157,6 +159,10 @@ func NewServer(configFilename string, config *Config) *Server {
|
157
|
159
|
if err != nil {
|
158
|
160
|
log.Fatal("Error loading connection limits:", err.Error())
|
159
|
161
|
}
|
|
162
|
+ connectionThrottle, err := NewConnectionThrottle(config.Server.ConnectionThrottle)
|
|
163
|
+ if err != nil {
|
|
164
|
+ log.Fatal("Error loading connection throttler:", err.Error())
|
|
165
|
+ }
|
160
|
166
|
|
161
|
167
|
server := &Server{
|
162
|
168
|
accounts: make(map[string]*ClientAccount),
|
|
@@ -166,6 +172,7 @@ func NewServer(configFilename string, config *Config) *Server {
|
166
|
172
|
commands: make(chan Command),
|
167
|
173
|
configFilename: configFilename,
|
168
|
174
|
connectionLimits: connectionLimits,
|
|
175
|
+ connectionThrottle: connectionThrottle,
|
169
|
176
|
ctime: time.Now(),
|
170
|
177
|
currentOpers: make(map[*Client]bool),
|
171
|
178
|
idle: make(chan *Client),
|
|
@@ -403,6 +410,27 @@ func (server *Server) Run() {
|
403
|
410
|
continue
|
404
|
411
|
}
|
405
|
412
|
|
|
413
|
+ // check connection throttle
|
|
414
|
+ server.connectionThrottleMutex.Lock()
|
|
415
|
+ err = server.connectionThrottle.AddClient(ipaddr)
|
|
416
|
+ server.connectionThrottleMutex.Unlock()
|
|
417
|
+ if err != nil {
|
|
418
|
+ // too many connections too quickly from client, tell them and close the connection
|
|
419
|
+ length := &IPRestrictTime{
|
|
420
|
+ Duration: server.connectionThrottle.BanDuration,
|
|
421
|
+ Expires: time.Now().Add(server.connectionThrottle.BanDuration),
|
|
422
|
+ }
|
|
423
|
+ server.dlines.AddIP(ipaddr, length, server.connectionThrottle.BanMessage, "Exceeded automated connection throttle")
|
|
424
|
+
|
|
425
|
+ // reset ban on connectionThrottle
|
|
426
|
+ server.connectionThrottle.ResetFor(ipaddr)
|
|
427
|
+
|
|
428
|
+ // 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
|
|
429
|
+ conn.Conn.Write([]byte(server.connectionThrottle.BanMessageBytes))
|
|
430
|
+ conn.Conn.Close()
|
|
431
|
+ continue
|
|
432
|
+ }
|
|
433
|
+
|
406
|
434
|
go NewClient(server, conn.Conn, conn.IsTLS)
|
407
|
435
|
continue
|
408
|
436
|
}
|
|
@@ -1066,23 +1094,29 @@ func (server *Server) rehash() error {
|
1066
|
1094
|
config, err := LoadConfig(server.configFilename)
|
1067
|
1095
|
|
1068
|
1096
|
if err != nil {
|
1069
|
|
- return fmt.Errorf("Error rehashing config file: %s", err.Error())
|
|
1097
|
+ return fmt.Errorf("Error rehashing config file config: %s", err.Error())
|
1070
|
1098
|
}
|
1071
|
1099
|
|
1072
|
1100
|
// confirm connectionLimits are fine
|
1073
|
1101
|
connectionLimits, err := NewConnectionLimits(config.Server.ConnectionLimits)
|
1074
|
1102
|
if err != nil {
|
1075
|
|
- return fmt.Errorf("Error rehashing config file: %s", err.Error())
|
|
1103
|
+ return fmt.Errorf("Error rehashing config file connection-limits: %s", err.Error())
|
|
1104
|
+ }
|
|
1105
|
+
|
|
1106
|
+ // confirm connectionThrottler is fine
|
|
1107
|
+ connectionThrottle, err := NewConnectionThrottle(config.Server.ConnectionThrottle)
|
|
1108
|
+ if err != nil {
|
|
1109
|
+ return fmt.Errorf("Error rehashing config file connection-throttle: %s", err.Error())
|
1076
|
1110
|
}
|
1077
|
1111
|
|
1078
|
1112
|
// confirm operator stuff all exists and is fine
|
1079
|
1113
|
operclasses, err := config.OperatorClasses()
|
1080
|
1114
|
if err != nil {
|
1081
|
|
- return fmt.Errorf("Error rehashing config file: %s", err.Error())
|
|
1115
|
+ return fmt.Errorf("Error rehashing config file operclasses: %s", err.Error())
|
1082
|
1116
|
}
|
1083
|
1117
|
opers, err := config.Operators(operclasses)
|
1084
|
1118
|
if err != nil {
|
1085
|
|
- return fmt.Errorf("Error rehashing config file: %s", err.Error())
|
|
1119
|
+ return fmt.Errorf("Error rehashing config file opers: %s", err.Error())
|
1086
|
1120
|
}
|
1087
|
1121
|
for client := range server.currentOpers {
|
1088
|
1122
|
_, exists := opers[client.operName]
|
|
@@ -1094,6 +1128,8 @@ func (server *Server) rehash() error {
|
1094
|
1128
|
// apply new connectionlimits
|
1095
|
1129
|
server.connectionLimitsMutex.Lock()
|
1096
|
1130
|
server.connectionLimits = connectionLimits
|
|
1131
|
+ server.connectionThrottleMutex.Lock()
|
|
1132
|
+ server.connectionThrottle = connectionThrottle
|
1097
|
1133
|
|
1098
|
1134
|
server.clients.ByNickMutex.RLock()
|
1099
|
1135
|
for _, client := range server.clients.ByNick {
|