Squid Proxy — Transparent SSL Web Proxy redirection using WCCP, Cisco ASA, and Squid 3.4+

I’ve posted a few articles on how to set up a Forwarding Proxy using Squid, and using benefits like caching and content blocking (Ads, adult, gambling, etc). This can bring centralized web security and delivery to you and your users.  However, users need to be expliclty configured to use the Proxy service. This means having their web browser like Firefox or even Internet Explorer set with the DNS or IP address of the Proxy server. This can be an issue if youhave little or no management of the user’s Web Browsers configuration.  This is where a content-routing protocol like WCCP(Web Cache Communication Protocol) comes into play. With WCCP we can influence specific user traffic to be encapsulated and re-routed to your Proxy server. The difference between this and some of the other ways to force web traffic to your Proxy server(like iptables redirection) is the original Web packet generated by the user’s device is not altered. Instead it is encapsulated when it reaches your WCCP receiver running on an upstream egress router(user gateway towards Internet). It is then re-routed via this encapsulation to your Proxy server which is WCCP aware.

Before we begin, you will need a few things:

  • Squid Proxy Server 3.4+ compiled with WCCP
  • Router or Security device capable of running the WCCPv2 service(See vendor list here…)
  • Some knowledge of Web Proxy Technology.
  • A Web Browser to test with.
  • Your favorite beverage and some patients.

Topology

Notice: Cisco ASA only supports having the user subnet(s) and the cache-engine(Squid Proxy server) behind the same Cisco ASA interface(inside,dmz,outside,etc). The reason for this is the WCCP processing on the ASA happens after interface ACL, meaning for example ACL on your inside interface are processed before any WCCP manipulation can begin.

  1. User requests a web resource on outside interface(usually the Internet) of Router/Firewall.
  2. WCCP Server (Router/Firewall) catches this interesting traffic(traffic we want to redirect) and encapsulates it within a GRE tunnel to the WCCP Client(Squid Proxy Server) on the other end of the tunnel.
  3. WCCP Client (Squid Proxy Server) decapsulates the GRE payload and fetches the original client request just like an ordinary Web Proxy would.
  4. WCCP Client receives a response from the external web server.
  5. WCCP Client (Squid Proxy Server) serves the web page back to the original User by spoofing the source IP address(This is key). Spoofing is done by rewriting the source IP address field of the packet with the External Resource’s IP address. This makes it look like the packet the user receives is from the external web site.

Note: There are only two(2) content re-routing methods available in WCCPv2 to deliver the user’s original request to the cache-engine(Squid Proxy server). Layer 2 rewrite which rewrites the destination MAC address to push the frame to the cache-engine, or GRE encapsulation which encapsulates the original IP packet into a GRE tunnel which is routed to the cache-engine. The Layer 2 method is the fastest and requires less processing power, however the GRE method allows redirection between different subnets. The Cisco ASA only supports the GRE method, however other Cisco products, like the Cisco 6000 catalysis series or Cisco Content Engine support L2 rewrites for WCCPv2.

Squid Proxy Section(WCCP Client):

Our Squid Proxy server is acting as the WCCP Client, it is responsible for requesting registration to the WCCP Server(Cisco ASA) as a cache-engine and will be used to fetch web content on behalf of the user.

  1. Check Version

    First check your squid version by issuing a squid -v and look for a line –enable-wccpv2(here). If you have that you are good to go and can skip the next step(Step 2).

  2. Compile Squid 3.4+ with WCCP support.
    apt-get install libssl-dev build-essentials
    
    cd /tmp
    wget http://www.squid-cache.org/Versions/v3/3.4/squid-3.4.8.tar.gz
    tar xzvf squid-3.4.8.tar.gz 
    cd squid-3.4.8/
    
    ./configure --enable-gnuregex --enable-xmalloc-statistics --enable-async-io --enable-icmp --enable-delay-pools --enable-useragent-log --enable-kill-parent-hack --enable-htpc --enable-forw-via-db --enable-cache-digests --enable-dl-malloc --enable-time-hack --enable-err-language=English --prefix=/usr --sysconfdir=/etc/squid --with-default-user=proxy --with-logdir=/opt/squid_logs --enable-ssl --enable-ssl-crtd --with-openssl=/usr/include --enable-linux-netfilter --enable-wccpv2
    
    make
    make install
  3. Configuring Squid
    #WCCPv2 items
    http_port 3128 intercept                    #intercept = treat incoming connections as redirects
    wccp_version 4
    wccp2_router 172.16.0.129
    #wccp2_address 172.16.0.135 (only needed in WCCPv1)
    wccp2_forwarding_method gre                 #(1=gre,2=l2l)
    wccp2_return_method gre                     #(1=gre,2=l2l)
    wccp2_service standard 0 password=TEST123   # standard 0 = http, password={7 characters or less}
    

    NOTE: Here is only the WCCP section of Squid. You must allow the subnets and services to proxy. See my other article.

  4. Creating a virtual interface and setting up the GRE tunnel

    We need to create the GRE interface on our Squid Proxy server. This interface allows the Squid Proxy server running on Linux to form the other end of the GRE tunnel with the Cisco ASA. Only the phsyical interface is assigned an IP address. The GRE interface does not require one because once it reaches the eth0 interface it will be decapsulated and passed directly to our virtual GRE interface wccp0.

    modprobe ip_gre
    
    ip tunnel add wccp0 mode gre remote 172.16.0.129 local 172.16.0.135 dev eth0
    
    ip link set wccp0 up
    • modprobe — loads GRE module to be used by Linux
    • ip tunnel add — defines a new tunnel interface (wccp0) and what address to use local and remote to form it
    • ip link set wccp0 up — activates the virtual interface (ifconfig wccp0 up works as well)
  5. Local Forwarding

    We need to forward ingress port 80(http) traffic on interface wccp0 to the default Squid cache port(3128).

    iptables -A PREROUTING -i wccp0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 172.16.0.135:3128
    
    echo 1 > /proc/sys/net/ipv4/ip_forward
    

    NOTE: The first line creates the port forwarding from 80 to the Squid Proxy server port , and the second allows IP forwarding between interfaces in the kernel(wccp –> eth0). Remember packets inside the wccp0 interface are those already decapsulated.

