OpenVPN: redirect all HTTP traffic from clients to Squid

linux-networkingnetworkingopenvpnroutingsquid

I'm trying to setup Squid as transparent proxy inside my OpenVPN network:

 __________               ________________                    _____________
| Client   |             | OpenVPN server |                  | Squid Proxy |
| 10.8.0.3 |-------------|    10.8.0.1    |------------------|  10.8.0.2   |
|__________|             |________________|                  |_____________|

Basically what I want to achieve is all HTTP traffic from client to go through Squid proxy; I follow official guide (https://wiki.squid-cache.org/ConfigExamples/Intercept/IptablesPolicyRoute) which recommends to mark all 80-port traffic and then redirect it to proxy:

# mark everything on port 80 to be routed to the Squid box
iptables -t mangle -A PREROUTING -i tun0 -p tcp --dport 80 -j MARK --set-mark 2
iptables -t mangle -A PREROUTING -m mark --mark 2 -j ACCEPT
ip rule add fwmark 2 table proxy
ip route add default via 10.8.0.2 table proxy

So I did and ip route get 8.8.8.8 mark 2 returns

8.8.8.8 via 10.8.0.2 dev tun0 table proxy src 10.8.0.1 mark 2 uid 1000

I checked iptables and I can see that 80-port requests are marked. But no traffic comes to 10.8.0.2 – it's like my routing is ignored (tcpdump port 80 -i tun0 is empty at 10.8.0.2).

Is there different solution to route HTTP traffic inside the OpenVPN network?

Best Answer

First of all, gateway doesn't actually do anything for a tun route. To make a client become the gateway of a (sub)network, you need to have iroute(s) in its CCD (client-config-dir) file. The filename should be its Common Name (CN).

Say you have client-config-dir /etc/openvpn/ccd/ in the openvpn server conf, and the CN of the proxy server is squid, have:

iroute 0.0.0.0 0.0.0.0

in /etc/openvpn/ccd/squid.

(Note: you probably need to avoid pushing redirect-gateway or route 0.0.0.0 0.0.0.0 with the server conf as you don't want a default route via the its own tun on the proxy server. You should be able to workaround that by having the directive in /etc/openvpn/ccd/DEFAULT instead, if you can't / don't want to have it in the client conf. But you do need to have the default route added on the other clients so that the iroute matters.)

Since you only want certain traffics to use the proxy server as "gateway", make sure you don't have client-to-client in the openvpn server conf, otherwise the tun on the clients will route traffics to the proxy server directly (as in, they will not leave the tunnel when they reach the openvpn server so that you can selectively forward them on IP level, but being internally forwarded by openvpn).

As you are doing forwarding on IP level, make sure IP forwarding is enabled with sysctl, and allowed in your firewall (e.g. iptables). The latter should be default if you (or whatever you use) haven't instructed it otherwise.

Then on the server:

ip route add default dev tun0 table proxy

You probably don't even need fwmark (and the corresponding iptables rules) for your use case, but instead:

ip rule add iif tun0 ipproto tcp dport 80 table proxy

(Note: AFAICR iroute 0.0.0.0 0.0.0.0 wouldn't avoid the any client from being reached via the tun of the server. That's why the above route and rule should allow replies from the proxy server to reach the clients as well.)

EDIT: If you want tcp 80 traffics of the openvpn server itself to go to the proxy server as well, this should do:

ip rule add iif lo ippproto tcp dport 80 table proxy