Setting up a transparent proxy for internal network
Overview
This document explains how to set up a web proxy on the internal network so that it can act as a configured proxy as well as transparent network proxy, including both http and https traffic. Exceptions for sites (destinations) as well as clients can be configured.
Architecture
A dd-wrt router is the heart of the example network, at 192.168.1.2. Proxy server proxy.ipa.example.com at 192.168.1.82 provides both transparent proxy and configured proxy behavior.
Configuring router for transparent proxy
The router is set up with dd-wrt firmware: DD-WRT v3.0-r43055 big (05/05/20)
and contains a firewall start script (nvram get rc_firewall
) which forces
all World Wide Web traffic (tcp ports 80 and 443) to a transparent proxy.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
|
The MARK rule performs a logical OR to set just a few binary flags, so it does
not merely "set" all the flags. See Weblink 7. The web server steps are
there to ensure that incoming web traffic get to the web server. Observe that
CHROMECAST_IP
is granted ACCEPT in the firewall. The Chromecast device is
given a reserved IP address in DHCP which is described later. An attempt was
made to perform logging on the router level, and while this provides IP
addresses, it was not sufficient for the needs of this project. See weblink
12.
Configuring the proxy server
First, configure the firewall. Set contents of file
/etc/firewalld/direct.xml
.
<?xml version="1.0" encoding="utf-8"?>
<direct>
<rule ipv="ipv4" table="nat" chain="PREROUTING" priority="0">-i eth0 -p tcp --dport 80 -j REDIRECT --to-ports 3130</rule>
<rule ipv="ipv4" table="nat" chain="PREROUTING" priority="0">-i eth0 -p tcp --dport 443 -j REDIRECT --to-ports 3129</rule>
</direct>
I was unable to find any other mechanism within firewalld that works for getting the traffic transparently to squid (i.e., that keeps the client IP address). See weblink 7. Also allow a few services and additional ports.
firewall-cmd --permanent --add-service=http --add-service=https --add-service=squid --add-port=3129/tcp
firewall-cmd --permanent --add-port=3130/tcp --add-port=3129/tcp
firewall-cmd --reload
Configuring squid
Configure squid itself. Fill file /etc/squid/squid.conf
with contents.
# Research for a log filter includes:
# tail -f /var/log/squid/access.log | grep -iE '200 [0-9]+ GET https?:\/\/[^ ]+'
acl localnet src 10.0.0.0/8 # RFC1918 possible internal network
acl localnet src 172.16.0.0/12 # RFC1918 possible internal network
acl localnet src 192.168.0.0/16 # RFC1918 possible internal network
acl localnet src fc00::/7 # RFC 4193 local private network range
acl localnet src fe80::/10 # RFC 4291 link-local (directly plugged) machines
acl SSL_ports port 443
acl Safe_ports port 80 # http
acl Safe_ports port 21 # ftp
acl Safe_ports port 443 # https
acl Safe_ports port 70 # gopher
acl Safe_ports port 210 # wais
acl Safe_ports port 1025-65535 # unregistered ports
acl Safe_ports port 280 # http-mgmt
acl Safe_ports port 488 # gss-http
acl Safe_ports port 591 # filemaker
acl Safe_ports port 777 # multiling http
acl CONNECT method CONNECT
http_access deny !Safe_ports
http_access deny CONNECT !SSL_ports
http_access allow localhost manager
http_access deny manager
http_access allow localnet
http_access allow localhost
http_access deny all
http_port 3128 ssl-bump \
cert=/etc/pki/tls/certs/proxy.ipa.example.com.pem \
key=/etc/pki/tls/private/proxy.ipa.example.com-nopw.key \
cafile=/etc/pki/tls/certs/ca-ipa.example.com.crt \
generate-host-certificates=on dynamic_cert_mem_cache_size=4MB
https_port 3129 intercept ssl-bump \
cert=/etc/pki/tls/certs/proxy.ipa.example.com.pem \
key=/etc/pki/tls/private/proxy.ipa.example.com-nopw.key \
cafile=/etc/pki/tls/certs/ca-ipa.example.com.crt \
generate-host-certificates=on dynamic_cert_mem_cache_size=4MB
http_port 3130 intercept ssl-bump \
cert=/etc/pki/tls/certs/proxy.ipa.example.com.pem \
key=/etc/pki/tls/private/proxy.ipa.example.com-nopw.key \
generate-host-certificates=on dynamic_cert_mem_cache_size=4MB
sslcrtd_program /usr/lib64/squid/ssl_crtd -s /var/lib/ssl_db -M 4MB
sslproxy_cert_error allow all
sslproxy_flags DONT_VERIFY_PEER
acl step1 at_step SslBump1
acl SAFE_sites ssl::server_name .telephony.goog .discord.gg
acl DIRECT_sites_name dstdomain .youtube.com
# DIRECT_sites_ip is primarily for youtube; not from nslookup; only from examining squid logs
acl DIRECT_sites_ip dst 172.217.164.74 64.233.177.106 173.194.219.95 64.233.177.99 31.13.65.1 31.13.65.36 74.125.138.95 64.233.185.139 64.233.185.91 172.217.164.78
acl DIRECT_sites any-of DIRECT_sites_name DIRECT_sites_ip
acl DIRECT_site_clients srcdomain tab1.ipa.example.com
acl WORK_clients srcdomain device1.ipa.example.com
always_direct allow DIRECT_sites DIRECT_site_clients
ssl_bump splice DIRECT_sites DIRECT_site_clients
ssl_bump splice SAFE_sites
ssl_bump splice WORK_clients
ssl_bump peek step1
ssl_bump bump all # needed for youtube somehow
coredump_dir /var/spool/squid
refresh_pattern ^ftp: 1440 20% 10080
refresh_pattern ^gopher: 1440 0% 1440
refresh_pattern -i (/cgi-bin/|\?) 0 0% 0
refresh_pattern . 0 20% 4320
strip_query_terms off #This will allow checking which youtube URLs were visited by user
visible_hostname proxy.ipa.example.com
logformat squid %ts.%03tu %>a %>A %03>Hs %rm %>ru %[un %<a %mt
The order of these entries matters. Additionally, the Chromecast materials may be out of date, but Youtube it still important. An important consideration is to keep the work computer's vpn uninterrupted. Several comments in this file demonstrate which lines are important to that end. The certificate used here is described in a few steps. The cafile used is the root CA cert for the entire FreeIPA infrastructure in the example network. Without this configuration, it is possible that clients who trust the root CA would still not trust the web traffic because squid would have an incomplete cert chain.
Initializing squid
The dynamic ssl certificate database needs to be initialized outside of squid itself. This only needs to be run once.
/usr/lib64/squid/ssl_crtd -c -s /var/lib/ssl_db
chown -R squid /var/lib/ssl_db
restorecon -Rv /var/lib/ssl_db
Without this step, squid could fail to start, or it could fail with an error about crashing too rapidly after so long. See weblink 3.
Getting a valid ssl certificate for squid
See post Getting a valid subCA certificate for squid from FreeIPA
Operations
It is probable that in the future I will want to make changes. A few possible changes are described below.
Disabling transparent proxy at router
If the proxy server is offline, then all outbound www traffic will fail. The best way to disable the transparent proxy setting entirely is to disable the ip rule on the router. Ssh in to the router or visit the web portal. Run command:
ip rule del fwmark 0x3
To re-enable, run the one ip rule command from the rc_firewall startup script.
ip rule add fwmark 3 table 2
Adding a new exclusion for a client on router
To allow a single client unmonitored access to the www, you can add a new rule to the router. This can be achieved by running a single command, or by updating the rc_firewall script.
iptables -t mangle -I PREROUTING 1 -p tcp -m multiport --dports 80,443 -s 192.168.1.300 -j ACCEPT
Where the IP address here is the target client. To remove a specific rule, run
iptables -t mangle -D PREROUTING 1
But ensure that the rule it will remove is not the main one that allows outbound www traffic from the proxy server.
Adding new sites and clients in squid
To exclude the ssl decryption of a site in squid, add it to the SAFE_sites entry in squid.conf and restart squid. You can confirm the syntax is valid without affecting the running daemon by running the following command.
squid -k parse ; echo $?
To exclude a combination of site and client, you can add a site or client to their respesctive lists uner attributes
- DIRECT_sites_name
- DIRECT_sites_ip
- DIRECT_site_clients
Using the proxy by choice
If for some reason you want to manually configure a proxy, you can set the exact following values.
export http_proxy=http://proxy:3128
export https_proxy=http://proxy:3128
It is worth noting that squid has to act differently when being used as a "transparent proxy" so those ports are 3129 (https) and 3130 (http). But port 3128 can be used explicitly for both protocols. Manually choosing to use the proxy can make troubleshooting easier. For example, mobile devices' applications rarely use the host proxy settings, but it can be easier to whitelist requests.
Assign a reserved IP address in dhcp
The internal network uses ISC dhcpd for assigning IP addresses to clients. To add a host to have a specific reservation, you have to edit the dhcpd.conf through the local mechanism dhcpd-control on host dns1.
sudo dhcpd-control --edit
This will open a cached copy of the dhcpd.conf.combined
which will get
replicated to host dns2 if any changes are made. The changes must be made
between headings:
-
- BEGIN POOLS FOR SYNC
- END POOLS FOR SYNC
Add an entry using the MAC address of the client and the desired reserved IP address.
host Obi200 { hardware ethernet 9c:7e:fe:60:64:f3; fixed-address 192.168.1.27; }
Improvements
Need to discover how to get android to think it has Internet access.
References
Man pages
/usr/share/doc/squid-3.5.20/squid.conf.documented
Weblinks
- http://silverskysoft.com/open-stack-xwrpr/2015/09/creating-a-subordinate-certificate-authority-in-freeipa/
- https://serverfault.com/questions/624879/ssl-crtd-helpers-are-crashing-too-rapidly-in-squid
- https://netfilter.org/documentation/HOWTO//packet-filtering-HOWTO.txt General guide for iptables
-
https://www.agix.com.au/minimal-transparent-squid-proxy-with-ssl-interception-bumping-on-centos-7/ useful examples about
ssl_bump
- https://wiki.squid-cache.org/Features/SslPeekAndSplice
- https://wiki.dd-wrt.com/wiki/index.php/Squid_Transparent_Proxy "Alternative Solution" to Proxy Server on the LAN Subnet
- https://forum.dd-wrt.com/phpBB2/viewtopic.php?p=1217511#1217511 I opened a thread on dd-wrt forum for help, but it turned out to be squid-side firewall problems.
- https://docs.mitmproxy.org/stable/howto-transparent/ minor examples of ip rules
- http://www.silverhawk.net/2016/07/centos-7-squid-and-firewall.html Ultimately unused examples for firewalld and squid acls
-
https://elatov.github.io/2019/01/using-squid-to-proxy-ssl-sites/ Great initial reference for establishing squid
ssl_bump
- https://nlug.ml1.co.uk/2014/01/the-missing-firewall-logs-of-dd-wrt/4528 A modest attempt to log traffic on the router, without regard to www hosts and requests.
Comments