Installing a Transparent Squid Proxy Directly onto a DD-WRT Netgear R7000p Router

This guide will show you how to setup a transparent Squid proxy with HTTPS support directly on DD-WRT. Let’s dive right in!

NOTE: Links will open in a new tab\window.

Prerequisites

The only requirements are that you have a SSH connection and a working Optware installation. Visit the DD-WRT Optware1 page for additional information on installing Optware. In short, you need to mount /opt and run the bootstrap command. (Bootstrap may only be available in Kong builds.) How you mount /opt does not matter as long as the user nobody has read and write access. I won’t go into too much detail but, I have used a CIFS mount for mine:

/sbin/insmod /lib/modules/`uname -r`/kernel/crypto/md4.ko
/sbin/insmod /lib/modules/`uname -r`/kernel/crypto/md5.ko
/sbin/insmod /lib/modules/`uname -r`/kernel/crypto/des_generic.ko
/sbin/insmod /lib/modules/`uname -r`/kernel/fs/fscache/fscache.ko
/sbin/insmod /lib/modules/`uname -r`/kernel/fs/cifs/cifs.ko
/bin/mount.cifs //192.168.x.x/ddwrt /opt -o uid=nobody,username=user,password=pass

NOTE: fscache.ko must be loaded before cifs.ko.

Getting Started

Once you have an SSH connection and Optware is properly functioning, install Squid. You may also want to install nano if you prefer nano over vi like I do:

opkg install squid
opkg install nano

Create Missing Directories

Now that we have Squid installed, we need to create a few directories before Squid will run. The default installation is a bit broken and needs the following directories to be created:

mkdir /dev/shm
chown nobody /dev/shm
mkdir /opt/var/run/
mkdir /opt/etc/squid/ssl
mkdir /opt/etc/squid/ssl/cacerts

IMPORTANT: As previously mentioned, make sure the user nobody has read and write access to all directories in /opt. If you are mounting via CIFS, ensure you use uid=nobody in your mount options. This will save you a lot of headaches.

My device does not create the /dev/shm/ directory so I create it and change the owner to nobody. You should check your device to see if the directory exists before doing this.

Certificates, Certificates and more Certificates

Now that we have our directories created, we need to initialize the certificate cache:

/opt/lib/squid/ssl_crtd -c -s /opt/etc/squid/ssl/ssl_db/

Next you will need to generate a self-signed root certificate and copy the certificate and key to /opt/etc/squid/ssl/. There are plenty of guides on how to generate your own certificate so, I will not be going into detail on this. However, if you need a place to start, you may visit the Squid Dynamic SSL Certificate Generation2 page where you can find a few clues as to the correct commands to use. Just be sure to have the certificate and key separated or change the Squid configuration file to point to a combined certificate and key file.

Squid doesn’t come with any Global Root Certificates by default so you’ll need to copy our own into /opt/etc/squid/ssl/cacerts/. There are several ways you can obtain Root Certificates. The easiest method is to copy them from /etc/ssl/certs/ on a Debian based system. You may also download them from Curl’s CA Extract4 page.

Once you have your Root Certificate generated, create a DER certificate and import it into your web browser. Visit the Squid Dynamic SSL Certificate Generation2 page for additional information on creating the DER certificate.

Modern Ciphers

It’s a good idea to generate a DH/EDH cipher and copy it to /opt/etc/squid/ssl/. This will help to harden your Squid connections. If you have a version of Squid less than 3.5.27, you may need to use a different directive in the Squid configuration file. Visit the link above to obtain the relevant directive.

Visit the Squid Modern DH/EDH Ciphers3 page for additional information.

If you don’t want to use a modern cipher then you can skip this section but, be sure to change the Squid configuration file accordingly.

Squid Configuration File

Add the following configuration directives to the end of /opt/etc/squid/squid.conf:

# If you have 64 MB device RAM you can use 16 MB cache_mem, default is 8 MB
cache_mem 8 MB
maximum_object_size_in_memory 100 KB
maximum_object_size 32 MB

# Leave coredumps in the first cache dir
coredump_dir /opt/var/cache/squid

# Set the cache directory location and size
cache_dir aufs /opt/var/cache/squid 500 16 256

# Listen on port 3130 for https
https_port 3130 intercept ssl-bump generate-host-certificates=on dynamic_cert_mem_cache_size=4MB cert=/opt/etc/squid/ssl/cert.pem key=/opt/etc/squid/ssl/key.pem tls-dh=prime256v1:/opt/etc/squid/ssl/tls-dh.pem

