mirror of
https://github.com/9001/copyparty.git
synced 2025-08-17 09:02:15 -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)
|
* [other tricks](#other-tricks)
|
||||||
* [searching](#searching) - search by size, date, path/name, mp3-tags, ...
|
* [searching](#searching) - search by size, date, path/name, mp3-tags, ...
|
||||||
* [server config](#server-config) - using arguments or config files, or a mix of both
|
* [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)
|
* [file indexing](#file-indexing)
|
||||||
* [upload rules](#upload-rules) - set upload rules using volume flags
|
* [upload rules](#upload-rules) - set upload rules using volume flags
|
||||||
* [compress uploads](#compress-uploads) - files can be autocompressed on upload
|
* [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
|
## 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)
|
* based on [pyftpdlib](https://github.com/giampaolo/pyftpdlib)
|
||||||
* needs a dedicated port (cannot share with the HTTP/HTTPS API)
|
* 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 -- delete and restart if necessary
|
||||||
* uploads are not resumable
|
* 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
|
## file indexing
|
||||||
|
|
|
@ -447,9 +447,10 @@ def run_argparse(argv, formatter):
|
||||||
|
|
||||||
ap2 = ap.add_argument_group('FTP options')
|
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("--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-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-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 = ap.add_argument_group('opt-outs')
|
||||||
ap2.add_argument("-nw", action="store_true", help="disable writes (benchmark)")
|
ap2.add_argument("-nw", action="store_true", help="disable writes (benchmark)")
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
from __future__ import print_function, unicode_literals
|
from __future__ import print_function, unicode_literals
|
||||||
|
|
||||||
import os
|
import os
|
||||||
|
import sys
|
||||||
import stat
|
import stat
|
||||||
import time
|
import time
|
||||||
import logging
|
import logging
|
||||||
|
@ -14,6 +15,7 @@ from pyftpdlib.servers import FTPServer
|
||||||
from pyftpdlib.ioloop import IOLoop
|
from pyftpdlib.ioloop import IOLoop
|
||||||
from pyftpdlib.log import config_logging
|
from pyftpdlib.log import config_logging
|
||||||
|
|
||||||
|
from .__init__ import E
|
||||||
from .util import Pebkac, fsenc, exclude_dotfiles
|
from .util import Pebkac, fsenc, exclude_dotfiles
|
||||||
from .bos import bos
|
from .bos import bos
|
||||||
from .authsrv import AuthSrv
|
from .authsrv import AuthSrv
|
||||||
|
@ -275,19 +277,55 @@ class FtpHandler(FTPHandler):
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
try:
|
||||||
|
from pyftpdlib.handlers import TLS_FTPHandler
|
||||||
|
|
||||||
|
class SftpHandler(FtpHandler, TLS_FTPHandler):
|
||||||
|
pass
|
||||||
|
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Ftpd(object):
|
class Ftpd(object):
|
||||||
def __init__(self, hub):
|
def __init__(self, hub):
|
||||||
self.hub = hub
|
self.hub = hub
|
||||||
self.args = hub.args
|
self.args = hub.args
|
||||||
|
|
||||||
h = FtpHandler
|
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)
|
||||||
|
|
||||||
|
h.certfile = os.path.join(E.cfg, "cert.pem")
|
||||||
|
h.tls_control_required = True
|
||||||
|
h.tls_data_required = True
|
||||||
|
|
||||||
|
hs.append([h, self.args.ftps])
|
||||||
|
|
||||||
|
for h in hs:
|
||||||
|
h, lp = h
|
||||||
h.hub = hub
|
h.hub = hub
|
||||||
h.args = hub.args
|
h.args = hub.args
|
||||||
h.authorizer = FtpAuth()
|
h.authorizer = FtpAuth()
|
||||||
h.authorizer.hub = hub
|
h.authorizer.hub = hub
|
||||||
|
|
||||||
if self.args.ftp_r:
|
if self.args.ftp_pr:
|
||||||
p1, p2 = [int(x) for x in self.args.ftp_r.split("-")]
|
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))
|
h.passive_ports = list(range(p1, p2 + 1))
|
||||||
|
|
||||||
if self.args.ftp_nat:
|
if self.args.ftp_nat:
|
||||||
|
@ -298,7 +336,8 @@ class Ftpd(object):
|
||||||
|
|
||||||
ioloop = IOLoop()
|
ioloop = IOLoop()
|
||||||
for ip in self.args.i:
|
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 = threading.Thread(target=ioloop.loop)
|
||||||
t.daemon = True
|
t.daemon = True
|
||||||
|
|
|
@ -105,7 +105,7 @@ class SvcHub(object):
|
||||||
|
|
||||||
args.th_poke = min(args.th_poke, args.th_maxage, args.ac_maxage)
|
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
|
from .ftpd import Ftpd
|
||||||
|
|
||||||
self.ftpd = Ftpd(self)
|
self.ftpd = Ftpd(self)
|
||||||
|
|
1
setup.py
1
setup.py
|
@ -116,6 +116,7 @@ args = {
|
||||||
"thumbnails": ["Pillow"],
|
"thumbnails": ["Pillow"],
|
||||||
"audiotags": ["mutagen"],
|
"audiotags": ["mutagen"],
|
||||||
"ftpd": ["pyftpdlib"],
|
"ftpd": ["pyftpdlib"],
|
||||||
|
"ftps": ["pyopenssl"],
|
||||||
},
|
},
|
||||||
"entry_points": {"console_scripts": ["copyparty = copyparty.__main__:main"]},
|
"entry_points": {"console_scripts": ["copyparty = copyparty.__main__:main"]},
|
||||||
"scripts": ["bin/copyparty-fuse.py", "bin/up2k.py"],
|
"scripts": ["bin/copyparty-fuse.py", "bin/up2k.py"],
|
||||||
|
|
Loading…
Reference in a new issue