]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Splice to origin cache_peer.
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Tue, 14 Jul 2015 17:51:21 +0000 (10:51 -0700)
committerAmos Jeffries <squid3@treenet.co.nz>
Tue, 14 Jul 2015 17:51:21 +0000 (10:51 -0700)
Currently, Squid cannot redirect intercepted connections that are subject to
SslBump rules to _originserver_ cache_peer. For example, consider Squid that
enforces "safe search" by redirecting clients to forcesafesearch.example.com.
Consider a TLS client that tries to connect to www.example.com. Squid needs to
send that client to forcesafesearch.example.com (without changing the host
header and SNI information; those would still point to www.example.com for
safe search to work as intended!).

The admin may configure Squid to send intercepted clients to an originserver
cache_peer with the forcesafesearch.example.com address. Such a configuration
does not currently work together with ssl_bump peek/splice rules.

This patch:

* Fixes src/neighbors.cc bug which prevented CONNECT requests from going
  to originserver cache peers. This bug affects both true CONNECT requests
  and intercepted SSL/TLS connections (with fake CONNECT requests). Squid
  use the CachePeer::in_addr.port which is not meant to be used for the HTTP
  port, apparently. HTTP checks should use CachePeer::http_port instead.

* Changes Squid to not initiate SSL/TLS connection to cache_peer for
  true CONNECT requests.

* Allows forwarding being-peeked (or stared) at connections to originserver
  cache_peers.

The bug fix described in the first bullet makes the last two changes
necessary.

This is a Measurement Factory project.

src/FwdState.cc
src/neighbors.cc

index 7fea9e259cb7391667774aa2301012b38626f61b..d0c1b090d33092651f00184cee576b60aa3c6010 100644 (file)
@@ -683,10 +683,14 @@ FwdState::connectDone(const Comm::ConnectionPointer &conn, Comm::Flag status, in
 
 #if USE_OPENSSL
     if (!request->flags.pinned) {
-        if ((serverConnection()->getPeer() && serverConnection()->getPeer()->use_ssl) ||
-                (!serverConnection()->getPeer() && request->url.getScheme() == AnyP::PROTO_HTTPS) ||
-                request->flags.sslPeek) {
-
+        const CachePeer *p = serverConnection()->getPeer();
+        const bool peerWantsTls = p && p->use_ssl;
+        // userWillSslToPeerForUs assumes CONNECT == HTTPS
+        const bool userWillTlsToPeerForUs = p && p->options.originserver &&
+                                            request->method == Http::METHOD_CONNECT;
+        const bool needTlsToPeer = peerWantsTls && !userWillTlsToPeerForUs;
+        const bool needTlsToOrigin = !p && request->url.getScheme() == AnyP::PROTO_HTTPS;
+        if (needTlsToPeer || needTlsToOrigin || request->flags.sslPeek) {
             HttpRequest::Pointer requestPointer = request;
             AsyncCall::Pointer callback = asyncCall(17,4,
                                                     "FwdState::ConnectedToPeer",
@@ -782,7 +786,9 @@ FwdState::connectStart()
 
     request->hier.startPeerClock();
 
-    if (serverDestinations[0]->getPeer() && request->flags.sslBumped) {
+    // Do not fowrward bumped connections to parent proxy unless it is an
+    // origin server
+    if (serverDestinations[0]->getPeer() && !serverDestinations[0]->getPeer()->options.originserver && request->flags.sslBumped) {
         debugs(50, 4, "fwdConnectStart: Ssl bumped connections through parent proxy are not allowed");
         ErrorState *anErr = new ErrorState(ERR_CANNOT_FORWARD, Http::scServiceUnavailable, request);
         fail(anErr);
index a656193a99190a09d988d0abac6bc9823d095fa2..49320f653ccb60ff8d5f72065df34946e67dcda3 100644 (file)
@@ -161,7 +161,7 @@ peerAllowedToUse(const CachePeer * p, HttpRequest * request)
 
     // CONNECT requests are proxy requests. Not to be forwarded to origin servers.
     // Unless the destination port matches, in which case we MAY perform a 'DIRECT' to this CachePeer.
-    if (p->options.originserver && request->method == Http::METHOD_CONNECT && request->port != p->in_addr.port())
+    if (p->options.originserver && request->method == Http::METHOD_CONNECT && request->port != p->http_port)
         return false;
 
     if (p->peer_domain == NULL && p->access == NULL)