megrxu

Transparent Proxy and DoT Setup

Oct 25, 2020  「DevOps」  

Summary:

The Proxy Slice

Run the proxy server in a specific systemd slice, such that the packets from the proxy won’t go loop.

A classic clash service file can be like following. Choose ${SLICE_NAME} as you like (such as clash.slice).

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
# /etc/systemd/system/clash.service
[Unit]
Description=Clash Daemon
After=zjunet.service

[Service]
Slice=${SLICE_NAME}
ExecStart=/usr/bin/clash -d /etc/clash/

[Install]
WantedBy=multi-user.target

iptables and Transparent Proxy

Edit the iptables.rules properly. Remember to replce the ${ENV_VARIABLES}.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
# /etc/iptables/iptables.rules
*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
:TP-TCP - [0:0]

# Redirect all output through TP-TCP
-A OUTPUT -p tcp -j TP-TCP

# Don't loop!
-A TP-TCP -m cgroup --path "${SLICE_NAME}" -j RETURN

# Whitelist LANs and some other reserved addresses.
# https://en.wikipedia.org/wiki/Reserved_IP_addresses#Reserved_IPv4_addresses
-A TP-TCP -d 0.0.0.0/8 -j RETURN
-A TP-TCP -d 127.0.0.0/8 -j RETURN
-A TP-TCP -d 10.0.0.0/8 -j RETURN
-A TP-TCP -d 169.254.0.0/16 -j RETURN
-A TP-TCP -d 172.16.0.0/12 -j RETURN
-A TP-TCP -d 192.168.0.0/16 -j RETURN
-A TP-TCP -d 224.0.0.0/4 -j RETURN
-A TP-TCP -d 240.0.0.0/4 -j RETURN

# Redirect everything else to the transparent proxy port
-A TP-TCP -p tcp -j REDIRECT --to-ports ${PORT}

COMMIT

Enable and start our iptables.service. Now we are able to TCP transparently just in shell.

Try telnet google.com 443, we will fail because we have to fix the DNS issue.

DNS

Of course we can just use a NORMAL DNS (not poisoned one). Better, we can also use DoT or DoH.

Stubby

Use stubby for example.

Edit the stubby config file.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
# Listen on other ports
listen_addresses:
  - 127.0.0.1@53000
  - 0::1@53000
upstream_recursive_servers:
# The Surfnet/Sinodun servers
 - address_data: 145.100.185.15
    tls_auth_name: "dnsovertls.sinodun.com"
    tls_pubkey_pinset:
      - digest: "sha256"
        value: 62lKu9HsDVbyiPenApnc4sfmSYTHOVfFgL3pyB+cBL4=
# The Cloudflare server
- address_data: 1.1.1.1
    tls_port: 853
    tls_auth_name: "cloudflare-dns.com"

Ensure that these servers can be connected without the proxy.

Then edit the stubby service file to put it into the proxy slice, such that it will not use the proxy.

1
2
3
# /etc/systemd/system/stubby.service.d/override.conf
[Service]
Slice=${SLICE_NAME}

dnsmasq

stubby does not provide DNS cache, so we have to setup a local DNS cache for a better experience. We use dnsmasq here.

Edit the config file.

1
2
3
4
5
no-resolv
proxy-dnssec
server=::1#53000
server=127.0.0.1#53000
listen-address=::1,127.0.0.1

Resolver Configuration

Config your local resolver properly to query at 127.0.0.1:53.

Done. Now you can try curl -L google.com.

Refs