Cisco ASA Part(WCCP Server):

In this section we will configure the WCCP Server running on a Cisco ASA 5505. The WCCP servers responsibility is to maintain a communication channel to the WCCP Client cache-engine(Squid Proxy Server). The WCCP Server sends the user’s original packet via a GRE tunnel to the cache-engine, effectively encapsulating the original packet. This ensures the original packet is not altered, and is re-routed to the WCCP Client cache-engine(Squid Proxy Server) for processing.

  1. ACL to identify WCCP cache-server (Squid Proxy server)
    access-list wccp-servers extended permit ip host 172.16.0.135 any
  2. ACL to identify user traffic to re-route to WCCP Client cache-engine(Squid Proxy Server)
    access-list wccp-traffic-http extended deny ip host 172.16.0.135 any 
    access-list wccp-traffic-http extended permit tcp 172.16.0.128 255.255.255.128 any eq www 
    

    NOTE: The first statement denies our caching server (Squid Proxy Server) from being included in the WCCP redirection ACL and prevents a looped request. The only reason I needed this statement was because my Squid Proxy Server and my users share the same subnet. If your caching server does not, just don’t add it to the wccp-traffic-http ACL.

  3. Ingress traffic will be processed first

    So we have to allow http and any other traffic you want the Cisco ASA to allow.

    access-list inside-acl extended permit tcp object inside-network any eq www
    access-group inside-acl in interface inside
  4. Configure the redirect-list(ACL with client subnets) and the group-list(WCCP caching engine or Squid Proxy)
    wccp web-cache redirect-list wccp-traffic-http group-list wccp-servers password TEST123
    

    Note: password is optional and has to be 7 characters or less and make sure it matches your cache-engine(Squid Proxy server)

Wireshark Captures

WCCP Registration between WCCP Client(172.16.0.135) and WCCP Server (172.16.0.129)

Client GET/ HTTP request redirected to Proxy Server via WCCP

Cache-missed, Proxy server fetches web page

Web Page response to Proxy server

Source IP address spoofed and packet sent back directly to originating client

Complete Flow

Optional: https(SSL) redirection

As I’ve stated in other Squid articles, https(SSL) redirection and proxying is a difficult beast to tackle.  Unlike unencrypted  http traffic it can’t be manipulated and put back together easily. https(SSL) prevents us from tampering with anything Layer 4 and above(see OSI model) without disruption. These disruptions can appear seamless to the user (SSL inspection with trusted CA), but it requires additional infrastructure in place and modification.  The difficult part about performing https(SSL) transparent proxying is we cannot touch anything inside the SSL encrypted tunnel. In there is usually were we can get to the actual content and cache it or filter it. Kinda the point of proxying with Squid. We cannot content filter either, even by domain name. The issue is we can’t see the original host header values stored in the http stream (Layer 7) because it’s encrypted. You may have seen this done with Enterprise Web filters like Barracuda or Palo Alto, however they are relying on reverse domain lookups(IP to DNS) to do their filtering, which is why there are so many false positives. But I digress…

Squid Proxy server — Create CA and additional SSL configs

