new option --ipa; client IP allowlist:

connections from outside the specified list of IP prefixes are rejected
(docker-friendly alternative to -i 127.0.0.1)

also mkdir any missing folders when logging to file
This commit is contained in:
ed 2023-11-30 20:45:43 +00:00
parent 16766e702e
commit 00812cb1da
5 changed files with 32 additions and 3 deletions

View file

@ -18,8 +18,17 @@
# (note: enable compression by adding .xz at the end) # (note: enable compression by adding .xz at the end)
q, lo: $LOGS_DIRECTORY/%Y-%m%d.log q, lo: $LOGS_DIRECTORY/%Y-%m%d.log
# p: 80,443,3923 # listen on 80/443 as well (requires CAP_NET_BIND_SERVICE) # p: 80,443,3923 # listen on 80/443 as well (requires CAP_NET_BIND_SERVICE)
# i: 127.0.0.1 # only allow connections from localhost (reverse-proxies) # i: 127.0.0.1 # only allow connections from localhost (reverse-proxies)
# ftp: 3921 # enable ftp server on port 3921
# p: 3939 # listen on another port
# df: 16 # stop accepting uploads if less than 16 GB free disk space
# ver # show copyparty version in the controlpanel
# grid # show thumbnails/grid-view by default
# theme: 2 # monokai
# name: datasaver # change the server-name that's displayed in the browser
# stats, nos-dup # enable the prometheus endpoint, but disable the dupes counter (too slow)
# no-robots, force-js # make it harder for search engines to read your server
[accounts] [accounts]

View file

@ -876,6 +876,7 @@ def add_network(ap):
ap2.add_argument("--rproxy", metavar="DEPTH", type=int, default=1, help="which ip to keep; [\033[32m0\033[0m]=tcp, [\033[32m1\033[0m]=origin (first x-fwd, unsafe), [\033[32m2\033[0m]=outermost-proxy, [\033[32m3\033[0m]=second-proxy, [\033[32m-1\033[0m]=closest-proxy") ap2.add_argument("--rproxy", metavar="DEPTH", type=int, default=1, help="which ip to keep; [\033[32m0\033[0m]=tcp, [\033[32m1\033[0m]=origin (first x-fwd, unsafe), [\033[32m2\033[0m]=outermost-proxy, [\033[32m3\033[0m]=second-proxy, [\033[32m-1\033[0m]=closest-proxy")
ap2.add_argument("--xff-hdr", metavar="NAME", type=u, default="x-forwarded-for", help="if reverse-proxied, which http header to read the client's real ip from (argument must be lowercase, but not the actual header)") ap2.add_argument("--xff-hdr", metavar="NAME", type=u, default="x-forwarded-for", help="if reverse-proxied, which http header to read the client's real ip from (argument must be lowercase, but not the actual header)")
ap2.add_argument("--xff-src", metavar="IP", type=u, default="127., ::1", help="comma-separated list of trusted reverse-proxy IPs; only accept the real-ip header (--xff-hdr) if the incoming connection is from an IP starting with either of these. Can be disabled with [\033[32many\033[0m] if you are behind cloudflare (or similar) and are using --xff-hdr=cf-connecting-ip (or similar)") ap2.add_argument("--xff-src", metavar="IP", type=u, default="127., ::1", help="comma-separated list of trusted reverse-proxy IPs; only accept the real-ip header (--xff-hdr) if the incoming connection is from an IP starting with either of these. Can be disabled with [\033[32many\033[0m] if you are behind cloudflare (or similar) and are using --xff-hdr=cf-connecting-ip (or similar)")
ap2.add_argument("--ipa", metavar="PREFIX", type=u, default="", help="only accept connections from IP-addresses starting with \033[33mPREFIX\033[0m; example: [\033[32m127., 10.89., 192.168.\033[0m]")
ap2.add_argument("--rp-loc", metavar="PATH", type=u, default="", help="if reverse-proxying on a location instead of a dedicated domain/subdomain, provide the base location here (eg. /foo/bar)") ap2.add_argument("--rp-loc", metavar="PATH", type=u, default="", help="if reverse-proxying on a location instead of a dedicated domain/subdomain, provide the base location here (eg. /foo/bar)")
if ANYWIN: if ANYWIN:
ap2.add_argument("--reuseaddr", action="store_true", help="set reuseaddr on listening sockets on windows; allows rapid restart of copyparty at the expense of being able to accidentally start multiple instances") ap2.add_argument("--reuseaddr", action="store_true", help="set reuseaddr on listening sockets on windows; allows rapid restart of copyparty at the expense of being able to accidentally start multiple instances")
@ -921,7 +922,7 @@ def add_cert(ap, cert_path):
def add_auth(ap): def add_auth(ap):
ap2 = ap.add_argument_group('user authentication options') ap2 = ap.add_argument_group('user authentication options')
ap2.add_argument("--hdr-au-usr", metavar="HN", type=u, default="", help="bypass the copyparty authentication checks and assume the request-header \033[33mHN\033[0m contains the username of the requesting user (for use with authentik/oauth/...)\n\033[1;31mWARNING:\033[0m if you enable this feature, make sure clients are unable to specify this header themselves; must be washed away and replaced by a reverse-proxy. Also, the argument must be lowercase, but not the actual header") ap2.add_argument("--hdr-au-usr", metavar="HN", type=u, default="", help="bypass the copyparty authentication checks and assume the request-header \033[33mHN\033[0m contains the username of the requesting user (for use with authentik/oauth/...)\n\033[1;31mWARNING:\033[0m if you enable this, make sure clients are unable to specify this header themselves; must be washed away and replaced by a reverse-proxy. Also, the argument must be lowercase, but not the actual header")
def add_zeroconf(ap): def add_zeroconf(ap):

View file

@ -236,6 +236,10 @@ class HttpCli(object):
if self.is_banned(): if self.is_banned():
return False return False
if self.args.ipa_re and not self.args.ipa_re.match(self.conn.addr[0]):
self.log("client rejected (--ipa)", 3)
return False
try: try:
self.s.settimeout(2) self.s.settimeout(2)
headerlines = read_header(self.sr, self.args.s_thead, self.args.s_thead) headerlines = read_header(self.sr, self.args.s_thead, self.args.s_thead)

View file

@ -438,6 +438,12 @@ class SvcHub(object):
zs = al.xff_src.replace(" ", "").replace(".", "\\.").replace(",", "|") zs = al.xff_src.replace(" ", "").replace(".", "\\.").replace(",", "|")
al.xff_re = re.compile("^(?:" + zs + ")") 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 + ")")
mte = ODict.fromkeys(DEF_MTE.split(","), True) mte = ODict.fromkeys(DEF_MTE.split(","), True)
al.mte = odfusion(mte, al.mte) al.mte = odfusion(mte, al.mte)
@ -517,6 +523,10 @@ class SvcHub(object):
sel_fn = "{}.{}".format(fn, ctr) sel_fn = "{}.{}".format(fn, ctr)
fn = sel_fn fn = sel_fn
try:
os.makedirs(os.path.dirname(fn))
except:
pass
try: try:
if do_xz: if do_xz:

View file

@ -8,9 +8,14 @@
e2ts # enable multimedia indexing e2ts # enable multimedia indexing
ansi # enable colors in log messages ansi # enable colors in log messages
# q, lo: /cfg/log/%Y-%m%d.log # log to file instead of docker
# ftp: 3921 # enable ftp server on port 3921 # ftp: 3921 # enable ftp server on port 3921
# p: 3939 # listen on another port # p: 3939 # listen on another port
# ipa: 10.89. # only allow connections from 10.89.*
# df: 16 # stop accepting uploads if less than 16 GB free disk space # df: 16 # stop accepting uploads if less than 16 GB free disk space
# ver # show copyparty version in the controlpanel
# grid # show thumbnails/grid-view by default
# theme: 2 # monokai # theme: 2 # monokai
# name: datasaver # change the server-name that's displayed in the browser # name: datasaver # change the server-name that's displayed in the browser
# stats, nos-dup # enable the prometheus endpoint, but disable the dupes counter (too slow) # stats, nos-dup # enable the prometheus endpoint, but disable the dupes counter (too slow)