mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 00:52:16 -06:00
ftpd: add ftps
This commit is contained in:
parent
76beaae7f2
commit
6ce0e2cd5b
|
@ -54,6 +54,7 @@ turn your phone or raspi into a portable file server with resumable uploads/down
|
|||
* [other tricks](#other-tricks)
|
||||
* [searching](#searching) - search by size, date, path/name, mp3-tags, ...
|
||||
* [server config](#server-config) - using arguments or config files, or a mix of both
|
||||
* [ftp-server](#ftp-server) - an FTP server can be started using `--ftp 3921`
|
||||
* [file indexing](#file-indexing)
|
||||
* [upload rules](#upload-rules) - set upload rules using volume flags
|
||||
* [compress uploads](#compress-uploads) - files can be autocompressed on upload
|
||||
|
@ -626,12 +627,13 @@ using arguments or config files, or a mix of both:
|
|||
|
||||
## ftp-server
|
||||
|
||||
an FTP server can be started using `--ftp 3921` (or any other port)
|
||||
an FTP server can be started using `--ftp 3921`, and/or `--ftps` for explicit TLS (ftpes)
|
||||
|
||||
* based on [pyftpdlib](https://github.com/giampaolo/pyftpdlib)
|
||||
* needs a dedicated port (cannot share with the HTTP/HTTPS API)
|
||||
* runs in active mode by default, you probably want `--ftp-r`
|
||||
* uploads are not resumable
|
||||
* uploads are not resumable -- delete and restart if necessary
|
||||
* runs in active mode by default, you probably want `--ftp-pr 12000-13000`
|
||||
* if you enable both `ftp` and `ftps`, the port-range will be divided in half
|
||||
|
||||
|
||||
## file indexing
|
||||
|
|
|
@ -447,9 +447,10 @@ def run_argparse(argv, formatter):
|
|||
|
||||
ap2 = ap.add_argument_group('FTP options')
|
||||
ap2.add_argument("--ftp", metavar="PORT", type=int, help="enable FTP server on PORT, for example 3921")
|
||||
ap2.add_argument("--ftps", metavar="PORT", type=int, help="enable FTPS server on PORT, for example 3990")
|
||||
ap2.add_argument("--ftp-dbg", action="store_true", help="enable debug logging")
|
||||
ap2.add_argument("--ftp-nat", metavar="ADDR", type=u, help="the NAT address to use for passive connections")
|
||||
ap2.add_argument("--ftp-r", metavar="P-P", type=u, help="the range of TCP ports to use for passive connections, for example 12000-13000")
|
||||
ap2.add_argument("--ftp-pr", metavar="P-P", type=u, help="the range of TCP ports to use for passive connections, for example 12000-13000")
|
||||
|
||||
ap2 = ap.add_argument_group('opt-outs')
|
||||
ap2.add_argument("-nw", action="store_true", help="disable writes (benchmark)")
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
from __future__ import print_function, unicode_literals
|
||||
|
||||
import os
|
||||
import sys
|
||||
import stat
|
||||
import time
|
||||
import logging
|
||||
|
@ -14,6 +15,7 @@ from pyftpdlib.servers import FTPServer
|
|||
from pyftpdlib.ioloop import IOLoop
|
||||
from pyftpdlib.log import config_logging
|
||||
|
||||
from .__init__ import E
|
||||
from .util import Pebkac, fsenc, exclude_dotfiles
|
||||
from .bos import bos
|
||||
from .authsrv import AuthSrv
|
||||
|
@ -275,30 +277,67 @@ class FtpHandler(FTPHandler):
|
|||
)
|
||||
|
||||
|
||||
try:
|
||||
from pyftpdlib.handlers import TLS_FTPHandler
|
||||
|
||||
class SftpHandler(FtpHandler, TLS_FTPHandler):
|
||||
pass
|
||||
|
||||
except:
|
||||
pass
|
||||
|
||||
|
||||
class Ftpd(object):
|
||||
def __init__(self, hub):
|
||||
self.hub = hub
|
||||
self.args = hub.args
|
||||
|
||||
h = FtpHandler
|
||||
h.hub = hub
|
||||
h.args = hub.args
|
||||
h.authorizer = FtpAuth()
|
||||
h.authorizer.hub = hub
|
||||
hs = []
|
||||
if self.args.ftp:
|
||||
hs.append([FtpHandler, self.args.ftp])
|
||||
if self.args.ftps:
|
||||
try:
|
||||
h = SftpHandler
|
||||
except:
|
||||
m = "\nftps requires pyopenssl;\nplease run the following:\n\n {} -m pip install --user pyopenssl\n"
|
||||
print(m.format(sys.executable))
|
||||
sys.exit(1)
|
||||
|
||||
if self.args.ftp_r:
|
||||
p1, p2 = [int(x) for x in self.args.ftp_r.split("-")]
|
||||
h.passive_ports = list(range(p1, p2 + 1))
|
||||
h.certfile = os.path.join(E.cfg, "cert.pem")
|
||||
h.tls_control_required = True
|
||||
h.tls_data_required = True
|
||||
|
||||
if self.args.ftp_nat:
|
||||
h.masquerade_address = self.args.ftp_nat
|
||||
hs.append([h, self.args.ftps])
|
||||
|
||||
for h in hs:
|
||||
h, lp = h
|
||||
h.hub = hub
|
||||
h.args = hub.args
|
||||
h.authorizer = FtpAuth()
|
||||
h.authorizer.hub = hub
|
||||
|
||||
if self.args.ftp_pr:
|
||||
p1, p2 = [int(x) for x in self.args.ftp_pr.split("-")]
|
||||
if self.args.ftp and self.args.ftps:
|
||||
# divide port range in half
|
||||
d = int((p2 - p1) / 2)
|
||||
if lp == self.args.ftp:
|
||||
p2 = p1 + d
|
||||
else:
|
||||
p1 += d + 1
|
||||
|
||||
h.passive_ports = list(range(p1, p2 + 1))
|
||||
|
||||
if self.args.ftp_nat:
|
||||
h.masquerade_address = self.args.ftp_nat
|
||||
|
||||
if self.args.ftp_dbg:
|
||||
config_logging(level=logging.DEBUG)
|
||||
|
||||
ioloop = IOLoop()
|
||||
for ip in self.args.i:
|
||||
FTPServer((ip, int(self.args.ftp)), h, ioloop)
|
||||
for h, lp in hs:
|
||||
FTPServer((ip, int(lp)), h, ioloop)
|
||||
|
||||
t = threading.Thread(target=ioloop.loop)
|
||||
t.daemon = True
|
||||
|
|
|
@ -105,7 +105,7 @@ class SvcHub(object):
|
|||
|
||||
args.th_poke = min(args.th_poke, args.th_maxage, args.ac_maxage)
|
||||
|
||||
if args.ftp:
|
||||
if args.ftp or args.ftps:
|
||||
from .ftpd import Ftpd
|
||||
|
||||
self.ftpd = Ftpd(self)
|
||||
|
|
Loading…
Reference in a new issue