AnyP::PortCfg *p = Config.Sockaddr.http;
while (p) {
// Bug 3239: not reliable when there is interception traffic coming
- if (p->intercepted)
+ if (p->flags.natIntercept)
debugs(28, DBG_CRITICAL, "WARNING: 'myip' ACL is not reliable for interception proxies. Please use 'myportname' instead.");
p = p->next;
}
while (p) {
// Bug 3239: not reliable when there is interception traffic coming
// Bug 3239: myport - not reliable (yet) when there is interception traffic coming
- if (p->intercepted)
+ if (p->flags.natIntercept)
debugs(28, DBG_CRITICAL, "WARNING: 'myport' ACL is not reliable for interception proxies. Please use 'myportname' instead.");
p = p->next;
}
PortCfg.h \
ProtocolType.cc \
ProtocolType.h \
- ProtocolVersion.h
+ ProtocolVersion.h \
+ TrafficMode.h
ProtocolType.cc: ProtocolType.h $(top_srcdir)/src/mk-string-arrays.awk
($(AWK) -f $(top_srcdir)/src/mk-string-arrays.awk <$(srcdir)/ProtocolType.h | sed -e 's%PROTO_%%' >$@) || ($(RM) -f $@ && exit 1)
if (defaultsite)
b->defaultsite = xstrdup(defaultsite);
- b->intercepted = intercepted;
- b->spoof_client_ip = spoof_client_ip;
- b->accel = accel;
+ b->flags = flags;
b->allow_direct = allow_direct;
b->vhost = vhost;
- b->sslBump = sslBump;
b->vport = vport;
b->connection_auth_disabled = connection_auth_disabled;
b->disable_pmtu_discovery = disable_pmtu_discovery;
#ifndef SQUID_ANYP_PORTCFG_H
#define SQUID_ANYP_PORTCFG_H
+#include "anyp/TrafficMode.h"
#include "cbdata.h"
#include "comm/Connection.h"
char *name; /* visible name */
char *defaultsite; /* default web site */
- unsigned int intercepted:1; /**< intercepting proxy port */
- unsigned int spoof_client_ip:1; /**< spoof client ip if possible */
- unsigned int accel:1; /**< HTTP accelerator */
+ TrafficMode flags; ///< flags indicating what type of traffic to expect via this port.
+
unsigned int allow_direct:1; /**< Allow direct forwarding in accelerator mode */
unsigned int vhost:1; /**< uses host header */
- unsigned int sslBump:1; /**< intercepts CONNECT requests */
unsigned int actAsOrigin:1; ///< update replies to conform with RFC 2616
unsigned int ignore_cc:1; /**< Ignore request Cache-Control directives */
--- /dev/null
+#ifndef SQUID_ANYP_TRAFFIC_MODE_H
+#define SQUID_ANYP_TRAFFIC_MODE_H
+
+namespace AnyP
+{
+
+/**
+ * Set of 'mode' flags defining types of trafic which can be received.
+ *
+ * Use to determine the processing steps which need to be applied
+ * to this traffic under any special circumstances which may apply.
+ */
+class TrafficMode
+{
+public:
+ TrafficMode() : accelSurrogate(false), natIntercept(false), tproxyIntercept(false), tunnelSslBumping(false) {}
+ TrafficMode(const TrafficMode &rhs) { operator =(rhs); }
+ TrafficMode &operator =(const TrafficMode &rhs) { memcpy(this, &rhs, sizeof(TrafficMode)); return *this; }
+
+ /** marks HTTP accelerator (reverse/surrogate proxy) traffic
+ *
+ * Indicating the following are required:
+ * - URL translation from relative to absolute form
+ * - restriction to origin peer relay recommended
+ */
+ bool accelSurrogate;
+
+ /** marks NAT intercepted traffic
+ *
+ * Indicating the following are required:
+ * - NAT lookups
+ * - URL translation from relative to absolute form
+ * - Same-Origin verification is mandatory
+ * - destination pinning is recommended
+ * - authentication prohibited
+ */
+ bool natIntercept;
+
+ /** marks TPROXY intercepted traffic
+ *
+ * Indicating the following are required:
+ * - src/dst IP inversion must be performed
+ * - client IP should be spoofed if possible
+ * - URL translation from relative to absolute form
+ * - Same-Origin verification is mandatory
+ * - destination pinning is recommended
+ * - authentication prohibited
+ */
+ bool tproxyIntercept;
+
+ /** marks intercept and decryption of CONNECT (tunnel) SSL traffic
+ *
+ * Indicating the following are required:
+ * - decryption of CONNECT request
+ * - URL translation from relative to absolute form
+ * - authentication prohibited on unwrapped requests (only on the CONNECT tunnel)
+ * - encrypted outbound server connections
+ * - peer relay prohibited. TODO: re-encrypt and re-wrap with CONNECT
+ */
+ bool tunnelSslBumping;
+};
+
+} // namespace AnyP
+
+#endif
}
for (AnyP::PortCfg *s = Config.Sockaddr.http; s != NULL; s = s->next) {
- if (!s->sslBump)
+ if (!s->flags.tunnelSslBumping)
continue;
debugs(3, DBG_IMPORTANT, "Initializing http_port " << s->s << " SSL context");
/* modes first */
if (strcmp(token, "accel") == 0) {
- if (s->intercepted || s->spoof_client_ip) {
+ if (s->flags.natIntercept || s->flags.tproxyIntercept) {
debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: Accelerator mode requires its own port. It cannot be shared with other modes.");
self_destruct();
}
- s->accel = s->vhost = 1;
+ s->flags.accelSurrogate = true;
+ s->vhost = 1;
} else if (strcmp(token, "transparent") == 0 || strcmp(token, "intercept") == 0) {
- if (s->accel || s->spoof_client_ip) {
+ 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();
}
- s->intercepted = 1;
+ s->flags.natIntercept = true;
Ip::Interceptor.StartInterception();
/* Log information regarding the port modes under interception. */
debugs(3, DBG_IMPORTANT, "Starting Authentication on port " << s->s);
self_destruct();
}
} else if (strcmp(token, "tproxy") == 0) {
- if (s->intercepted || s->accel) {
+ 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();
}
- s->spoof_client_ip = 1;
+ s->flags.tproxyIntercept = true;
Ip::Interceptor.StartTransparency();
/* Log information regarding the port modes under transparency. */
debugs(3, DBG_IMPORTANT, "Starting IP Spoofing on port " << s->s);
}
} else if (strncmp(token, "defaultsite=", 12) == 0) {
- if (!s->accel) {
+ if (!s->flags.accelSurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: defaultsite option requires Acceleration mode flag.");
self_destruct();
}
safe_free(s->defaultsite);
s->defaultsite = xstrdup(token + 12);
} else if (strcmp(token, "vhost") == 0) {
- if (!s->accel) {
+ if (!s->flags.accelSurrogate) {
debugs(3, DBG_CRITICAL, "WARNING: http(s)_port: vhost option is deprecated. Use 'accel' mode flag instead.");
}
- s->accel = s->vhost = 1;
+ s->flags.accelSurrogate = true;
+ s->vhost = 1;
} else if (strcmp(token, "no-vhost") == 0) {
- if (!s->accel) {
+ if (!s->flags.accelSurrogate) {
debugs(3, DBG_IMPORTANT, "ERROR: http(s)_port: no-vhost option requires Acceleration mode flag.");
}
s->vhost = 0;
} else if (strcmp(token, "vport") == 0) {
- if (!s->accel) {
+ if (!s->flags.accelSurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: vport option requires Acceleration mode flag.");
self_destruct();
}
s->vport = -1;
} else if (strncmp(token, "vport=", 6) == 0) {
- if (!s->accel) {
+ if (!s->flags.accelSurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: vport option requires Acceleration mode flag.");
self_destruct();
}
s->vport = xatos(token + 6);
} else if (strncmp(token, "protocol=", 9) == 0) {
- if (!s->accel) {
+ if (!s->flags.accelSurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: protocol option requires Acceleration mode flag.");
self_destruct();
}
s->protocol = xstrdup(token + 9);
} else if (strcmp(token, "allow-direct") == 0) {
- if (!s->accel) {
+ if (!s->flags.accelSurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: allow-direct option requires Acceleration mode flag.");
self_destruct();
}
s->allow_direct = 1;
} else if (strcmp(token, "act-as-origin") == 0) {
- if (!s->accel) {
+ if (!s->flags.accelSurrogate) {
debugs(3, DBG_IMPORTANT, "ERROR: http(s)_port: act-as-origin option requires Acceleration mode flag.");
} else
s->actAsOrigin = 1;
} else if (strcmp(token, "ignore-cc") == 0) {
#if !USE_HTTP_VIOLATIONS
- if (!s->accel) {
+ if (!s->flags.accelSurrogate) {
debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: ignore-cc option requires Scceleration mode flag.");
self_destruct();
}
} else if (strcasecmp(token, "sslBump") == 0) {
debugs(3, DBG_CRITICAL, "WARNING: '" << token << "' is deprecated " <<
"in http_port. Use 'ssl-bump' instead.");
- s->sslBump = 1; // accelerated when bumped, otherwise not
+ s->flags.tunnelSslBumping = true; // accelerated when bumped, otherwise not
} else if (strcmp(token, "ssl-bump") == 0) {
- s->sslBump = 1; // accelerated when bumped, otherwise not
+ s->flags.tunnelSslBumping = true; // accelerated when bumped, otherwise not
} else if (strncmp(token, "cert=", 5) == 0) {
safe_free(s->cert);
s->cert = xstrdup(token + 5);
#if USE_SSL
if (strcasecmp(protocol, "https") == 0) {
/* ssl-bump on https_port configuration requires either tproxy or intercept, and vice versa */
- const bool hijacked = s->spoof_client_ip || s->intercepted;
- if (s->sslBump && !hijacked) {
+ const bool hijacked = s->flags.tproxyIntercept || s->flags.natIntercept;
+ if (s->flags.tunnelSslBumping && !hijacked) {
debugs(3, DBG_CRITICAL, "FATAL: ssl-bump on https_port requires tproxy/intercept which is missing.");
self_destruct();
}
- if (hijacked && !s->sslBump) {
+ if (hijacked && !s->flags.tunnelSslBumping) {
debugs(3, DBG_CRITICAL, "FATAL: tproxy/intercept on https_port requires ssl-bump which is missing.");
self_destruct();
}
s->s.ToURL(buf,MAX_IPSTRLEN));
// MODES and specific sub-options.
- if (s->intercepted)
+ if (s->flags.natIntercept)
storeAppendPrintf(e, " intercept");
- else if (s->spoof_client_ip)
+ else if (s->flags.tproxyIntercept)
storeAppendPrintf(e, " tproxy");
- else if (s->accel) {
+ else if (s->flags.accelSurrogate) {
storeAppendPrintf(e, " accel");
if (s->vhost)
storeAppendPrintf(e, " name=%s", s->name);
#if USE_HTTP_VIOLATIONS
- if (!s->accel && s->ignore_cc)
+ if (!s->flags.accelSurrogate && s->ignore_cc)
storeAppendPrintf(e, " ignore-cc");
#endif
}
#if USE_SSL
- if (s->sslBump)
+ if (s->flags.tunnelSslBumping)
storeAppendPrintf(e, " ssl-bump");
if (s->cert)
*method_p = HttpRequestMethod(&hp->buf[hp->req.m_start], &hp->buf[hp->req.m_end]+1);
/* deny CONNECT via accelerated ports */
- if (*method_p == Http::METHOD_CONNECT && csd->port && csd->port->accel) {
+ if (*method_p == Http::METHOD_CONNECT && csd->port && csd->port->flags.accelSurrogate) {
debugs(33, DBG_IMPORTANT, "WARNING: CONNECT method received on " << csd->port->protocol << " Accelerator port " << csd->port->s.GetPort() );
/* XXX need a way to say "this many character length string" */
debugs(33, DBG_IMPORTANT, "WARNING: for request: " << hp->buf);
#endif
- debugs(33,5, HERE << "repare absolute URL from " << (csd->transparent()?"intercept":(csd->port->accel ? "accel":"")));
+ debugs(33,5, HERE << "repare absolute URL from " <<
+ (csd->transparent()?"intercept":(csd->port->flags.accelSurrogate ? "accel":"")));
/* Rewrite the URL in transparent or accelerator mode */
/* NP: there are several cases to traverse here:
* - standard mode (forward proxy)
// But have not parsed there yet!! flag for local-only handling.
http->flags.internal = 1;
- } else if (csd->port->accel || csd->switchedToHttps()) {
+ } else if (csd->port->flags.accelSurrogate || csd->switchedToHttps()) {
/* accelerator mode */
prepareAcceleratedURL(csd, http, url, req_hdr);
}
// Socket is ready, setup the connection manager to start using it
ConnStateData *connState = connStateCreate(params.conn, s);
- if (s->sslBump) {
+ if (s->flags.tunnelSslBumping) {
debugs(33, 5, "httpsAccept: accept transparent connection: " << params.conn);
if (!Config.accessList.ssl_bump) {
debugs(33, 5, HERE << "Error while bumping: " << sslConnectHostOrIp);
Ip::Address intendedDest;
intendedDest = sslConnectHostOrIp.termedBuf();
- const bool isConnectRequest = !port->spoof_client_ip && !port->intercepted;
+ const bool isConnectRequest = !port->flags.tproxyIntercept && !port->flags.natIntercept;
// Squid serves its own error page and closes, so we want
// a CN that causes no additional browser errors. Possible
}
#if USE_SSL
- if (s->sslBump && !Config.accessList.ssl_bump) {
+ if (s->flags.tunnelSslBumping && !Config.accessList.ssl_bump) {
debugs(33, DBG_IMPORTANT, "WARNING: No ssl_bump configured. Disabling ssl-bump on " << s->protocol << "_port " << s->s);
- s->sslBump = 0;
+ s->flags.tunnelSslBumping = false;
}
- if (s->sslBump && !s->staticSslContext && !s->generateHostCertificates) {
+ if (s->flags.tunnelSslBumping &&
+ !s->staticSslContext &&
+ !s->generateHostCertificates) {
debugs(1, DBG_IMPORTANT, "Will not bump SSL at http_port " << s->s << " due to SSL initialization failure.");
- s->sslBump = 0;
+ s->flags.tunnelSslBumping = false;
}
- if (s->sslBump) {
+ if (s->flags.tunnelSslBumping) {
// Create ssl_ctx cache for this port.
Ssl::TheGlobalContextStorage.addLocalStorage(s->s, s->dynamicCertMemCacheSize == std::numeric_limits<size_t>::max() ? 4194304 : s->dynamicCertMemCacheSize);
}
// then pass back when active so we can start a TcpAcceptor subscription.
s->listenConn = new Comm::Connection;
s->listenConn->local = s->s;
- s->listenConn->flags = COMM_NONBLOCKING | (s->spoof_client_ip ? COMM_TRANSPARENT : 0) | (s->intercepted ? COMM_INTERCEPTION : 0);
+ s->listenConn->flags = COMM_NONBLOCKING | (s->flags.tproxyIntercept ? COMM_TRANSPARENT : 0) | (s->flags.natIntercept ? COMM_INTERCEPTION : 0);
// setup the subscriptions such that new connections accepted by listenConn are handled by HTTP
typedef CommCbFunPtrCallT<CommAcceptCbPtrFun> AcceptCall;
}
// TODO: merge with similar code in clientHttpConnectionsOpen()
- if (s->sslBump && !Config.accessList.ssl_bump) {
+ if (s->flags.tunnelSslBumping && !Config.accessList.ssl_bump) {
debugs(33, DBG_IMPORTANT, "WARNING: No ssl_bump configured. Disabling ssl-bump on " << s->protocol << "_port " << s->s);
- s->sslBump = 0;
+ s->flags.tunnelSslBumping = false;
}
- if (s->sslBump && !s->staticSslContext && !s->generateHostCertificates) {
+ if (s->flags.tunnelSslBumping && !s->staticSslContext && !s->generateHostCertificates) {
debugs(1, DBG_IMPORTANT, "Will not bump SSL at http_port " << s->s << " due to SSL initialization failure.");
- s->sslBump = 0;
+ s->flags.tunnelSslBumping = false;
}
- if (s->sslBump) {
+ if (s->flags.tunnelSslBumping) {
// Create ssl_ctx cache for this port.
Ssl::TheGlobalContextStorage.addLocalStorage(s->s, s->dynamicCertMemCacheSize == std::numeric_limits<size_t>::max() ? 4194304 : s->dynamicCertMemCacheSize);
}
// Fill out a Comm::Connection which IPC will open as a listener for us
s->listenConn = new Comm::Connection;
s->listenConn->local = s->s;
- s->listenConn->flags = COMM_NONBLOCKING | (s->spoof_client_ip ? COMM_TRANSPARENT : 0) |
- (s->intercepted ? COMM_INTERCEPTION : 0);
+ s->listenConn->flags = COMM_NONBLOCKING | (s->flags.tproxyIntercept ? COMM_TRANSPARENT : 0) |
+ (s->flags.natIntercept ? COMM_INTERCEPTION : 0);
// setup the subscriptions such that new connections accepted by listenConn are handled by HTTPS
typedef CommCbFunPtrCallT<CommAcceptCbPtrFun> AcceptCall;
AsyncJob::Start(new Comm::TcpAcceptor(s->listenConn, FdNote(portTypeNote), sub));
debugs(1, DBG_IMPORTANT, "Accepting " <<
- (s->intercepted ? "NAT intercepted " : "") <<
- (s->spoof_client_ip ? "TPROXY spoofing " : "") <<
- (s->sslBump ? "SSL bumped " : "") <<
- (s->accel ? "reverse-proxy " : "")
+ (s->flags.natIntercept ? "NAT intercepted " : "") <<
+ (s->flags.tproxyIntercept ? "TPROXY spoofing " : "") <<
+ (s->flags.tunnelSslBumping ? "SSL bumped " : "") <<
+ (s->flags.accelSurrogate ? "reverse-proxy " : "")
<< FdNote(portTypeNote) << " connections at "
<< s->listenConn);
// (bumping of intercepted SSL conns is decided before we get 1st request).
// We also do not bump redirected CONNECT requests.
if (http->request->method != Http::METHOD_CONNECT || http->redirect.status ||
- !Config.accessList.ssl_bump || !http->getConn()->port->sslBump) {
+ !Config.accessList.ssl_bump ||
+ !http->getConn()->port->flags.tunnelSslBumping) {
http->al->ssl.bumpMode = Ssl::bumpEnd; // SslBump does not apply; log -
debugs(85, 5, HERE << "cannot SslBump this request");
return false;
// For intercepted connections, set the host name to the server
// certificate CN. Otherwise, we just hope that CONNECT is using
// a user-entered address (a host name or a user-entered IP).
- const bool isConnectRequest = !request->clientConnectionManager->port->spoof_client_ip &&
- !request->clientConnectionManager->port->intercepted;
+ const bool isConnectRequest = !request->clientConnectionManager->port->flags.tproxyIntercept &&
+ !request->clientConnectionManager->port->flags.natIntercept;
if (request->flags.sslPeek && !isConnectRequest) {
if (X509 *srvX509 = errDetails->peerCert()) {
if (const char *name = Ssl::CommonHostName(srvX509)) {
// unless it was the CONNECT request with a user-typed address.
const char *hostname = request->GetHost();
const bool hostnameIsIp = request->GetHostIsNumeric();
- const bool isConnectRequest = !request->clientConnectionManager->port->spoof_client_ip &&
- !request->clientConnectionManager->port->intercepted;
+ const bool isConnectRequest = !request->clientConnectionManager->port->flags.tproxyIntercept &&
+ !request->clientConnectionManager->port->flags.natIntercept;
if (!request->flags.sslPeek || isConnectRequest)
SSL_set_ex_data(ssl, ssl_ex_index_server, (void*)hostname);
// we need to start ssl_crtd only if some port(s) need to bump SSL
bool found = false;
for (AnyP::PortCfg *s = ::Config.Sockaddr.http; !found && s; s = s->next)
- found = s->sslBump;
+ found = s->flags.tunnelSslBumping;
for (AnyP::PortCfg *s = ::Config.Sockaddr.https; !found && s; s = s->next)
- found = s->sslBump;
+ found = s->flags.tunnelSslBumping;
if (!found)
return;
// we need to start ssl_crtd only if some port(s) need to bump SSL
bool found = false;
for (AnyP::PortCfg *s = ::Config.Sockaddr.http; !found && s; s = s->next)
- found = s->sslBump;
+ found = s->flags.tunnelSslBumping;
for (AnyP::PortCfg *s = ::Config.Sockaddr.https; !found && s; s = s->next)
- found = s->sslBump;
+ found = s->flags.tunnelSslBumping;
if (!found)
return;
AnyP::PortCfg *p = NULL;
if ((p = Config.Sockaddr.http)) {
// skip any special interception ports
- while (p && (p->intercepted || p->spoof_client_ip))
+ while (p && (p->flags.natIntercept || p->flags.tproxyIntercept))
p = p->next;
if (p)
return p->s.GetPort();
#if USE_SSL
if ((p = Config.Sockaddr.https)) {
// skip any special interception ports
- while (p && (p->intercepted || p->spoof_client_ip))
+ while (p && (p->flags.natIntercept || p->flags.tproxyIntercept))
p = p->next;
if (p)
return p->s.GetPort();