]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Splice to origin cache_peer.
authorChristos Tsantilas <chtsanti@users.sourceforge.net>
Fri, 3 Jul 2015 14:07:05 +0000 (17:07 +0300)
committerChristos Tsantilas <chtsanti@users.sourceforge.net>
Fri, 3 Jul 2015 14:07:05 +0000 (17:07 +0300)
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 4b87b1ad28fcfa610d65ac4706a86a209cbfbf79..0e1a892b4ced207c8c3c0c74dce3bd61645c403e 100644 (file)
@@ -691,10 +691,14 @@ FwdState::connectDone(const Comm::ConnectionPointer &conn, Comm::Flag status, in
 
 #if USE_OPENSSL
     if (!request->flags.pinned) {
-        if ((serverConnection()->getPeer() && serverConnection()->getPeer()->secure.encryptTransport) ||
-                (!serverConnection()->getPeer() && request->url.getScheme() == AnyP::PROTO_HTTPS) ||
-                request->flags.sslPeek) {
-
+        const CachePeer *p = serverConnection()->getPeer();
+        const bool peerWantsTls = p && p->secure.encryptTransport;
+        // 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",
@@ -790,7 +794,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 9f8b05201adeda0b0a2614ad4349a631fe06a43b..6903239202f2bc425a530d433600ef8c7a53cfb3 100644 (file)
@@ -159,7 +159,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->url.port() != p->in_addr.port())
+    if (p->options.originserver && request->method == Http::METHOD_CONNECT && request->url.port() != p->http_port)
         return false;
 
     if (p->access == NULL)