HowTo: Privoxy SOCKS Forwarding By Client Header Filter

www/privoxy is a non-caching web proxy with filtering, conditional forwarding & privacy enhancing capabilities. It is a good idea to use Privoxy as a gateway to SOCKS. The traffic flow should look like:

Browser -> caching_proxy -> privoxy {user-agent TAG filtering} -> a) Internet OR b) SOCKS proxy

Edit the /usr/local/etc/privoxy/user.action file as below:
# Tag every request with the User-Agent header. Client-header taggers are
# first to be executed and can be used to control every other action.

# Tagging doesn't change action, sections with TAG patterns do
# Use different forwarding based on user-agent
{+forward-override{forward-socks5 192.168.0.XXX:9050 .} \
+client-header-filter{hide-tor-exit-notation} }
TAG:^User-Agent: Some user agent string etc

# Spoof accept-language and user agent for normal & socks use
{+hide-accept-language{en-ca} \
+hide-user-agent{Mozilla/5.0 (X11; Linux i686; rv:10.0) Gecko/20100101 Firefox/10.0) KHTML (like Gecko)}  }

From what I have learned, browser-based on the fly proxy changers should NOT be used with SOCKS due to potential data leak. There are instead two options:
a) Use a user-agent switcher/changer add-on, if all requests go through Privoxy and you are sure the switcher does its job correctly.
b) Use an entirely separate browser dedicated to SOCKS use only and encode the header of this browser to the TAG filter.

The privoxy TAG filter will forward traffic to SOCKS or not, based on what user-agent string it receives from the browser.
Let's also go over Jails while we're at it. All of the above services should be placed in jails, with additional security precautions. Posting some pointers for easier jail management as well. The example is for Privoxy.

* Create the base dataset for jails with dedup on. This is one of the few instances that dedup serves a purpose.
# zfs create zpool/path/jails -o dedup=on

* Create the ZFS dataset for the jail.
# zfs create zpool/path/jails/prvx

* Create the actual jail using ezjail/qjail (ezjail example). path is
folder where ZFS is to mount the dataset.
# ezjail-admin create -f default -r /path/jails/prvx prvx

* Create a folder /etc/jail and edit /etc/jail.conf as below. Not covering topics of vlan creation, Firewall Natting or /etc/devfs.rules settings here.
  securelevel = 3;
  allow.set_hostname = 0;
  exec.start = "/bin/sh /etc/rc";
  exec.stop = "/bin/sh /etc/rc.shutdown"

prvx {  path = /path/jails/prvx;
   interface = vlan1;
    ip4.addr =;
   host.hostname =;
   devfs_ruleset = 11;
   mount.fstab = /etc/jail/fstab.prvx;

* Move the fstab file created by ezjail (fstab.prvx should already exist from the ezjail-admin command above) to /etc/jail/ - this is so you have all jail fstab files in one place. The jail fstab file will null mount/unmount specified folders on jail start/stop. Edit fstab.prvx as:
/path/jails/basejail    /path/jails/prvx/basejail   nullfs ro 0 0
/usr/local             /path/jails/prvx/usr/local  nullfs ro 0 0
With this trick, you don't have to install and maintain packages in a bunch of jails. Install packages only on host, then mount as read-only to the jail's usr/local without compromising security.

* By placing the config in /etc/jail, you can now use the base jail commands to administer jails rather than ezjail-admin commands. You only use azjail-admin for jail creation and updating jail world.

* One last important step is to take a clean ZFS snapshot of the jail. Snapshot is why we placed each jail on its own dataset.
# zfs snapshot zpool/path/jails/prvx@clean
You can now periodically rollback the snapshot for a completely clean jail environment. ezjail-admin update does not do any mergemaster stuff, so one would have to a) rollback snapshot 2) run mergemaster / etcupdate 3) destroy snapshot & re-snapshot, all while the jail is stopped of course.

All that's left to do is configure autostart services with:
# echo "privoxy_enable='YES'" >> /path/jails/prvx/etc/rc.conf
# echo "jail_enable='YES'" >> /etc/rc.conf
# echo "jail_list='dns prvx'" >> /etc/rc.conf
If you prefer to manually start/stop jails, # jail -c prvx / # jail -r prvx