I am doing everything in /opt/squid_* for the next steps. On our Squid Proxy server we will need to;

    1. Add a new iptables rule
      iptables -t nat -A PREROUTING -i wccp0 -p tcp --dport 443 -j DNAT --to-destination 172.16.0.135:3129
      
    2. Create a directory for the sslcrtd (SSL helper) program(default location is /usr/local/libexec/ssl_crtd) Mine was in /usr/libexec/ssl_crtd.
      mkdir /opt/squid_ssldb/
      cd /opt/squid_ssldb/
      /usr/libexec/ssl_crtd -c -s /opt/squid_ssldb/ssl_db -M 40MB
      chown -R proxy.proxy /opt/squid_ssldb
    3. Create a mock Certificate Authority
      mkdir /opt/squid_certs
      cd /opt/squid_certs/
      openssl req -new -newkey rsa:2048 -days 36500 -nodes -x509 -keyout proxyCA.pem -out proxyCA.pem
      chown -R proxy.proxy /opt/squid_certs/
      /pre>

 

  1. Add WCCP dyanmic service 70 to SquidProxy server The next steps do not perform inspection or decryption. The Squid proxy receives the original packet via the WCCP GRE tunnel and
    https_port 3129 intercept ssl-bump cert=/opt/squid_certs/proxyCA.pem 
    
    #ssl-bump stuff
    ssl_bump none all
    sslcrtd_program  /usr/libexec/ssl_crtd -s /opt/squid_ssldb/ssl_db -M 40MB
    sslcrtd_children 5
    
    #add this below you other wccp2_service statements
    wccp2_service dynamic 70 password=TEST456
    wccp2_service_info 70 protocol=tcp flags=src_ip_hash,src_port_alt_hash priority=240 ports=443
    • https_port 3129 intercept ssl-bump cert= — https_port tells Squid Proxy server to expect SSL type connections, 3129 is the port I picked, intercept tells Squid that the packets were redirected, ssl-bump is the SSL bypass and decryption subfuction, cert= is where our mock CA is
    • ssl_bump none all — this sets Squid Proxy to CONNECT(pass everything without inspection)
    • sslcrtd_program — This is the SSL helper program that helps Squid Proxy server with the mimicing of SSL Certficates from the actual Web servers your users are trying to connect to. Remember Squid doens’t have them it’s just a proxy, so it has to grab them first and generate a mimic certficate to your users so everything matches up.
    • sslcrtd_children — How many sslcrtd child process we will allow Squid to open. I chose 5, anything higher than that was to much for my Virtual Machine.
    • wccp_service dynamic 70 — Declare a new dynamic WCCP service. (See list of types here).
    • wccp_service_info — Dyanmic services require you to build out each WCCP parameter manually and register is with the WCCP Client(Squid Proxy Server)
    • Type = Standard or Dynamic Service
    • Id = Service idenfier (in our case 70)
    • Priority = A single interface may contain several Service Groups. Proritize which ones first from 0 -254
    • Protocol = TCP/UDP or some other IP protocol number (TCP = IP protocol 6)
    • Options = Reserved for future use
    • Hash = Used for distribution in WCCP cluster mode. Some value to use from the original packet hash checking (SrcIP,DstIP,SrcPort,DstPort)
      See here …
    • Alt Hash = If the regular Hash can’t be used because of collisions, use these fields form the original packet in order.
    • Ports = What OSI Layer 4 port(s) to bind to this dynamic service

Cisco ASA — WCCP https service

  1. Add https dynamic WCCP service to Cisco ASA
    access-list wccp-traffic-https extended deny ip host 172.16.0.135 any
    access-list wccp-traffic-https extended permit tcp 172.16.0.128 255.255.255.128 any eq https
  2. Start the WCCP dynamic service 70
    wccp 70 redirect-list wccp-traffic-https group-list wccp-servers password TEST456
    wccp interface guest 70 redirect in

    NOTE: We have to create new ACL to identify the new https traffic. We can’t bundle them together because then it will be bundled into the web-cache (standard 0) WCCP service.

  3. Verify with show wccp 70

Troubleshooting:

  • If squid is receiving traffic verified in logs, but it is slow at servicing pages issue a net.ipv4.ip_forward = 1.This allows IP forwarding from wccp0 to eth0 at kernel level
  • cisco# show wccp web-cache view

    NOTE: If you don’t see anything in the WCCP Routers Informed Of: Your Cisco device is not announcing or accepting registration of WCCP Cache Engines. If you do not see anything listed under WCCP Cache Engines Visible, means your Cisco device has not receieved any registration reqwuests from your Squid server.

  • Check Squid has formed a GRE tunnel and the proper modules are loaded
    lsmod | grep gre
    ip_gre                 22164  0 
    gre                    12531  1 ip_gre
    
    AND
    ip tunnel show
    wccp0: gre/ip  remote 172.16.0.129  local 172.16.0.135  dev eth0  ttl inherit
  • Client’s being blocked before being redirected. Interface ACL are processed first. Make sure you allow www out from your ingress interface ACL where your clients are coming from. If you are afraid to allow entire subnets outside, create a NAT rule only for your proxy server. This will prevent clients from being able to bypass the proxy.
  • tailf is your friend. tailf /var/log/squid/access.log or wherever your Squid logs are. You should see the user’s IP address here and the GET requests to resources.
  • My SSL redirection isn’t working. Users browsers are complaining that the certificate is wrong or unaccepted. Anweser, you cannot do SSL inspection or decryption without manipulating your user’s trusted CA chains. Impossible. This is the whole point of SSL

Sources: