#!/usr/bin/env bash
set -e
# Let's explain this.
#
# 1. We use a dedicated table (happen to be 123 here) inside which we treat all
# IPs (including those who are generally treated as public / private IPs such
# as 1.2.3.4) as loopback IP, by routing them all to the loopback device.
#
# 2. Then we routing all packets with a specific mark (happen to be 12345 here)
# to that table.
#
# 3. Finally we use xt_TPROXY to mark the some of the packets (selected by iptables'
# `-m set` condition) with the mark we use above (12345) so that they'll be
# routed as rule above.
#
# 4. We also specified a IP/port as xt_TPROXY's parameters so that the process
# listening on that IP/port will receive the packets and proxy them as desired.
# The environment variables goes first.
export PATH=/usr/local/bin:/opt/bin:/opt/sbin:$PATH
# Send all packets with mark 12345 to routing table #123.
ip rule add fwmark 12345 table 123
ip -6 rule add fwmark 12345 table 123
# Routing table #123 routes all packets to loopback device.
ip route add local default dev lo table 123
ip -6 route add local default dev lo table 123
# For packets with `dst` matching `proxied_v4`, mark them with 12345,
# and let process listening on 127.0.0.1:8765 to receive it.
iptables -t mangle -A PREROUTING -p tcp -m set --match-set proxied_v4 dst -j TPROXY --on-port 8765 --on-ip 127.0.0.1 --tproxy-mark 12345
iptables -t mangle -A PREROUTING -p udp -m set --match-set proxied_v4 dst -j TPROXY --on-port 8765 --on-ip 127.0.0.1 --tproxy-mark 12345
# For packets with `dst` matching `proxied_v6`, mark them with 12345,
# and let process listening on [::1]:8765 to receive it.
ip6tables -t mangle -A PREROUTING -p tcp -m set --match-set proxied_v6 dst -j TPROXY --on-port 8765 --on-ip ::1 --tproxy-mark 12345
ip6tables -t mangle -A PREROUTING -p udp -m set --match-set proxied_v6 dst -j TPROXY --on-port 8765 --on-ip ::1 --tproxy-mark 12345