// Because it failed verification, or someone bypassed the security tests
// we cannot cache the reponse for sharing between clients.
// TODO: update cache to store for particular clients only (going to same Host: and destination IP)
- if (!flags.hostVerified && (flags.intercepted || flags.spoofClientIp))
+ if (!flags.hostVerified && (flags.intercepted || flags.interceptTproxy))
return false;
switch (protocol) {
bool intercepted :1;
/** set if the Host: header passed verification */
bool hostVerified :1;
- /** request to spoof the client ip */
+ /// Set for requests handled by a "tproxy" port.
+ bool interceptTproxy :1;
+ /// The client IP address should be spoofed when connecting to the web server.
+ /// This applies to TPROXY traffic that has not had spoofing disabled through
+ /// the spoof_client_ip squid.conf ACL.
bool spoofClientIp :1;
/** set if the request is internal (\see ClientHttpRequest::flags.internal)*/
bool internal :1;
#if ICAP_CLIENT
acl_access* icap;
#endif
+
+ /// spoof_client_ip squid.conf acl.
+ /// nil unless configured
+ acl_access* spoof_client_ip;
} accessList;
AclDenyInfoList *denyInfoList;
// Bypass of browser same-origin access control in intercepted communication
// To resolve this we will force DIRECT and only to the original client destination.
// In which case, we also need this ACL to accurately match the destination
- if (Config.onoff.client_dst_passthru && (checklist->request->flags.intercepted || checklist->request->flags.spoofClientIp)) {
+ if (Config.onoff.client_dst_passthru && (checklist->request->flags.intercepted || checklist->request->flags.interceptTproxy)) {
assert(checklist->conn() && checklist->conn()->clientConnection != NULL);
return ACLIP::match(checklist->conn()->clientConnection->local);
}
} else if (request->flags.accelerated) {
/* WWW authorization on accelerated requests */
headertype = HDR_AUTHORIZATION;
- } else if (request->flags.intercepted || request->flags.spoofClientIp) {
+ } else if (request->flags.intercepted || request->flags.interceptTproxy) {
debugs(28, DBG_IMPORTANT, "NOTICE: Authentication not applicable on intercepted requests.");
return ACCESS_DENIED;
} else {
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);
- debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (IP spoofing enabled)");
+ debugs(3, DBG_IMPORTANT, "Disabling Authentication on port " << s->s << " (TPROXY enabled)");
if (!Ip::Interceptor.ProbeForTproxy(s->s)) {
debugs(3, DBG_CRITICAL, "FATAL: http(s)_port: TPROXY support in the system does not work.");
sources is required to prevent abuse of your proxy.
DOC_END
+NAME: spoof_client_ip
+TYPE: acl_access
+LOC: Config.accessList.spoof_client_ip
+DEFAULT: none
+DEFAULT_DOC: Allow spoofing on all TPROXY traffic.
+DOC_START
+ Control client IP address spoofing of TPROXY traffic based on
+ defined access lists.
+
+ spoof_client_ip allow|deny [!]aclname ...
+
+ If there are no "spoof_client_ip" lines present, the default
+ is to "allow" spoofing of any suitable request.
+
+ Note that the cache_peer "no-tproxy" option overrides this ACL.
+
+ This clause supports fast acl types.
+ See http://wiki.squid-cache.org/SquidFaq/SquidAcl for details.
+DOC_END
+
NAME: http_access
TYPE: acl_access
LOC: Config.accessList.http
no-tproxy Do not use the client-spoof TPROXY support when forwarding
requests to this peer. Use normal address selection instead.
+ This overrides the spoof_client_ip ACL.
proxy-only objects fetched from the peer will not be stored locally.
*/
if (http->clientConnection != NULL) {
request->flags.intercepted = ((http->clientConnection->flags & COMM_INTERCEPTION) != 0);
- request->flags.spoofClientIp = ((http->clientConnection->flags & COMM_TRANSPARENT) != 0 ) ;
+ request->flags.interceptTproxy = ((http->clientConnection->flags & COMM_TRANSPARENT) != 0 ) ;
+ if (request->flags.interceptTproxy) {
+ if (Config.accessList.spoof_client_ip) {
+ ACLFilledChecklist *checklist = clientAclChecklistCreate(Config.accessList.spoof_client_ip, http);
+ request->flags.spoofClientIp = (checklist->fastCheck() == ACCESS_ALLOWED);
+ delete checklist;
+ } else
+ request->flags.spoofClientIp = true;
+ } else
+ request->flags.spoofClientIp = false;
}
if (internalCheck(request->urlpath.termedBuf())) {
else {
char buf[MAX_IPSTRLEN];
assert(bumpMode != Ssl::bumpNone && bumpMode != Ssl::bumpEnd);
- HttpRequest *fakeRequest = new HttpRequest;
+ HttpRequest::Pointer fakeRequest(new HttpRequest);
fakeRequest->SetHost(details->local.NtoA(buf, sizeof(buf)));
fakeRequest->port = details->local.GetPort();
fakeRequest->clientConnectionManager = connState;
fakeRequest->indirect_client_addr = connState->clientConnection->remote;
#endif
fakeRequest->my_addr = connState->clientConnection->local;
- fakeRequest->flags.spoofClientIp = ((connState->clientConnection->flags & COMM_TRANSPARENT) != 0 ) ;
+ fakeRequest->flags.interceptTproxy = ((connState->clientConnection->flags & COMM_TRANSPARENT) != 0 ) ;
fakeRequest->flags.intercepted = ((connState->clientConnection->flags & COMM_INTERCEPTION) != 0);
+ fakeRequest->myportname = connState->port->name;
+ if (fakeRequest->flags.interceptTproxy) {
+ if (Config.accessList.spoof_client_ip) {
+ ACLFilledChecklist checklist(Config.accessList.spoof_client_ip, fakeRequest.getRaw(), NULL);
+ fakeRequest->flags.spoofClientIp = (checklist.fastCheck() == ACCESS_ALLOWED);
+ } else
+ fakeRequest->flags.spoofClientIp = true;
+ } else
+ fakeRequest->flags.spoofClientIp = false;
debugs(33, 4, HERE << details << " try to generate a Dynamic SSL CTX");
- connState->switchToHttps(fakeRequest, bumpMode);
+ connState->switchToHttps(fakeRequest.getRaw(), bumpMode);
}
}
debugs(1, DBG_IMPORTANT, "Accepting " <<
(s->flags.natIntercept ? "NAT intercepted " : "") <<
- (s->flags.tproxyIntercept ? "TPROXY spoofing " : "") <<
+ (s->flags.tproxyIntercept ? "TPROXY intercepted " : "") <<
(s->flags.tunnelSslBumping ? "SSL bumped " : "") <<
(s->flags.accelSurrogate ? "reverse-proxy " : "")
<< FdNote(portTypeNote) << " connections at "
}
debugs(85, 3, HERE << "validate host=" << host << ", port=" << port << ", portStr=" << (portStr?portStr:"NULL"));
- if (http->request->flags.intercepted || http->request->flags.spoofClientIp) {
+ if (http->request->flags.intercepted || http->request->flags.interceptTproxy) {
// verify the Host: port (if any) matches the apparent destination
if (portStr && port != http->getConn()->clientConnection->local.GetPort()) {
debugs(85, 3, HERE << "FAIL on validate port " << http->getConn()->clientConnection->local.GetPort() <<
const wordlist *p = NULL;
// intercepted requests MUST NOT (yet) be sent to peers unless verified
- if (!request->flags.hostVerified && (request->flags.intercepted || request->flags.spoofClientIp))
+ if (!request->flags.hostVerified && (request->flags.intercepted || request->flags.interceptTproxy))
return 0;
/*
case LFT_LOCAL_LISTENING_IP: {
// avoid logging a dash if we have reliable info
const bool interceptedAtKnownPort = al->request ?
- (al->request->flags.spoofClientIp ||
+ (al->request->flags.interceptTproxy ||
al->request->flags.intercepted) && al->cache.port :
false;
if (interceptedAtKnownPort) {
// Bug 3243: CVE 2009-0801
// Bypass of browser same-origin access control in intercepted communication
// To resolve this we must force DIRECT and only to the original client destination.
- const bool isIntercepted = request && !request->flags.redirected && (request->flags.intercepted || request->flags.spoofClientIp);
+ const bool isIntercepted = request && !request->flags.redirected && (request->flags.intercepted || request->flags.interceptTproxy);
const bool useOriginalDst = Config.onoff.client_dst_passthru || (request && !request->flags.hostVerified);
if (isIntercepted && useOriginalDst) {
selectPeerForIntercepted();
// on intercepted traffic which failed Host verification
const HttpRequest *req = psstate->request;
const bool isIntercepted = !req->flags.redirected &&
- (req->flags.intercepted || req->flags.spoofClientIp);
+ (req->flags.intercepted || req->flags.interceptTproxy);
const bool useOriginalDst = Config.onoff.client_dst_passthru || !req->flags.hostVerified;
const bool choseDirect = fs && fs->code == HIER_DIRECT;
if (isIntercepted && useOriginalDst && choseDirect) {
if (psstate->paths->size() >= (unsigned int)Config.forward_max_tries)
break;
- // for TPROXY we must skip unusable addresses.
+ // for TPROXY spoofing we must skip unusable addresses.
if (psstate->request->flags.spoofClientIp && !(fs->_peer && fs->_peer->options.no_tproxy) ) {
if (ia->in_addrs[n].IsIPv4() != psstate->request->client_addr.IsIPv4()) {
// we CAN'T spoof the address on this link. find another.
TunnelStateData *tunnelState = (TunnelStateData *)data;
debugs(26, 3, HERE << server << ", tunnelState=" << tunnelState);
- if (tunnelState->request && (tunnelState->request->flags.spoofClientIp || tunnelState->request->flags.intercepted))
+ if (tunnelState->request && (tunnelState->request->flags.interceptTproxy || tunnelState->request->flags.intercepted))
tunnelStartShoveling(tunnelState); // ssl-bumped connection, be quiet
else {
AsyncCall::Pointer call = commCbCall(5,5, "tunnelConnectedWriteDone",