mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 17:12:13 -06:00
ftp: ban password-bruteforcing IPs
This commit is contained in:
parent
ab655a56af
commit
d326ba9723
|
@ -15,7 +15,7 @@ from pyftpdlib.servers import FTPServer
|
|||
|
||||
from .__init__ import PY2, TYPE_CHECKING, E
|
||||
from .bos import bos
|
||||
from .util import Daemon, Pebkac, exclude_dotfiles, fsenc
|
||||
from .util import Daemon, Pebkac, exclude_dotfiles, fsenc, ipnorm
|
||||
|
||||
try:
|
||||
from pyftpdlib.ioloop import IOLoop
|
||||
|
@ -42,21 +42,41 @@ class FtpAuth(DummyAuthorizer):
|
|||
def validate_authentication(
|
||||
self, username: str, password: str, handler: Any
|
||||
) -> None:
|
||||
handler.username = "{}:{}".format(username, password)
|
||||
|
||||
ip = handler.addr[0]
|
||||
if ip.startswith("::ffff:"):
|
||||
ip = ip[7:]
|
||||
|
||||
ip = ipnorm(ip)
|
||||
bans = self.hub.bans
|
||||
if ip in bans:
|
||||
rt = bans[ip] - time.time()
|
||||
if rt < 0:
|
||||
logging.info("client unbanned")
|
||||
del bans[ip]
|
||||
else:
|
||||
raise AuthenticationFailed("banned")
|
||||
|
||||
asrv = self.hub.asrv
|
||||
if username == "anonymous":
|
||||
password = ""
|
||||
uname = "*"
|
||||
else:
|
||||
creds = password or username
|
||||
uname = asrv.iacct.get(creds, "") if creds else "*"
|
||||
|
||||
uname = "*"
|
||||
if password:
|
||||
uname = asrv.iacct.get(password, "")
|
||||
if not uname or not (asrv.vfs.aread.get(uname) or asrv.vfs.awrite.get(uname)):
|
||||
g = self.hub.gpwd
|
||||
if g.lim:
|
||||
bonk, ip = g.bonk(ip, handler.username)
|
||||
if bonk:
|
||||
logging.warning("client banned: invalid passwords")
|
||||
bans[ip] = bonk
|
||||
|
||||
raise AuthenticationFailed("Authentication failed.")
|
||||
|
||||
handler.username = uname
|
||||
|
||||
if (password and not uname) or not (
|
||||
asrv.vfs.aread.get(uname) or asrv.vfs.awrite.get(uname)
|
||||
):
|
||||
raise AuthenticationFailed("Authentication failed.")
|
||||
|
||||
def get_home_dir(self, username: str) -> str:
|
||||
return "/"
|
||||
|
||||
|
|
|
@ -35,6 +35,7 @@ from .up2k import Up2k
|
|||
from .util import (
|
||||
VERSIONS,
|
||||
Daemon,
|
||||
Garda,
|
||||
HLog,
|
||||
HMaccas,
|
||||
alltrace,
|
||||
|
@ -85,6 +86,11 @@ class SvcHub(object):
|
|||
|
||||
self.iphash = HMaccas(os.path.join(self.E.cfg, "iphash"), 8)
|
||||
|
||||
# for non-http clients (ftp)
|
||||
self.bans: dict[str, int] = {}
|
||||
self.gpwd = Garda(self.args.ban_pw)
|
||||
self.g404 = Garda(self.args.ban_404)
|
||||
|
||||
if args.sss or args.s >= 3:
|
||||
args.ss = True
|
||||
args.no_dav = True
|
||||
|
|
|
@ -412,8 +412,12 @@ class HLog(logging.Handler):
|
|||
if record.name == "pyftpdlib":
|
||||
m = self.ptn_ftp.match(msg)
|
||||
if m:
|
||||
record.name = ip = m.group(1)
|
||||
ip = m.group(1)
|
||||
msg = msg[len(ip) + 1 :]
|
||||
if ip.startswith("::ffff:"):
|
||||
record.name = ip[7:]
|
||||
else:
|
||||
record.name = ip
|
||||
elif record.name.startswith("impacket"):
|
||||
if self.ptn_smb_ign.match(msg):
|
||||
return
|
||||
|
|
Loading…
Reference in a new issue