0001 .. SPDX-License-Identifier: GPL-2.0
0002
0003 =========================
0004 Transparent proxy support
0005 =========================
0006
0007 This feature adds Linux 2.2-like transparent proxy support to current kernels.
0008 To use it, enable the socket match and the TPROXY target in your kernel config.
0009 You will need policy routing too, so be sure to enable that as well.
0010
0011 From Linux 4.18 transparent proxy support is also available in nf_tables.
0012
0013 1. Making non-local sockets work
0014 ================================
0015
0016 The idea is that you identify packets with destination address matching a local
0017 socket on your box, set the packet mark to a certain value::
0018
0019 # iptables -t mangle -N DIVERT
0020 # iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
0021 # iptables -t mangle -A DIVERT -j MARK --set-mark 1
0022 # iptables -t mangle -A DIVERT -j ACCEPT
0023
0024 Alternatively you can do this in nft with the following commands::
0025
0026 # nft add table filter
0027 # nft add chain filter divert "{ type filter hook prerouting priority -150; }"
0028 # nft add rule filter divert meta l4proto tcp socket transparent 1 meta mark set 1 accept
0029
0030 And then match on that value using policy routing to have those packets
0031 delivered locally::
0032
0033 # ip rule add fwmark 1 lookup 100
0034 # ip route add local 0.0.0.0/0 dev lo table 100
0035
0036 Because of certain restrictions in the IPv4 routing output code you'll have to
0037 modify your application to allow it to send datagrams _from_ non-local IP
0038 addresses. All you have to do is enable the (SOL_IP, IP_TRANSPARENT) socket
0039 option before calling bind::
0040
0041 fd = socket(AF_INET, SOCK_STREAM, 0);
0042 /* - 8< -*/
0043 int value = 1;
0044 setsockopt(fd, SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
0045 /* - 8< -*/
0046 name.sin_family = AF_INET;
0047 name.sin_port = htons(0xCAFE);
0048 name.sin_addr.s_addr = htonl(0xDEADBEEF);
0049 bind(fd, &name, sizeof(name));
0050
0051 A trivial patch for netcat is available here:
0052 http://people.netfilter.org/hidden/tproxy/netcat-ip_transparent-support.patch
0053
0054
0055 2. Redirecting traffic
0056 ======================
0057
0058 Transparent proxying often involves "intercepting" traffic on a router. This is
0059 usually done with the iptables REDIRECT target; however, there are serious
0060 limitations of that method. One of the major issues is that it actually
0061 modifies the packets to change the destination address -- which might not be
0062 acceptable in certain situations. (Think of proxying UDP for example: you won't
0063 be able to find out the original destination address. Even in case of TCP
0064 getting the original destination address is racy.)
0065
0066 The 'TPROXY' target provides similar functionality without relying on NAT. Simply
0067 add rules like this to the iptables ruleset above::
0068
0069 # iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY \
0070 --tproxy-mark 0x1/0x1 --on-port 50080
0071
0072 Or the following rule to nft:
0073
0074 # nft add rule filter divert tcp dport 80 tproxy to :50080 meta mark set 1 accept
0075
0076 Note that for this to work you'll have to modify the proxy to enable (SOL_IP,
0077 IP_TRANSPARENT) for the listening socket.
0078
0079 As an example implementation, tcprdr is available here:
0080 https://git.breakpoint.cc/cgit/fw/tcprdr.git/
0081 This tool is written by Florian Westphal and it was used for testing during the
0082 nf_tables implementation.
0083
0084 3. Iptables and nf_tables extensions
0085 ====================================
0086
0087 To use tproxy you'll need to have the following modules compiled for iptables:
0088
0089 - NETFILTER_XT_MATCH_SOCKET
0090 - NETFILTER_XT_TARGET_TPROXY
0091
0092 Or the floowing modules for nf_tables:
0093
0094 - NFT_SOCKET
0095 - NFT_TPROXY
0096
0097 4. Application support
0098 ======================
0099
0100 4.1. Squid
0101 ----------
0102
0103 Squid 3.HEAD has support built-in. To use it, pass
0104 '--enable-linux-netfilter' to configure and set the 'tproxy' option on
0105 the HTTP listener you redirect traffic to with the TPROXY iptables
0106 target.
0107
0108 For more information please consult the following page on the Squid
0109 wiki: http://wiki.squid-cache.org/Features/Tproxy4