# Listen on port 3129 for http
http_port 3129 intercept

# Squid normally listens to port 3128 for direct browser connections
# Squid refuses to run if port 3128 is missing - giving a "no forwarding proxy configured" error
http_port 3128

# Visit https://wiki.squid-cache.org/ConfigExamples/Intercept/SslBumpExplicit#Troubleshooting for additional information on the following version differences
# For Squid 3.5.x only
sslcrtd_program /opt/lib/squid/ssl_crtd -s /opt/etc/squid/ssl/ssl_db -M 4MB
sslcrtd_children 5

# For Squid 4 and newer
#tls_outgoing_options options=NO_SSLv3,SINGLE_DH_USE,SINGLE_ECDH_USE

sslproxy_options NO_SSLv2,NO_SSLv3,SINGLE_ECDH_USE
sslproxy_cipher EECDH+ECDSA+AESGCM:EECDH+aRSA+AESGCM:EECDH+ECDSA+SHA384:EECDH+ECDSA+SHA256:EECDH+aRSA+SHA384:EECDH+aRSA+SHA256:EECDH+aRSA+RC4:EECDH:EDH+aRSA:!RC4:!aNULL:!eNULL:!LOW:!3DES:!MD5:!EXP:!PSK:!SRP:!DSS
sslproxy_capath /opt/etc/squid/ssl/cacerts

# Replace this section with your own ssl_bump and acl rules
# Visit https://wiki.squid-cache.org/Features/SslPeekAndSplice for additional information
# NOTE: You should splice banking websites
acl step1 at_step SslBump1
acl excludeServerFromProxy ssl::server_name .example.org
ssl_bump peek step1
ssl_bump splice excludeServerFromProxy
ssl_bump stare all

The important parts here are the cache size, ports, rules and file paths. Ensure they are what you expect them to be before continuing. As there are so many possible configuration directives, I will not be going into further detail about the configuration directives and what they do. Visit the Squid Configuration Directives Documentation5 page for additional information.

Cache Building

Next, build the cache that Squid will use:

squid -z

You should receive similar output to the following:

2019/01/05 15:43:09 kid1| Set Current Directory to /opt/var/cache/squid
2019/01/05 15:43:09 kid1| Creating missing swap directories
2019/01/05 15:43:09 kid1| /opt/var/cache/squid exists
2019/01/05 15:43:09 kid1| Making directories in /opt/var/cache/squid/00
2019/01/05 15:43:09 kid1| Making directories in /opt/var/cache/squid/01
2019/01/05 15:43:10 kid1| Making directories in /opt/var/cache/squid/02
2019/01/05 15:43:10 kid1| Making directories in /opt/var/cache/squid/03
2019/01/05 15:43:10 kid1| Making directories in /opt/var/cache/squid/04
2019/01/05 15:43:11 kid1| Making directories in /opt/var/cache/squid/05
2019/01/05 15:43:11 kid1| Making directories in /opt/var/cache/squid/06
2019/01/05 15:43:11 kid1| Making directories in /opt/var/cache/squid/07
2019/01/05 15:43:12 kid1| Making directories in /opt/var/cache/squid/08
2019/01/05 15:43:12 kid1| Making directories in /opt/var/cache/squid/09
2019/01/05 15:43:12 kid1| Making directories in /opt/var/cache/squid/0A
2019/01/05 15:43:13 kid1| Making directories in /opt/var/cache/squid/0B
2019/01/05 15:43:13 kid1| Making directories in /opt/var/cache/squid/0C
2019/01/05 15:43:13 kid1| Making directories in /opt/var/cache/squid/0D
2019/01/05 15:43:14 kid1| Making directories in /opt/var/cache/squid/0E
2019/01/05 15:43:14 kid1| Making directories in /opt/var/cache/squid/0F

If you do not get the above output, ensure that file permissions are correct and that /opt/var/cache/squid/ exists. REMEMBER: The user nobody must have read and write access.

The Virgin Voyage

Now it is finally time to try to start Squid. Let’s start Squid in a special debugging mode so that we can see what is happening in case something goes wrong.

squid -d 1

You should receive output similar to the following:

