From 151ba0d491fa70882e659f416cac078f974f3157 Mon Sep 17 00:00:00 2001 From: Amos Jeffries Date: Fri, 25 Jul 2014 01:27:38 -0700 Subject: [PATCH] Allow proxy-surrogate to be used with any traffic mode The accel/intercept/tproxy mode flag when used with proxy-surrogate indicates what type of traffic the remote client used to receive this traffic. * disable use on https_port * disable TPROXY spoofing when the PROXY header provides client IP --- src/anyp/TrafficMode.h | 4 ++-- src/cache_cf.cc | 23 ++++++++++++++--------- src/cf.data.pre | 10 +++++----- src/client_side.cc | 5 +++++ 4 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/anyp/TrafficMode.h b/src/anyp/TrafficMode.h index 4e5bea7b29..eb03cf9bac 100644 --- a/src/anyp/TrafficMode.h +++ b/src/anyp/TrafficMode.h @@ -30,8 +30,8 @@ public: * Indicating the following are required: * - PROXY protocol magic header * - src/dst IP retrieved from magic PROXY header - * - reverse-proxy traffic prohibited - * - intercepted traffic prohibited + * - indirect client IP trust verification is mandatory + * - TLS is not supported */ bool proxySurrogate; diff --git a/src/cache_cf.cc b/src/cache_cf.cc index f65c34e930..e7ccd2f155 100644 --- a/src/cache_cf.cc +++ b/src/cache_cf.cc @@ -3566,14 +3566,14 @@ parse_port_option(AnyP::PortCfg * s, char *token) /* modes first */ if (strcmp(token, "accel") == 0) { - if (s->flags.isIntercepted() || s->flags.proxySurrogate) { + if (s->flags.isIntercepted()) { debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: Accelerator mode requires its own port. It cannot be shared with other modes."); self_destruct(); } s->flags.accelSurrogate = true; s->vhost = true; } else if (strcmp(token, "transparent") == 0 || strcmp(token, "intercept") == 0) { - if (s->flags.accelSurrogate || s->flags.tproxyIntercept || s->flags.proxySurrogate) { + if (s->flags.accelSurrogate || s->flags.tproxyIntercept) { debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: Intercept mode requires its own interception port. It cannot be shared with other modes."); self_destruct(); } @@ -3583,7 +3583,7 @@ parse_port_option(AnyP::PortCfg * s, char *token) debugs(3, DBG_IMPORTANT, "Starting Authentication on port " << s->s); debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (interception enabled)"); } else if (strcmp(token, "tproxy") == 0) { - if (s->flags.natIntercept || s->flags.accelSurrogate || s->flags.proxySurrogate) { + if (s->flags.natIntercept || s->flags.accelSurrogate) { debugs(3,DBG_CRITICAL, "FATAL: http(s)_port: TPROXY option requires its own interception port. It cannot be shared with other modes."); self_destruct(); } @@ -3592,17 +3592,18 @@ parse_port_option(AnyP::PortCfg * s, char *token) /* Log information regarding the port modes under transparency. */ debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (TPROXY enabled)"); + if (s->flags.proxySurrogate) { + debugs(3, DBG_IMPORTANT, "Disabling TPROXY Spoofing on port " << s->s << " (proxy-surrogate enabled)"); + } + if (!Ip::Interceptor.ProbeForTproxy(s->s)) { debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: TPROXY support in the system does not work."); self_destruct(); } } else if (strcmp(token, "proxy-surrogate") == 0) { - if (s->flags.natIntercept || s->flags.accelSurrogate || s->flags.tproxyIntercept) { - debugs(3,DBG_CRITICAL, "FATAL: http(s)_port: proxy-surrogate option requires its own port. It cannot be shared with other modes."); - self_destruct(); - } s->flags.proxySurrogate = true; + debugs(3, DBG_IMPORTANT, "Disabling TPROXY Spoofing on port " << s->s << " (proxy-surrogate enabled)"); } else if (strncmp(token, "defaultsite=", 12) == 0) { if (!s->flags.accelSurrogate) { @@ -3802,8 +3803,8 @@ parsePortCfg(AnyP::PortCfg ** head, const char *optionName) parse_port_option(s, token); } -#if USE_OPENSSL if (s->transport.protocol == AnyP::PROTO_HTTPS) { +#if USE_OPENSSL /* ssl-bump on https_port configuration requires either tproxy or intercept, and vice versa */ const bool hijacked = s->flags.isIntercepted(); if (s->flags.tunnelSslBumping && !hijacked) { @@ -3814,8 +3815,12 @@ parsePortCfg(AnyP::PortCfg ** head, const char *optionName) debugs(3, DBG_CRITICAL, "FATAL: tproxy/intercept on https_port requires ssl-bump which is missing."); self_destruct(); } - } #endif + if (s->transport.protocol == AnyP::PROTO_HTTPS) { + debugs(3,DBG_CRITICAL, "FATAL: https_port: proxy-surrogate option cannot be used on HTTPS ports."); + self_destruct(); + } + } if (Ip::EnableIpv6&IPV6_SPECIAL_SPLITSTACK && s->s.isAnyAddr()) { // clone the port options from *s to *(s->next) diff --git a/src/cf.data.pre b/src/cf.data.pre index 462e4c1861..27136249f1 100644 --- a/src/cf.data.pre +++ b/src/cf.data.pre @@ -1543,11 +1543,6 @@ DOC_START accel Accelerator / reverse proxy mode - proxy-surrogate - Support for PROXY protocol version 1 or 2 connections. - The proxy_forwarded_access is required to whitelist - downstream proxies which can be trusted. - ssl-bump For each CONNECT request allowed by ssl_bump ACLs, establish secure connection with the client and with the server, decrypt HTTPS messages as they pass through @@ -1734,6 +1729,11 @@ DOC_START probing the connection, interval how often to probe, and timeout the time before giving up. + proxy-surrogate + Require PROXY protocol version 1 or 2 connections. + The proxy_forwarded_access is required to whitelist + downstream proxies which can be trusted. + If you run Squid on a dual-homed machine with an internal and an external interface we recommend you to specify the internal address:port in http_port. This way Squid will only be diff --git a/src/client_side.cc b/src/client_side.cc index ba587b692a..3dfc41da21 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -2342,6 +2342,8 @@ parseHttpRequest(ConnStateData *csd, HttpParser *hp, HttpRequestMethod * method_ * - accelerator mode (reverse proxy) * - internal URL * - mixed combos of the above with internal URL + * - remote interception with PROXY protocol + * - remote reverse-proxy with PROXY protocol */ if (csd->transparent()) { /* intercept or transparent mode, properly working with no failures */ @@ -3045,6 +3047,7 @@ ConnStateData::parseProxy10() debugs(33, 5, "PROXY/1.0 protocol on connection " << clientConnection); clientConnection->local = originalDest; clientConnection->remote = originalClient; + clientConnection->flags ^= COMM_TRANSPARENT; // prevent TPROXY spoofing of this new IP. debugs(33, 5, "PROXY/1.0 upgrade: " << clientConnection); // repeat fetch ensuring the new client FQDN can be logged @@ -3122,12 +3125,14 @@ ConnStateData::parseProxy20() clientConnection->local.port(ntohs(ipu->ipv4_addr.dst_port)); clientConnection->remote = ipu->ipv4_addr.src_addr; clientConnection->remote.port(ntohs(ipu->ipv4_addr.src_port)); + clientConnection->flags ^= COMM_TRANSPARENT; // prevent TPROXY spoofing of this new IP. break; case 0x2: // IPv6 clientConnection->local = ipu->ipv6_addr.dst_addr; clientConnection->local.port(ntohs(ipu->ipv6_addr.dst_port)); clientConnection->remote = ipu->ipv6_addr.src_addr; clientConnection->remote.port(ntohs(ipu->ipv6_addr.src_port)); + clientConnection->flags ^= COMM_TRANSPARENT; // prevent TPROXY spoofing of this new IP. break; default: // do nothing break; -- 2.47.3