From 626b5770a53ee4b31209062cc3db91cddad5cb3c Mon Sep 17 00:00:00 2001 From: ed Date: Thu, 30 Nov 2023 23:36:46 +0000 Subject: [PATCH] add --ftp-ipa --- copyparty/__main__.py | 1 + copyparty/ftpd.py | 11 ++++++++++- copyparty/svchub.py | 21 ++++++++++----------- 3 files changed, 21 insertions(+), 12 deletions(-) diff --git a/copyparty/__main__.py b/copyparty/__main__.py index 4c9e13f4..36439513 100755 --- a/copyparty/__main__.py +++ b/copyparty/__main__.py @@ -971,6 +971,7 @@ def add_ftp(ap): ap2.add_argument("--ftps", metavar="PORT", type=int, help="enable FTPS server on \033[33mPORT\033[0m, for example \033[32m3990") ap2.add_argument("--ftpv", action="store_true", help="verbose") ap2.add_argument("--ftp4", action="store_true", help="only listen on IPv4") + ap2.add_argument("--ftp-ipa", metavar="PFX", type=u, default="", help="only accept connections from IP-addresses starting with \033[33mPFX\033[0m; specify [\033[32many\033[0m] to disable inheriting \033[33m--ipa\033[0m. Example: [\033[32m127., 10.89., 192.168.\033[0m]") ap2.add_argument("--ftp-wt", metavar="SEC", type=int, default=7, help="grace period for resuming interrupted uploads (any client can write to any file last-modified more recently than \033[33mSEC\033[0m seconds ago)") ap2.add_argument("--ftp-nat", metavar="ADDR", type=u, help="the NAT address to use for passive connections") ap2.add_argument("--ftp-pr", metavar="P-P", type=u, help="the range of TCP ports to use for passive connections, for example \033[32m12000-13000") diff --git a/copyparty/ftpd.py b/copyparty/ftpd.py index 3538be94..13bca7bf 100644 --- a/copyparty/ftpd.py +++ b/copyparty/ftpd.py @@ -404,7 +404,16 @@ class FtpHandler(FTPHandler): super(FtpHandler, self).__init__(conn, server, ioloop) cip = self.remote_ip - self.cli_ip = cip[7:] if cip.startswith("::ffff:") else cip + if cip.startswith("::ffff:"): + cip = cip[7:] + + if self.args.ftp_ipa_re and not self.args.ftp_ipa_re.match(cip): + logging.warning("client rejected (--ftp-ipa): %s", cip) + self.connected = False + conn.close() + return + + self.cli_ip = cip # abspath->vpath mapping to resolve log_transfer paths self.vfs_map: dict[str, str] = {} diff --git a/copyparty/svchub.py b/copyparty/svchub.py index c5ec4529..89efe6df 100644 --- a/copyparty/svchub.py +++ b/copyparty/svchub.py @@ -432,17 +432,9 @@ class SvcHub(object): elif al.ban_url == "no": al.sus_urls = None - if al.xff_src in ("any", "0", ""): - al.xff_re = None - else: - zs = al.xff_src.replace(" ", "").replace(".", "\\.").replace(",", "|") - al.xff_re = re.compile("^(?:" + zs + ")") - - if al.ipa in ("any", "0", ""): - al.ipa_re = None - else: - zs = al.ipa.replace(" ", "").replace(".", "\\.").replace(",", "|") - al.ipa_re = re.compile("^(?:" + zs + ")") + al.xff_re = self._ipa2re(al.xff_src) + al.ipa_re = self._ipa2re(al.ipa) + al.ftp_ipa_re = self._ipa2re(al.ftp_ipa or al.ipa) mte = ODict.fromkeys(DEF_MTE.split(","), True) al.mte = odfusion(mte, al.mte) @@ -461,6 +453,13 @@ class SvcHub(object): return True + def _ipa2re(self, txt) -> Optional[re.Pattern]: + if txt in ("any", "0", ""): + return None + + zs = txt.replace(" ", "").replace(".", "\\.").replace(",", "|") + return re.compile("^(?:" + zs + ")") + def _setlimits(self) -> None: try: import resource