Blocking SSL requests.

Asked by Daryl Radivojevic

I have modified adapter_minimal.cc from ecap_adapter_sample-0.2.0.tar.gz to block a website.

This example does not work with HTTPS requests but does work fine with HTTP requests. I am not sure
what I am doing wrong.
The response is not encrypted in directed proxy mode (but works in transparent proxy mode).

Here is my modification to adapter_minimal.cc:

void Adapter::Xaction::start() {
 Must(hostx);

 if (libecap::RequestLine *requestLine = dynamic_cast<libecap::RequestLine *>(&hostx->virgin().firstLine())) {
  const libecap::Area &uri = requestLine->uri();
  if (strnstr(uri.start, "playboy", uri.size) != NULL) {
   // make this adapter non-callable
   libecap::host::Xaction *x = hostx;
   hostx = 0;
   x->blockVirgin();
   return;
  }
 }

 // make this adapter non-callable
 libecap::host::Xaction *x = hostx;
 hostx = 0;

 // tell the host to use the virgin message
 x->useVirgin();
}

This is with squid 3.2.0.9, 3.2.0.10 & 3.2.0.10-20110811 on Debian 6.0 and CentOS 6.0.
Configured with --enable-ecap --enable-ssl & --enable-ssl-crtd (among other things.)

Question information

Language:
English Edit question
Status:
Solved
For:
eCAP Edit question
Assignee:
No assignee Edit question
Solved by:
Alex Rousskov
Solved:
Last query:
Last reply:
Revision history for this message
Alex Rousskov (rousskov) said :
#1

I do not see anything wrong with your eCAP adapter code snippet.

eCAP does not deal with the SSL encryption layer. If the block message is not encrypted on its way from Squid to the Squid client, this is a Squid bug. Please file a bug report with Squid bugzilla instead. Thank you.

Revision history for this message
Daryl Radivojevic (daryl-rad) said :
#2

I worked out how to get the correct response. It seems that I need to check that the URI starts with the protocol scheme, before I can use blockVirgin().

Modified example from above:

void Adapter::Xaction::start() {
 Must(hostx);

 if (libecap::RequestLine *requestLine = dynamic_cast<libecap::RequestLine *>(&hostx->virgin().firstLine())) {
  const libecap::Area &uri = requestLine->uri();
  if (strnstr(uri.start, "playboy", uri.size) != NULL) {
   if (strncmp(uri.start, "http", 4) != 0)
    goto useV;
   // make this adapter non-callable
   libecap::host::Xaction *x = hostx;
   hostx = 0;
   x->blockVirgin();
   return;
  }
 }

 useV:
 // make this adapter non-callable
 libecap::host::Xaction *x = hostx;
 hostx = 0;

 // tell the host to use the virgin message
 x->useVirgin();
}

Is there something that I need to configure in squid.conf to avoid getting SSL level eCAP calls?

Revision history for this message
Alex Rousskov (rousskov) said :
#3

It sounds like I do not understand the problem you are trying to solve, but, in general, both encrypted and plain requests may have Request-URIs that start (or do not start) with "http" if you look at raw headers.

Also, since Squid trunk r11270 (dated 2011-03-09), Squid should give always full URI to eCAP adapters (i.e., URI with scheme and host name followed by path). Thus, most URIs your adapter gets should start with http (both http://... and https://... URIs do). I believe that revision is in recent Squid v3.2 releases as well, but I have not checked that. URIs that do not start with "http" are ftp://... URIs and such.

If you need further help, please give specific examples of uri variable values (e.g., add debugging to your adapter) and explain how the beginning of a URI is related to SSL.

Thank you.

Revision history for this message
Daryl Radivojevic (daryl-rad) said :
#4

The problem is that squid calls void Adapter::Xaction::start() twice for each HTTPS request, whereas I expect it to be called only once. If I use blockVirgin() on the first Adapter::Xaction::start() call which does not contain URI with scheme, than that request is not processed by the browser.

If I add:
cout << __PRETTY_FUNCTION__ << ": " << uri << endl;
after "const libecap::Area &uri = requestLine->uri();" in my code above, this is the output from my
eCAP adapter when I browse to "https://www.playboy.com":

virtual void Adapter::Xaction::start(): www.playboy.com:443
virtual void Adapter::Xaction::start(): https://www.playboy.com/
virtual void Adapter::Xaction::start(): http://www.squid-cache.org/Artwork/SN.png

This is with ssl-bump enabled. Squid version:
# squid -v
Squid Cache: Version 3.2.0.9
configure options: '--prefix=/usr' '--includedir=/usr/include' '--datadir=/usr/share' '--bindir=/usr/sbin' '--libexecdir=/usr/lib/squid' '--localstatedir=/var' '--sysconfdir=/etc/squid' '--enable-async-io=64' '--with-pthreads' '--enable-storeio=diskd,ufs,aufs' '--enable-epoll' '--enable-removal-policies=heap,lru' '--with-large-files' '--enable-auth' '--enable-ntlm-auth-helpers=smb_lm' '--enable-basic-auth-helpers=MSNT,NCSA,LDAP,squid_radius_auth' '--enable-icap-client' '--with-filedescriptors=16384' '--enable-linux-netfilter' '--enable-ecap' '--enable-ssl' '--enable-ssl-crtd' 'PKG_CONFIG_PATH=/usr/local/lib/pkgconfig'

Revision history for this message
Alex Rousskov (rousskov) said :
#5

Squid does not send the same HTTPS request to the same REQMOD service twice. Based on your logs, the first request you got in your environment was an HTTP CONNECT request. The second was an HTTPS GET request.

IMO, you should detect CONNECT requests by their method, not URI pattern. Moreover, if you want to block based on a domain name, then blocking CONNECT request would be sufficient to prevent all subsequent HTTPS communication with that domain (there will be no HTTPS requests at all if all CONNECTs are blocked correctly).

Revision history for this message
Daryl Radivojevic (daryl-rad) said :
#6

O.K. That mostly answers my question. So if I use:

  if (requestLine->method() == libecap::methodConnect)
   goto useV;

I get the same result.

What should I use to block CONNECT requests, if not blockVirgin() ? Is this a bug with squid eCAP implementation that I should report?

Revision history for this message
Best Alex Rousskov (rousskov) said :
#7

I do not know what "same result" you are referring to exactly, but if you are saying that detecting CONNECT requests using request method is the same as detecting them by comparing the first URL characters with "http", then I do not think it is true in general. Consider an HTTP request with ftp://host/path URI, for example. Or a CONNECT request to http.com.

You should use blockVirgin() to block any message that needs blocking and that you have not started adapting yet, regardless of the associated request method or request URI.

If Squid does not respond with an access denial message when you use blockVirgin() in a REQMOD, then it does sound like a Squid bug and you should report it to Squid bugzilla, IMO, provided it has not been already reported there by others, of course.

Revision history for this message
Daryl Radivojevic (daryl-rad) said :
#8

Thanks Alex Rousskov, that solved my question.