2019/01/05 15:44:30 kid1| Set Current Directory to /opt/var/cache/squid
2019/01/05 15:44:30 kid1| Starting Squid Cache version 3.5.27 for arm-openwrt-linux-gnu...
2019/01/05 15:44:30 kid1| Service Name: squid
2019/01/05 15:44:30 kid1| Process ID 23227
2019/01/05 15:44:30 kid1| Process Roles: worker
2019/01/05 15:44:30 kid1| With 1024 file descriptors available
2019/01/05 15:44:30 kid1| Initializing IP Cache...
2019/01/05 15:44:30 kid1| DNS Socket created at 0.0.0.0, FD 6
2019/01/05 15:44:30 kid1| Adding nameserver 192.168.x.x from /etc/resolv.conf
2019/01/05 15:44:30 kid1| helperOpenServers: Starting 5/5 'ssl_crtd' processes
2019/01/05 15:44:30 kid1| Local cache digest enabled; rebuild/rewrite every 3600/3600 sec
2019/01/05 15:44:30 kid1| Logfile: opening log stdio:/dev/null
2019/01/05 15:44:30 kid1| Swap maxSize 51200000 + 262144 KB, estimated 3958626 objects
2019/01/05 15:44:30 kid1| Target number of buckets: 197931
2019/01/05 15:44:30 kid1| Using 262144 Store buckets
2019/01/05 15:44:30 kid1| Max Mem size: 262144 KB
2019/01/05 15:44:30 kid1| Max Swap size: 51200000 KB
2019/01/05 15:44:30 kid1| Rebuilding storage in /opt/var/cache/squid (no log)
2019/01/05 15:44:30 kid1| Using Least Load store dir selection
2019/01/05 15:44:30 kid1| Set Current Directory to /opt/var/cache/squid
2019/01/05 15:44:30 kid1| Finished loading MIME types and icons.
2019/01/05 15:44:30 kid1| HTCP Disabled.
2019/01/05 15:44:30 kid1| Pinger socket opened on FD 25
2019/01/05 15:44:30 kid1| Squid plugin modules loaded: 0
2019/01/05 15:44:30 kid1| Adaptation support is off.
2019/01/05 15:44:30 kid1| Accepting NAT intercepted HTTP Socket connections at local=0.0.0.0:3129 remote=[::] FD 21 flags=41
2019/01/05 15:44:30 kid1| Accepting HTTP Socket connections at local=0.0.0.0:3128 remote=[::] FD 22 flags=9
2019/01/05 15:44:30 kid1| Accepting NAT intercepted SSL bumped HTTPS Socket connections at local=0.0.0.0:3130 remote=[::] FD 23 flags=41
2019/01/05 15:44:34 kid1| Done scanning /opt/var/cache/squid dir (0 entries)
2019/01/05 15:44:34 kid1| Finished rebuilding storage from disk.
2019/01/05 15:44:34 kid1| 0 Entries scanned
2019/01/05 15:44:34 kid1| 0 Invalid entries.
2019/01/05 15:44:34 kid1| 0 With invalid flags.
2019/01/05 15:44:34 kid1| 0 Objects loaded.
2019/01/05 15:44:34 kid1| 0 Objects expired.
2019/01/05 15:44:34 kid1| 0 Objects cancelled.
2019/01/05 15:44:34 kid1| 0 Duplicate URLs purged.
2019/01/05 15:44:34 kid1| 0 Swapfile clashes avoided.
2019/01/05 15:44:34 kid1| Took 4.61 seconds ( 0.00 objects/sec).
2019/01/05 15:44:34 kid1| Beginning Validation Procedure
2019/01/05 15:44:34 kid1| Completed Validation Procedure
2019/01/05 15:44:34 kid1| Validated 0 Entries
2019/01/05 15:44:34 kid1| store_swap_size = 0.00 KB
2019/01/05 15:44:35 kid1| storeLateRelease: released 0 objects

Issue the following command to check if Squid has successfully started:

ps | grep -i squid

This will give you output similar to:

23225 root 11236 S squid -d 1
23227 nobody 16680 S {squid} (squid-1) -d 1
23229 nobody 3452 S {ssl_crtd} (ssl_crtd) -s /opt/etc/squid/ssl/ssl_db -M 4MB
23230 nobody 3364 S {ssl_crtd} (ssl_crtd) -s /opt/etc/squid/ssl/ssl_db -M 4MB
23231 nobody 3364 S {ssl_crtd} (ssl_crtd) -s /opt/etc/squid/ssl/ssl_db -M 4MB
23232 nobody 3364 S {ssl_crtd} (ssl_crtd) -s /opt/etc/squid/ssl/ssl_db -M 4MB
23233 nobody 3364 S {ssl_crtd} (ssl_crtd) -s /opt/etc/squid/ssl/ssl_db -M 4MB
23277 root 1196 S grep squid

