Table of Contents

About

The following tutorial uses Squid bumping to intercept SSL Second Life grid traffic in order to be able to better cache assets. In other words, this tutorial will show you how to use Squid to intercept and decrypt the traffic between your viewer and the SecondLife grid with the purpose of caching assets (textures and others).

Requirements

You will need Squid v3.5+ with SSL compiled in and with the following compile-time features enabled:

                --enable-ssl \
                --enable-ssl-crtd

If your distribution is Debian, then you can probably follow the tutorial on compiling your own Squid.

Configuring Squid for SSL Bumping

First, run the command:

/usr/lib/squid3/ssl_crtd -c -s /var/lib/ssl_db 

in order to create the certificate store.

On Debian, you will have to change the owner of the /var/lib/ssl_db to the proxy user that Squid runs under:

chown -R proxy:proxy /var/lib/ssl_db

The next part is to create the required certificate for SSL bumping by using OpenSSL:

openssl req -new -newkey rsa:2048 -sha256 -days 365 -nodes -x509 -extensions v3_ca -keyout myCA.pem  -out /etc/squid/certs/myCA.pem

Some root certificates can be installed on Debian using:

aptitude install ca-certificates 

to be used in the Squid configuration.

Finally, edit /etc/squid/squid.conf and amend the file with the following:

# Listening Port
http_port 8123 ssl-bump cert=/etc/squid/certs/myCA.pem generate-host-certificates=on dynamic_cert_mem_cache_size=4MB

# SSL Bump Config
acl bump_domains dstdom_regex -i "/etc/squid/bump_domains.conf"
acl DiscoverSNIHost at_step SslBump1
ssl_bump peek DiscoverSNIHost
ssl_bump bump bump_domains

### SSL Tweaks
# On Debian, from the package ca-certificates - not needed for Squid v4+
sslproxy_cafile /etc/ssl/certs/ca-certificates.crt
sslproxy_cert_error allow all
sslproxy_flags DONT_VERIFY_PEER
sslcrtd_program /usr/lib/squid3/ssl_crtd -s /var/lib/ssl_db -M 8MB
sslcrtd_children 5

# Do not forward bumped domains through cache peers.
always_direct allow bump_domains
never_direct allow !bump_domains

# Rewrite lindenlab assets.
acl rewritedoms dstdomain .agni.lindenlab.com
store_id_program /etc/squid/secondlife_store_rewrite.py
store_id_children 64 startup=10 idle=5 concurrency=0
store_id_access allow rewritedoms
store_id_access deny all

### SecondLife-specific configuration parameters.
# SecondLife Refresh patterns.
refresh_pattern -i /cap/					129600 100% 129600 ignore-no-cache ignore-no-store ignore-private override-expire override-lastmod reload-into-ims ignore-reload
refresh_pattern -i asset-cdn\.agni\.lindenlab\.com/.*		129600 100% 129600 ignore-no-cache ignore-no-store ignore-private override-expire override-lastmod reload-into-ims ignore-reload
refresh_pattern -i asset-cdn\.glb\.agni\.lindenlab\.com/.*	129600 100% 129600 ignore-no-cache ignore-no-store ignore-private override-expire override-lastmod reload-into-ims ignore-reload

# Access log
access_log /var/log/squid/access.log buffer-size=1MB
# Useful for debugging store re-writes: shows GET query terms.
strip_query_terms off

Now, all domains listed in /etc/squid/bump_domains.conf will be bumped so create the file /etc/squid/bump_domains.conf with the following contents:

(^|\.)lindenlab..+?$

Store Re-Write Script

The store re-write script will grab the UUID of the requested asset (either texture or mesh) and pass it to squid in a more palatable format. Using the configuration from the previous section, the script has to be placed at /etc/squid/secondlife_store_rewrite.py:

#!/usr/bin/python -u
# http://vex.fabulo.us/2015/12/return-of-the-squid-or-how-to-have-a-terabyte-texture-cache-using-squid-3/
import re
import sys
 
# http://sim34232.agni.lindenlab.com/cap/foo/?texture_id=klkjalkjsd
# http://asset-cdn.glb.agni.lindenlab.com/?texture_id=klklkjlkjs
# group 1 is the host - simNNNN or a CDN server
# group 2 is the port on the server
# group 3 cap
# group 4 is either 'texture' or 'mesh'
# group 5 the actual id
texturl_patt = re.compile('(.*)\.agni\.lindenlab\.com(.*)/(.*/?)\?(texture|mesh)_id=(.*)')
 
def rewrite(texturl):
    m = texturl_patt.search(texturl)
    if m is not None:
        r = 'http://{}.lindenlab.com/{}'.format(m.group(4),m.group(5))
        return r
    else:
        return None
 
def process(line):
    if line == 'quit':
        sys.exit(0)
 
    stuff = line.split()
    if stuff[0].isdigit():
        r = rewrite(stuff[1])
        if r is not None:
            print('{} OK store-id={}'.format(stuff[0], r))
        else:
            print('{} ERR'.format(stuff[0]))
    else:
        r=rewrite(stuff[0])
        if r is not None:
            print('OK store-id={}'.format(r))
        else:
            print('ERR')
 
while True:
    line = sys.stdin.readline().strip()
    if not line:
        break
    process(line)

and granted execute permissions: chmod +x /etc/squid/secondlife_store_rewrite.py.

You can now save all configurations and restart Squid.

Configuring the Viewer

To make the viewer use the Squid proxy, and assuming the configuration from the previous section, a few parameters have to be set.

If you save the settings now and attempt to connect, you will get and error telling you that the server certificate cannot be verified. This is because Squid is bumping the connection using the myCA.pem certificate. To resolve this issue, you can go to:

and type in: NoVerifySSLCert and set the toggle to True. The warning is fair, because intercepting the SSL session is exactly what you want to accomplish with Squid.

You should now be able to connect to SecondLife through Squid.

Optimizations

This section is viewer-specific but the general guideline is to enable:

such that all all requests for inventory or textures will flow through Squid.

Checking

You should now be able to monitor /var/log/squid/access.log to see all the requests that the viewer is making whilst minding for TCP_MISS (asset not cached) and TCP_HIT or TCP_MEM_HIT indicating that the asset was previously cached.

If the option strip_query_terms has been set to off, you should be able to see the GET request parameters which is useful for amending the secondlife_store_rewrite.py script.