diff --git a/copyparty/__main__.py b/copyparty/__main__.py index cef1a1f8..44e5f729 100644 --- a/copyparty/__main__.py +++ b/copyparty/__main__.py @@ -1278,6 +1278,7 @@ def add_network(ap): 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") ap2.add_argument("--xf-host", metavar="NAME", type=u, default="x-forwarded-host", help="if reverse-proxied, which http header to read the correct Host value from; this header must contain the server's external domain name") ap2.add_argument("--xf-proto", metavar="NAME", type=u, default="x-forwarded-proto", help="if reverse-proxied, which http header to read the correct protocol value from; this header must contain either 'http' or 'https'") + ap2.add_argument("--xf-proto-fb", metavar="T", type=u, default="", help="protocol to assume if the X-Forwarded-Proto header (\033[33m--xf-proto\033[0m) is not provided by the reverseproxy; either 'http' or 'https'") ap2.add_argument("--xff-src", metavar="CIDR", type=u, default="127.0.0.0/8, ::1/128", help="list of trusted reverse-proxy CIDRs (comma-separated); only accept the real-ip header (\033[33m--xff-hdr\033[0m) and IdP headers if the incoming connection is from an IP within either of these subnets. Specify [\033[32mlan\033[0m] to allow all LAN / private / non-internet IPs. Can be disabled with [\033[32many\033[0m] if you are behind cloudflare (or similar) and are using \033[32m--xff-hdr=cf-connecting-ip\033[0m (or similar)") ap2.add_argument("--ipa", metavar="CIDR", type=u, default="", help="only accept connections from IP-addresses inside \033[33mCIDR\033[0m (comma-separated); examples: [\033[32mlan\033[0m] or [\033[32m10.89.0.0/16, 192.168.33.0/24\033[0m]\n └─for performance and security, this only looks at the TCP/Network-level IP, and will NOT work behind a reverseproxy") ap2.add_argument("--ipar", metavar="CIDR", type=u, default="", help="only accept connections from IP-addresses inside \033[33mCIDR\033[0m (comma-separated).\n └─this is reverseproxy-compatible; reads client-IP from 'X-Forwarded-For' if possible, with TCP/Network IP as fallback") diff --git a/copyparty/httpcli.py b/copyparty/httpcli.py index 86bfca65..131a84b1 100644 --- a/copyparty/httpcli.py +++ b/copyparty/httpcli.py @@ -152,7 +152,8 @@ USED4SEC = {"usedforsecurity": False} if sys.version_info > (3, 9) else {} ALL_COOKIES = "k304 no304 js idxh dots cppwd cppws".split() BADXFF = " due to dangerous misconfiguration (the http-header specified by --xff-hdr was received from an untrusted reverse-proxy)" -BADXFF2 = ". Some copyparty features are now disabled as a safety measure." +BADXFF2 = ". Some copyparty features are now disabled as a safety measure.\n\n\n" +BADXFP = ', or change the copyparty global-option "xf-proto" to another header-name to read this value from. Alternatively, if your reverseproxy is not able to provide a header similar to "X-Forwarded-Proto", then you must tell copyparty which protocol to assume by setting global-option --xf-proto-fb to either http or https' H_CONN_KEEPALIVE = "Connection: Keep-Alive" H_CONN_CLOSE = "Connection: Close" @@ -449,10 +450,13 @@ class HttpCli(object): try: self.is_https = len(self.headers[self.args.xf_proto]) == 5 except: - self.bad_xff = True - self.host = "example.com" - t = 'got proxied request without header "%s" (global-option "xf-proto"). This header must contain either "http" or "https". Either fix your reverse-proxy config to include this header, or change the copyparty global-option "xf-proto" to another header-name to read this value from' - self.log(t % (self.args.xf_proto,) + BADXFF2, 3) + if self.args.xf_proto_fb: + self.is_https = len(self.args.xf_proto_fb) == 5 + else: + self.bad_xff = True + self.host = "example.com" + t = 'got proxied request without header "%s" (global-option "xf-proto"). This header must contain either "http" or "https". Either fix your reverse-proxy config to include this header%s%s' + self.log(t % (self.args.xf_proto, BADXFP, BADXFF2), 3) # the semantics of trusted_xff and bad_xff are different; # trusted_xff is whether the connection came from a trusted reverseproxy,