If you do not get any output other than the grep line, then something is wrong with Squid. You should check the output from the previous squid -d 1 command for clues as to what went wrong.

iptables (Yay!)

NOTE: If you don’t want to setup Squid to be a transparent proxy, then skip this step and configure your web browser’s proxy settings to send traffic to port 3128. (You still need to open the port with the first iptables line from below.) You may also want to remove the relevant http_port/https_port lines from your configuration file for the other ports. Be aware that you’ll lose the HTTPS proxy function as browsers do not yet have good support for direct communication to an HTTPS proxy. Hence why you should only be using one port with this type of configuration.

Now that we have Squid up and running, we can redirect our traffic to the correct port so that Squid can receive it. Be sure your configured ports match the redirection rule’s ports. If you forward non-https traffic to Squid’s https port, it will be refused. Also, make sure that you are using the correct interface — in this case br0.

Issue the following commands to add the redirect rules using iptables:

iptables -I INPUT -p tcp --dport 3128 -j ACCEPT
iptables -t nat -A PREROUTING -i br0 -p tcp --dport 80 -j REDIRECT --to-port 3129
iptables -I INPUT -p tcp --dport 3129 -j ACCEPT
iptables -t nat -A PREROUTING -i br0 -p tcp --dport 443 -j REDIRECT --to-port 3130
iptables -I INPUT -p tcp --dport 3130 -j ACCEPT

Lift off!

You made it! Congratulations, you should now be able to happily browse the Internet at decent first-page-load speeds and blazing fast subsequent-page-load speeds. If you are unable to pleasantly browse the worldwide inter-webs, scroll to the Notes and Comments section at the end of this article for some useful hints.

Making it Permanent

At this point, you should have a fully functioning Squid installation. The only problem is, it is temporary. When you restart your router, Squid will not be started automatically and special directories will once again be missing.

