mirror of
https://github.com/9001/copyparty.git
synced 2026-08-13 13:53:06 -06:00
sftp: filter spam from portscanners (closes #1519);
also use a threadpool for accepting clients, to avoid spinning up a new thread for each hit from a portscanner
This commit is contained in:
parent
32d074ffc5
commit
8c4e931300
|
|
@ -1507,6 +1507,8 @@ def add_sftp(ap):
|
|||
ap2.add_argument("--sftp-hostk", metavar="FP", type=u, default=E.cfg, help="path to folder with hostkeys, for example 'ssh_host_rsa_key'; missing keys will be generated")
|
||||
ap2.add_argument("--sftp-banner", metavar="T", type=u, default="", help="bannertext to send when someone connects; can be @filepath")
|
||||
ap2.add_argument("--sftp-ipa", metavar="CIDR", type=u, default="", help="only accept connections from IP-addresses inside \033[33mCIDR\033[0m (comma-separated); specify [\033[32many\033[0m] to disable inheriting \033[33m--ipa\033[0m / \033[33m--ipar\033[0m. Examples: [\033[32mlan\033[0m] or [\033[32m10.89.0.0/16, 192.168.33.0/24\033[0m]")
|
||||
ap2.add_argument("--sftp-hs-t", metavar="SEC", type=int, default=15, help="connection handshake timeout in seconds")
|
||||
ap2.add_argument("--sftp-hs-n", metavar="NUM", type=int, default=4, help="max num ongoing/incomplete handshakes")
|
||||
|
||||
|
||||
def add_ftp(ap):
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ from paramiko.sftp import (
|
|||
SFTP_OP_UNSUPPORTED,
|
||||
SFTP_PERMISSION_DENIED,
|
||||
)
|
||||
from queue import Queue
|
||||
|
||||
from .__init__ import ANYWIN, TYPE_CHECKING
|
||||
from .authsrv import LEELOO_DALLAS, VFS, AuthSrv
|
||||
|
|
@ -736,6 +737,22 @@ class SFTP_Srv(paramiko.SFTPServerInterface):
|
|||
return "/%s" % (undot(path),)
|
||||
|
||||
|
||||
class Transport2(paramiko.Transport):
|
||||
def __init__(self, cli, addr):
|
||||
self.addr = addr
|
||||
super(Transport2, self).__init__(cli)
|
||||
|
||||
def _check_banner(self):
|
||||
try:
|
||||
return super()._check_banner()
|
||||
except Exception as ex:
|
||||
if "Error reading SSH protocol bann" in str(ex):
|
||||
self.logger.warning("%s rejected: %s" % (self.addr, ex))
|
||||
self.addr = None
|
||||
else:
|
||||
raise
|
||||
|
||||
|
||||
class Sftpd(object):
|
||||
def __init__(self, hub: "SvcHub") -> None:
|
||||
self.hub = hub
|
||||
|
|
@ -743,6 +760,7 @@ class Sftpd(object):
|
|||
self.log_func = hub.log
|
||||
self.srv: list[socket.socket] = []
|
||||
self.bound: list[str] = []
|
||||
self.hs_q = Queue()
|
||||
self.sessions = {}
|
||||
|
||||
ips = args.sftp_i
|
||||
|
|
@ -793,6 +811,9 @@ class Sftpd(object):
|
|||
|
||||
self.log("listening @ %s port %s" % (self.bound, args.sftp))
|
||||
|
||||
for n in range(self.args.sftp_hs_n):
|
||||
Daemon(self.acceptor, "sftp-hs-%d" % (n,))
|
||||
|
||||
def log(self, msg: str, c: Union[int, str] = 0) -> None:
|
||||
self.hub.log("sftp", msg, c)
|
||||
|
||||
|
|
@ -828,12 +849,18 @@ class Sftpd(object):
|
|||
cli, addr = srv.accept()
|
||||
# cli.settimeout(0) # == srv.setblocking(False)
|
||||
self.log("%r is connecting" % (addr,))
|
||||
zs = "sftp-%s" % (addr[0],)
|
||||
# Daemon(self._accept2, zs, (cli, addr))
|
||||
self._accept2(cli, addr)
|
||||
self.hs_q.put((cli, addr))
|
||||
|
||||
def acceptor(self) -> None:
|
||||
while True:
|
||||
try:
|
||||
cli, addr = self.hs_q.get()
|
||||
self._accept2(cli, addr)
|
||||
except:
|
||||
time.sleep(1)
|
||||
|
||||
def _accept2(self, cli, addr) -> None:
|
||||
tra = paramiko.Transport(cli)
|
||||
tra = Transport2(cli, addr)
|
||||
for hkey in self.hostkeys:
|
||||
tra.add_server_key(hkey)
|
||||
tra.set_subsystem_handler("sftp", paramiko.SFTPServer, SFTP_Srv)
|
||||
|
|
@ -841,11 +868,12 @@ class Sftpd(object):
|
|||
try:
|
||||
tra.start_server(server=psrv)
|
||||
except Exception as ex:
|
||||
self.log("%r could not establish connection: %r" % (addr, ex), 3)
|
||||
if tra.addr:
|
||||
self.log("%r could not establish connection: %r" % (addr, ex), 3)
|
||||
cli.close()
|
||||
return
|
||||
|
||||
chan = tra.accept()
|
||||
chan = tra.accept(timeout=self.args.sftp_hs_t)
|
||||
if chan is None:
|
||||
self.log("%r did not open an sftp channel" % (addr,), 3)
|
||||
cli.close()
|
||||
|
|
|
|||
Loading…
Reference in a new issue