From: Christos Tsantilas Date: Fri, 16 Jun 2017 13:38:16 +0000 (+0300) Subject: tproxy does not spoof spliced connections X-Git-Tag: M-staged-PR71~115 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=cd4a5c6055c1511509373b8f89595224c512f03d;p=thirdparty%2Fsquid.git tproxy does not spoof spliced connections Squid does not spoof client IP addresses when splicing after peeking/staring. This is a Measurement Factory project --- diff --git a/src/HttpRequest.cc b/src/HttpRequest.cc index 9b75838d19..d08ad3e037 100644 --- a/src/HttpRequest.cc +++ b/src/HttpRequest.cc @@ -13,6 +13,7 @@ #include "acl/AclSizeLimit.h" #include "acl/FilledChecklist.h" #include "client_side.h" +#include "client_side_request.h" #include "dns/LookupDetails.h" #include "Downloader.h" #include "err_detail_type.h" @@ -693,3 +694,42 @@ UpdateRequestNotes(ConnStateData *csd, HttpRequest &request, NotePairs const &he request.notes()->replaceOrAdd(&helperNotes); } + +void +HttpRequest::manager(const CbcPointer &aMgr, const AccessLogEntryPointer &al) +{ + clientConnectionManager = aMgr; + + if (!clientConnectionManager.valid()) + return; + + AnyP::PortCfgPointer port = clientConnectionManager->port; + if (port) { + myportname = port->name; + flags.ignoreCc = port->ignore_cc; + } + + if (auto clientConnection = clientConnectionManager->clientConnection) { + client_addr = clientConnection->remote; // XXX: remove request->client_addr member. +#if FOLLOW_X_FORWARDED_FOR + // indirect client gets stored here because it is an HTTP header result (from X-Forwarded-For:) + // not details about the TCP connection itself + indirect_client_addr = clientConnection->remote; +#endif /* FOLLOW_X_FORWARDED_FOR */ + my_addr = clientConnection->local; + + flags.intercepted = ((clientConnection->flags & COMM_INTERCEPTION) != 0); + flags.interceptTproxy = ((clientConnection->flags & COMM_TRANSPARENT) != 0 ) ; + const bool proxyProtocolPort = port ? port->flags.proxySurrogate : false; + if (flags.interceptTproxy && !proxyProtocolPort) { + if (Config.accessList.spoof_client_ip) { + ACLFilledChecklist *checklist = new ACLFilledChecklist(Config.accessList.spoof_client_ip, this, clientConnection->rfc931); + checklist->al = al; + flags.spoofClientIp = (checklist->fastCheck() == ACCESS_ALLOWED); + delete checklist; + } else + flags.spoofClientIp = true; + } else + flags.spoofClientIp = false; + } +} diff --git a/src/HttpRequest.h b/src/HttpRequest.h index ef13d19af7..3aec5fd9fd 100644 --- a/src/HttpRequest.h +++ b/src/HttpRequest.h @@ -36,6 +36,8 @@ class ConnStateData; class Downloader; +class AccessLogEntry; +typedef RefCount AccessLogEntryPointer; /* Http Request */ void httpRequestPack(void *obj, Packable *p); @@ -88,6 +90,9 @@ public: /// clear error details, useful for retries/repeats void clearError(); + /// associates the request with a from-client connection manager + void manager(const CbcPointer &aMgr, const AccessLogEntryPointer &al); + protected: void clean(); diff --git a/src/client_side.cc b/src/client_side.cc index d8a5af00b1..d1bc0919bf 100644 --- a/src/client_side.cc +++ b/src/client_side.cc @@ -1634,11 +1634,11 @@ clientProcessRequest(ConnStateData *conn, const Http1::RequestParserPointer &hp, // this entire function to remove them from the FTP code path. Connection // setup and body_pipe preparation blobs are needed for FTP. - request->clientConnectionManager = conn; + + request->manager(conn, http->al); request->flags.accelerated = http->flags.accel; request->flags.sslBumped=conn->switchedToHttps(); - request->flags.ignoreCc = conn->port->ignore_cc; // TODO: decouple http->flags.accel from request->flags.sslBumped request->flags.noDirect = (request->flags.accelerated && !request->flags.sslBumped) ? !conn->port->allow_direct : 0; @@ -1651,25 +1651,6 @@ clientProcessRequest(ConnStateData *conn, const Http1::RequestParserPointer &hp, } #endif - /** \par - * If transparent or interception mode is working clone the transparent and interception flags - * from the port settings to the request. - */ - if (http->clientConnection != NULL) { - request->flags.intercepted = ((http->clientConnection->flags & COMM_INTERCEPTION) != 0); - request->flags.interceptTproxy = ((http->clientConnection->flags & COMM_TRANSPARENT) != 0 ) ; - static const bool proxyProtocolPort = (conn->port != NULL) ? conn->port->flags.proxySurrogate : false; - if (request->flags.interceptTproxy && !proxyProtocolPort) { - 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->url.path())) { if (internalHostnameIs(request->url.host()) && request->url.port() == getMyPort()) { debugs(33, 2, "internal URL found: " << request->url.getScheme() << "://" << request->url.authority(true)); @@ -1686,14 +1667,6 @@ clientProcessRequest(ConnStateData *conn, const Http1::RequestParserPointer &hp, request->flags.internal = http->flags.internal; setLogUri (http, urlCanonicalClean(request.getRaw())); - request->client_addr = conn->clientConnection->remote; // XXX: remove request->client_addr member. -#if FOLLOW_X_FORWARDED_FOR - // indirect client gets stored here because it is an HTTP header result (from X-Forwarded-For:) - // not details about the TCP connection itself - request->indirect_client_addr = conn->clientConnection->remote; -#endif /* FOLLOW_X_FORWARDED_FOR */ - request->my_addr = conn->clientConnection->local; - request->myportname = conn->port->name; if (!isFtp) { // XXX: for non-HTTP messages instantiate a different Http::Message child type @@ -1704,10 +1677,6 @@ clientProcessRequest(ConnStateData *conn, const Http1::RequestParserPointer &hp, request->http_ver.minor = http_ver.minor; } - // Link this HttpRequest to ConnStateData relatively early so the following complex handling can use it - // TODO: this effectively obsoletes a lot of conn->FOO copying. That needs cleaning up later. - request->clientConnectionManager = conn; - if (request->header.chunked()) { chunked = true; } else if (request->header.has(Http::HdrType::TRANSFER_ENCODING)) { @@ -3451,23 +3420,16 @@ ConnStateData::buildFakeRequest(Http::MethodType const method, SBuf &useHost, un http->request = request.getRaw(); HTTPMSGLOCK(http->request); - request->clientConnectionManager = this; + request->manager(this, http->al); if (proto == AnyP::PROTO_HTTP) request->header.putStr(Http::HOST, useHost.c_str()); - request->flags.intercepted = ((clientConnection->flags & COMM_INTERCEPTION) != 0); - request->flags.interceptTproxy = ((clientConnection->flags & COMM_TRANSPARENT) != 0 ); + request->sources |= ((switchedToHttps() || port->transport.protocol == AnyP::PROTO_HTTPS) ? Http::Message::srcHttps : Http::Message::srcHttp); #if USE_AUTH if (getAuth()) request->auth_user_request = getAuth(); #endif - request->client_addr = clientConnection->remote; -#if FOLLOW_X_FORWARDED_FOR - request->indirect_client_addr = clientConnection->remote; -#endif /* FOLLOW_X_FORWARDED_FOR */ - request->my_addr = clientConnection->local; - request->myportname = port->name; inBuf = payload; flags.readMore = false;