Tip

Check out the Repository on GitHub

Warning

WARNING: This Project is still in early development

Warning

Development & writing of this documentation is still in progress!

Redirect Traffic

Basics

You may want/need to redirect traffic to the proxy’s listeners for some use-case.

This is essential for using the transparent mode.

For modes like proxyproto, http, https or socks5 this is not necessary. (but it’s also possible using the Redirector)

You will have to choose between using DNAT and TPROXY to redirect the traffic on firewall-level.

TProxy has the benefit that it won’t modify the packets destination. This makes processing the traffic easier and can be benefitial in regards to performance.

But it also has the drawback that traffic that originates from the proxy-server (netfilter hook - output) will have to be looped-back.

I personally like to use TProxy for filtering input/forward- and DNAT for output-traffic.

Warning

The config-examples below may not be complete! If you find issues with them - please open an issue

NFTables

Read more about NFTables here: wiki.superstes.eu - NFTables

DNAT

define PROXY_PORT=4128
define PROXY_UID=13  # user-id of the proxy-user; anti-loop
define PROXY_PORTS={ 80, 443, 587, 25, 53, 853, 123 }

table inet default {
    chain prerouting_dnat {
        type nat hook prerouting priority dstnat; policy accept;

        # redirect traffic from outside
        meta l4proto tcp redirect to $PROXY_PORT
        # redirect to = equivalent to 'dnat to 127.0.0.1/::1'
    }

    chain output_dnat {
        type nat hook output priority -100; policy accept;

        # redirect traffic from this host
        meta l4proto tcp meta skuid != $PROXY_UID redirect to $PROXY_PORT
    }

    chain input {
        type filter hook output priority 0; policy drop;

        # allow traffic to proxy
        meta l4proto tcp dport $PROXY_PORT ip daddr 127.0.0.1 accept comment "Allow Network to proxy"
        meta l4proto tcp dport $PROXY_PORT ip6 daddr ::1 accept comment "Allow Network to proxy"
    }

    chain output {
        type filter hook output priority 0; policy drop;

        # allow traffic to proxy
        meta l4proto tcp dport $PROXY_PORT ip daddr 127.0.0.1 accept comment "Allow localhost to proxy"
        meta l4proto tcp dport $PROXY_PORT ip6 daddr ::1 accept comment "Allow localhost to proxy"

        # optional logging
        meta l4proto tcp dport $PROXY_PORTS meta skuid $PROXY_UID ct state new log prefix "NFTables Proxy outgoing "
        # allow traffic from proxy
        meta l4proto tcp dport $PROXY_PORTS meta skuid $PROXY_UID accept comment "Allow proxy traffic"
    }
}

TProxy

Full TProxy example: gist.github.com/superstes - TProxy NFTables

You might need to enable some nftables kernel modules: Kernel docs - NFTables extensions

IPTables

DNAT

PROXY_PORT=4128
PROXY_UID=13  # user-id of the proxy-user; anti-loop

# redirect traffic from outside
iptables -t nat -A PREROUTING -p tcp -j REDIRECT --to-destination --to-port "$PROXY_PORT"
# redirect traffic from localhost
iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner "$PROXY_UID" -j REDIRECT --to-port "$PROXY_PORT"

# allow traffic to proxy
#   iptable -A INPUT -p tcp -d 127.0.0.1 --dport "$PROXY_PORT" -j ACCEPT
#   iptable -A OUTPUT -p tcp -d 127.0.0.1 --dport "$PROXY_PORT" -j ACCEPT

# optional logging
iptables -A OUTPUT -p tcp -m conntrack --ctstate NEW -j LOG –log-prefix "IPTables Proxy outgoing "
# allow traffic from proxy
iptable -A OUTPUT -p tcp -m owner ! --uid-owner "$PROXY_UID" -j ACCEPT

TProxy

Full TProxy example: gist.github.com/superstes - TProxy IPTables

You might need to enable some iptables kernel modules: Kernel docs - IPTables extensions

TProxy

To run Calamary as TPROXY target - you will have to set CAP_NET_RAW:

bind to any address for transparent proxying

You can add it like this:

setcap cap_net_raw=+ep /usr/bin/calamary

# make sure only wanted users can execute the binary!
chown root:proxy /usr/bin/calamary
chmod 750 /usr/bin/calamary

Read more about TPROXY here:

Output loopback

You will have to configure a loopback route if you want to proxy ‘output’ traffic:

echo "200 proxy_loopback" > /etc/iproute2/rt_tables.d/proxy.conf

# These need to be configured persistent: (maybe use an interface up-hook)
ip rule add fwmark 200 table proxy_loopback
ip -6 rule add fwmark 200 table proxy_loopback
ip route add local 0.0.0.0/0 dev lo table proxy_loopback
ip -6 route add local ::/0 dev lo table proxy_loopback

# can be checked using:
ip rule list
ip -6 rule list
ip -d route show table all

# you might need to set a sysctl:
sysctl -w net.ipv4.conf.all.route_localnet=1

# you might want to block 127.0.0.1 on non loopback interfaces if you enable it:
iptables -t raw -A PREROUTING ! -i lo -d 127.0.0.0/8 -j DROP
iptables -t mangle -A POSTROUTING ! -o lo -s 127.0.0.0/8 -j DROP