On 26.02.13 21:56, Amos Jeffries wrote:
I'm happy with the use-case too now. If the code adjusted to 3.HEAD
still looks good I think it could go in.
I've attached a patch against 3.HEAD. I've tested it, although I would
appreciate it if you could double check that I'm using
HttpRequest::Pointer correctly in client_side.cc.
As well as the spoof_client_ip ACL, this introduces a new request flag
called interceptTproxy, which is set for all TPROXY requests. The
spoofClientIp flag is now only set for TPROXY requests that we want to
spoof.
Many thanks.
--
- Steve Hill
Technical Director
Opendium Limited http://www.opendium.com
Direct contacts:
Instant messager: xmpp:[email protected]
Email: [email protected]
Phone: sip:[email protected]
Sales / enquiries contacts:
Email: [email protected]
Phone: +44-844-9791439 / sip:[email protected]
Support contacts:
Email: [email protected]
Phone: +44-844-4844916 / sip:[email protected]
=== modified file 'src/HttpRequest.cc'
--- src/HttpRequest.cc 2013-02-17 02:24:54 +0000
+++ src/HttpRequest.cc 2013-02-28 10:08:37 +0000
@@ -596,7 +597,7 @@
// 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) {
=== modified file 'src/RequestFlags.h'
--- src/RequestFlags.h 2013-01-24 10:26:24 +0000
+++ src/RequestFlags.h 2013-02-27 15:34:00 +0000
@@ -87,7 +87,12 @@
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;
=== modified file 'src/SquidConfig.h'
--- src/SquidConfig.h 2013-02-08 09:25:04 +0000
+++ src/SquidConfig.h 2013-02-27 15:39:40 +0000
@@ -403,6 +403,10 @@
#if ICAP_CLIENT
acl_access* icap;
#endif
+
+ /// spoof_client_ip squid.conf acl.
+ /// nil unless configured
+ acl_access* spoof_client_ip;
} accessList;
AclDenyInfoList *denyInfoList;
=== modified file 'src/acl/DestinationIp.cc'
--- src/acl/DestinationIp.cc 2013-01-28 16:56:05 +0000
+++ src/acl/DestinationIp.cc 2013-02-27 15:30:24 +0000
@@ -56,7 +56,7 @@
// 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);
}
=== modified file 'src/auth/Acl.cc'
--- src/auth/Acl.cc 2012-09-19 17:16:56 +0000
+++ src/auth/Acl.cc 2013-02-27 15:27:16 +0000
@@ -34,7 +34,7 @@
} 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 {
=== modified file 'src/cache_cf.cc'
--- src/cache_cf.cc 2013-02-10 16:31:40 +0000
+++ src/cache_cf.cc 2013-02-27 15:19:13 +0000
@@ -3605,8 +3605,7 @@
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.");
=== modified file 'src/cf.data.pre'
--- src/cf.data.pre 2013-02-12 21:49:03 +0000
+++ src/cf.data.pre 2013-02-27 15:38:15 +0000
@@ -1223,6 +1223,27 @@
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
+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
@@ -2936,6 +2957,7 @@
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.
=== modified file 'src/client_side.cc'
--- src/client_side.cc 2013-02-12 11:34:35 +0000
+++ src/client_side.cc 2013-02-27 16:38:57 +0000
@@ -2696,7 +2696,14 @@
*/
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 = 1;
+ } else request->flags.spoofClientIp = 0;
}
if (internalCheck(request->urlpath.termedBuf())) {
@@ -3598,7 +3605,7 @@
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;
@@ -3607,10 +3614,17 @@
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 = 1;
+ } else fakeRequest->flags.spoofClientIp = 0;
debugs(33, 4, HERE << details << " try to generate a Dynamic SSL CTX");
- connState->switchToHttps(fakeRequest, bumpMode);
+ connState->switchToHttps(fakeRequest.getRaw(), bumpMode);
}
}
@@ -4145,7 +4159,7 @@
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 "
=== modified file 'src/client_side_request.cc'
--- src/client_side_request.cc 2013-02-12 11:34:35 +0000
+++ src/client_side_request.cc 2013-02-27 15:29:59 +0000
@@ -671,7 +671,7 @@
}
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() <<
@@ -971,7 +971,7 @@
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;
/*
=== modified file 'src/format/Format.cc'
--- src/format/Format.cc 2013-02-11 23:11:12 +0000
+++ src/format/Format.cc 2013-02-27 15:27:44 +0000
@@ -383,7 +383,7 @@
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) {
=== modified file 'src/forward.cc'
--- src/forward.cc 2013-02-18 13:02:42 +0000
+++ src/forward.cc 2013-02-27 15:31:33 +0000
@@ -151,7 +151,7 @@
// 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();
=== modified file 'src/peer_select.cc'
--- src/peer_select.cc 2013-02-12 11:34:35 +0000
+++ src/peer_select.cc 2013-02-27 15:34:13 +0000
@@ -236,7 +236,7 @@
// 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) {
@@ -343,7 +343,7 @@
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.
=== modified file 'src/tunnel.cc'
--- src/tunnel.cc 2013-02-12 11:34:35 +0000
+++ src/tunnel.cc 2013-02-27 15:26:54 +0000
@@ -541,7 +541,7 @@
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",