github.com/metaworking/channeld@v0.7.3/pkg/channeld/ddos.go (about) 1 package channeld 2 3 import ( 4 "sync" 5 "time" 6 7 "github.com/metaworking/channeld/pkg/channeldpb" 8 "go.uber.org/zap" 9 ) 10 11 var unauthenticatedConnections sync.Map 12 13 var failedAuthCounters = make(map[string]int) 14 var ipBlacklist = make(map[string]time.Time) 15 var pitBlacklist = make(map[string]time.Time) 16 17 func InitAntiDDoS() { 18 Event_AuthComplete.Listen(func(data AuthEventData) { 19 if data.Connection.GetConnectionType() == channeldpb.ConnectionType_SERVER { 20 return 21 } 22 23 if data.AuthResult == channeldpb.AuthResultMessage_INVALID_LT { 24 // Invalid access token - record the PIT 25 failedAuthCounters[data.PlayerIdentifierToken]++ 26 if GlobalSettings.MaxFailedAuthAttempts > 0 && failedAuthCounters[data.PlayerIdentifierToken] >= GlobalSettings.MaxFailedAuthAttempts { 27 pitBlacklist[data.PlayerIdentifierToken] = time.Now() 28 securityLogger.Info("blacklisted PIT due to too many failed auth attempts", zap.String("pit", data.PlayerIdentifierToken)) 29 data.Connection.Close() 30 } 31 } else if data.AuthResult == channeldpb.AuthResultMessage_INVALID_PIT { 32 // Invalid username token - record the IP 33 addr := data.Connection.RemoteAddr() 34 if addr == nil { 35 return 36 } 37 ip := GetIP(addr) 38 failedAuthCounters[ip]++ 39 if GlobalSettings.MaxFailedAuthAttempts > 0 && failedAuthCounters[ip] >= GlobalSettings.MaxFailedAuthAttempts { 40 ipBlacklist[ip] = time.Now() 41 securityLogger.Info("blacklisted IP due to too many failed auth attempts", zap.String("ip", ip)) 42 data.Connection.Close() 43 } 44 } 45 }) 46 47 // FSM disallowed - record the PIT 48 Event_FsmDisallowed.Listen(func(c *Connection) { 49 if c.GetConnectionType() == channeldpb.ConnectionType_SERVER { 50 return 51 } 52 53 c.fsmDisallowedCounter++ 54 if GlobalSettings.MaxFsmDisallowed > 0 && c.fsmDisallowedCounter >= GlobalSettings.MaxFsmDisallowed { 55 pitBlacklist[c.pit] = time.Now() 56 securityLogger.Info("blacklisted PIT due to too many FSM disallowed", zap.String("pit", c.pit)) 57 c.Close() 58 } 59 }) 60 61 go checkUnauthConns() 62 } 63 64 // Disconnection unauthenticated connections after ConnectionAuthTimeoutMs. 65 func checkUnauthConns() { 66 for { 67 unauthenticatedConnections.Range(func(_, v interface{}) bool { 68 conn := v.(*Connection) 69 if conn.IsClosing() { 70 return true 71 } 72 if conn.state == ConnectionState_UNAUTHENTICATED && time.Since(conn.connTime).Milliseconds() >= GlobalSettings.ConnectionAuthTimeoutMs { 73 ipBlacklist[GetIP(conn.RemoteAddr())] = time.Now() 74 conn.Close() 75 securityLogger.Info("closed and blacklisted unauthenticated connection due to timeout", zap.String("ip", conn.conn.RemoteAddr().String())) 76 } 77 return true 78 }) 79 80 time.Sleep(time.Millisecond * 500) 81 } 82 }