diff options
author | Himbeer <himbeer@disroot.org> | 2024-11-17 16:39:09 +0100 |
---|---|---|
committer | Himbeer <himbeer@disroot.org> | 2024-11-17 16:39:09 +0100 |
commit | 3b344731fff17f3c5255f278f8f14879e7610f7d (patch) | |
tree | f92726ba8364a21e450ff4b53fedfd285ab253e5 | |
parent | d0d39d2f9f3abb68eec146376b3233c8bc7c1cfa (diff) |
Notify authentication backends of failed login attempts
Closes #157.
-rw-r--r-- | auth.go | 13 | ||||
-rw-r--r-- | auth_files.go | 10 | ||||
-rw-r--r-- | auth_mtpostgresql.go | 10 | ||||
-rw-r--r-- | auth_mtsqlite3.go | 10 | ||||
-rw-r--r-- | process.go | 8 |
5 files changed, 37 insertions, 14 deletions
@@ -2,7 +2,6 @@ package proxy import ( "errors" - "net" "strings" "time" ) @@ -66,9 +65,15 @@ type AuthBackend interface { Ban(addr, name string) error // Unban deletes a ban entry by network address or username. Unban(id string) error - // Banned reports whether a network address is banned. - // The result is true if an error is encountered. - Banned(addr *net.UDPAddr) bool + // Banned reports whether a network address or username is banned. + // The result is true if either identifier is banned + // or if an error is encountered. + Banned(addr, name string) bool + // RecordFail records an authentication failure regarding a certain + // network address and username. The implementation is not required + // to process this event in any way, but the intent is to allow + // rate limiting / brute-force protection to be implemented by plugins. + RecordFail(addr, name string, sudo bool) error // ImportBans adds or modifies ban entries in bulk. ImportBans(in []Ban) error // Export returns all ban entries or an error. diff --git a/auth_files.go b/auth_files.go index eb7a076..c6a4d5d 100644 --- a/auth_files.go +++ b/auth_files.go @@ -1,7 +1,6 @@ package proxy import ( - "net" "os" "time" ) @@ -164,10 +163,10 @@ func (a AuthFiles) Unban(id string) error { // Banned reports whether a network address is banned. // Error cases count as banned. -func (a AuthFiles) Banned(addr *net.UDPAddr) bool { +func (a AuthFiles) Banned(addr, name string) bool { os.Mkdir(Path("ban"), 0700) - _, err := os.Stat(Path("ban/", addr.IP.String())) + _, err := os.Stat(Path("ban/", addr)) if os.IsNotExist(err) { return false } @@ -175,6 +174,11 @@ func (a AuthFiles) Banned(addr *net.UDPAddr) bool { return true } +// RecordFail is a no-op. +func (a AuthFiles) RecordFail(addr, name string, sudo bool) error { + return nil +} + // ImportBans deletes all ban entries and adds the passed entries. func (a AuthFiles) ImportBans(in []Ban) error { os.Mkdir(Path("ban"), 0700) diff --git a/auth_mtpostgresql.go b/auth_mtpostgresql.go index dc7f2f3..790a30f 100644 --- a/auth_mtpostgresql.go +++ b/auth_mtpostgresql.go @@ -5,7 +5,6 @@ import ( "database/sql" "errors" "fmt" - "net" "os" "strings" "time" @@ -261,16 +260,21 @@ func (a *AuthMTPostgreSQL) Unban(id string) error { // Banned reports whether a network address is banned. // Error cases count as banned. -func (a *AuthMTPostgreSQL) Banned(addr *net.UDPAddr) bool { +func (a *AuthMTPostgreSQL) Banned(addr, name string) bool { bans, err := a.readBans() if err != nil { return true } - _, ok := bans[addr.IP.String()] + _, ok := bans[addr] return ok } +// RecordFail is a no-op. +func (a *AuthMTPostgreSQL) RecordFail(addr, name string, sudo bool) error { + return nil +} + // ImportBans adds the passed entries. func (a *AuthMTPostgreSQL) ImportBans(in []Ban) error { for _, b := range in { diff --git a/auth_mtsqlite3.go b/auth_mtsqlite3.go index fb340c5..3140e69 100644 --- a/auth_mtsqlite3.go +++ b/auth_mtsqlite3.go @@ -5,7 +5,6 @@ import ( "database/sql" "errors" "fmt" - "net" "os" "strings" "time" @@ -207,16 +206,21 @@ func (a *AuthMTSQLite3) Unban(id string) error { // Banned reports whether a network address is banned. // Error cases count as banned. -func (a *AuthMTSQLite3) Banned(addr *net.UDPAddr) bool { +func (a *AuthMTSQLite3) Banned(addr, name string) bool { bans, err := a.readBans() if err != nil { return true } - _, ok := bans[addr.IP.String()] + _, ok := bans[addr] return ok } +// RecordFail is a no-op. +func (a *AuthMTSQLite3) RecordFail(addr, name string, sudo bool) error { + return nil +} + // ImportBans adds the passed entries. func (a *AuthMTSQLite3) ImportBans(in []Ban) error { for _, b := range in { @@ -88,7 +88,8 @@ func (cc *ClientConn) process(pkt mt.Pkt) { cc.name = cmd.PlayerName cc.logger.SetPrefix(fmt.Sprintf("[%s %s] ", cc.RemoteAddr(), cc.Name())) - if DefaultAuth().Banned(cc.RemoteAddr().(*net.UDPAddr)) { + ip := cc.RemoteAddr().(*net.UDPAddr).IP.String() + if DefaultAuth().Banned(ip, cc.Name()) { cc.Log("<-", "banned") cc.Kick("Banned by proxy.") return @@ -339,6 +340,11 @@ func (cc *ClientConn) process(pkt mt.Pkt) { }) } } else { + ip := cc.RemoteAddr().(*net.UDPAddr).IP.String() + if err := DefaultAuth().RecordFail(ip, cc.Name(), wantSudo); err != nil { + cc.Log("<-", "record auth fail:", err) + } + if wantSudo { cc.Log("<-", "invalid password (sudo)") cc.SendCmd(&mt.ToCltDenySudoMode{}) |