To fix this, add the following to your startup script by opening your router’s DD-WRT configuration page (usually at http://192.168.0.1) and navigating to the Administration Tab -> Commands Tab.

Input the following into the Command Shell field:

/bin/mkdir /dev/shm
/bin/chown nobody /dev/shm
/opt/sbin/squid &

Click on Save Startup to save your changes.

NOTE: If you are using a CIFS mount, you should add the relevant commands from the top of this article to your startup script as well.

After you have saved the startup script, input the following into the Command Shell field to add the iptables commands to the firewall script:

iptables -I INPUT -p tcp --dport 3128 -j ACCEPT
iptables -t nat -A PREROUTING -i br0 -p tcp --dport 80 -j REDIRECT --to-port 3129
iptables -I INPUT -p tcp --dport 3129 -j ACCEPT
iptables -t nat -A PREROUTING -i br0 -p tcp --dport 443 -j REDIRECT --to-port 3130
iptables -I INPUT -p tcp --dport 3130 -j ACCEPT

Click on Save Firewall to save your changes.

Finish Line!

Now it is time reboot and marvel at your work. If all is good, you should be able to browse the Internet without problems but, we still need to verify the proxy is actually working.

To do this, visit https://example.com in your web browser. Open the properties for the certificate of the website and look for your Root Certificate’s information to be populated under the Issued by field. If your Root Certificate’s information is not present, then your traffic is not being proxied correctly.

You’ll also want to visit https://www.ssllabs.com/ssltest/viewMyClient.html6. This site can tell you a lot about your connection to the outside world when it comes to certificate support. Visit https://wiki.squid-cache.org/ConfigExamples/Intercept/SslBumpExplicit#Hardening7 for additional information on what to expect.

Fine Tuning

Some fine tuning needs to be done after you have a working installation. You’ll probably want to change the acl directives at the end of your Squid configuration file to be what you want.

Specifically, you need to change .example.org in the acl line to a banking website or a website that you do not want to be included in the proxy. You may add additional acl lines to exclude multiple sites.

You may also want to enable logging. To do this, edit the configuration file and remove the following lines:

access_log none
cache_log /dev/null
cache_store_log stdio:/dev/null
logfile_rotate 0
logfile_daemon /dev/null

Create the /opt/var/logs/ directory:

mkdir /opt/var/logs

Next, add a cronjob to rotate the logs by visiting your router’s DD-WRT configuration page (usually at http://192.168.0.1) and navigating to Administration Tab -> Management Tab.

Input the following into the Cron section:

0 0 * * * /usr/local/squid/bin/squid -k rotate

Click on Save to save your changes. Reboot the router or run squid -k reconfigure to make your changes immediate.

Notes and Comments

The following commands are very useful when troubleshooting:

squid -k reconfigure
squid -k shutdown
ps | grep -i squid
killall squid

The following are only useful if you have logging enabled:

tail -n 50 -f /opt/var/logs/access.log
tail -n 50 -f /opt/var/logs/cache.log

If your browser displays warnings about the certificate not being trusted, you need to install your Self-Signed Root Certificate into the browser.

Issue the following command to allow a device to bypass the proxy altogether (you must replace [IPADDRESS]):

iptables -t nat -I PREROUTING -i br0 -s [IPADDRESS] -j ACCEPT

Delete an iptables entry by first viewing the list:

iptables -t nat --list --line-numbers

Then issue the following (you must replace # with the number of the rule you want to delete):

iptables -t nat -D PREROUTING #

Some errors Squid spits out are a little vague. If you receive a segmentation fault of any kind, it is most likely due to missing directories or incorrect permissions. Here is a list of errors I have ran across while installing Squid and the solutions to each:

FATAL: Failed to verify one of the swap directories, Check cache.log
for details. Run 'squid -z' to create swap directories
if needed, or if running Squid for the first time.

Check that the /var/cache/squid/ directory exists and that the user nobody has read and write access to it. Run squid -z if the directory is empty.

FATAL: Ipc::Mem::Segment::create failed to shm_open(/squid-cf__metadata.shm): (2) No such file or directory

Check that the /dev/shm/ directory exists and that the user nobody has read and write access to it.

FATAL: Unable to open HTTPS Socket

For any errors similar to this one, check that Squid is not already running and that no other process is using any of Squid’s ports (3128, 3129, 3130).

pinger: Initialising ICMP pinger ...
icmp_sock: (1) Operation not permitted
pinger: Unable to start ICMP pinger.
icmp_sock: (97) Address family not supported by protocol
pinger: Unable to start ICMPv6 pinger.
FATAL: pinger: Unable to open any ICMP sockets.

These error messages regard the ping utility. They can be safely ignored.

FATAL: Received Segment Violation...dying.

I’m not sure what this was about. It happened once when I issued the squid -k restart command. Regardless, the restart never works so, I just don’t use it. I use squid -k shutdown instead and bring Squid back up with squid after about 30 seconds. (Squid waits 30 seconds before shutting down during a clean shutdown.)

BUG: Unexpected state while connecting to a cache_peer or origin server

I’m not sure of the cause of this error either. I received it when posting to the DD-WRT forums along with messages about the queue being overloaded and to increase the number of ssl_crtd processes in the configuration file. I did so to no avail and the Squid process finally died one of the times I attempted to issue the squid -k reconfigure command. For now, I deleted and rebuilt the ssl_db directory, then rebooted. The error seems to be gone.

Thanks for reading!

Links in this Article
https://wiki.dd-wrt.com/wiki/index.php/Optware1
https://wiki.squid-cache.org/Features/DynamicSslCert2
https://wiki.squid-cache.org/ConfigExamples/Intercept/SslBumpExplicit#Modern_DH.2FEDH_ciphers_usage3
https://curl.haxx.se/docs/caextract.html4
http://www.squid-cache.org/Doc/config/5
https://www.ssllabs.com/ssltest/viewMyClient.html6
https://wiki.squid-cache.org/ConfigExamples/Intercept/SslBumpExplicit#Hardening7

Links of Interest
https://wiki.squid-cache.org/ConfigExamples/Intercept/SslBumpExplicit#Hardening
https://wiki.dd-wrt.com/wiki/index.php/Squid_Transparent_Proxy
https://forum.dd-wrt.com/phpBB2/viewtopic.php?t=80678&postdays=0&postorder=asc&start=30&sid=f60feaf2c1f415edc4e5a1e9382e45a3

Comments are closed.