14ac0b122SMauro Carvalho Chehab.. SPDX-License-Identifier: GPL-2.0
24ac0b122SMauro Carvalho Chehab
34ac0b122SMauro Carvalho Chehab=========================
44ac0b122SMauro Carvalho ChehabTransparent proxy support
54ac0b122SMauro Carvalho Chehab=========================
64ac0b122SMauro Carvalho Chehab
74ac0b122SMauro Carvalho ChehabThis feature adds Linux 2.2-like transparent proxy support to current kernels.
84ac0b122SMauro Carvalho ChehabTo use it, enable the socket match and the TPROXY target in your kernel config.
94ac0b122SMauro Carvalho ChehabYou will need policy routing too, so be sure to enable that as well.
104ac0b122SMauro Carvalho Chehab
114ac0b122SMauro Carvalho ChehabFrom Linux 4.18 transparent proxy support is also available in nf_tables.
124ac0b122SMauro Carvalho Chehab
134ac0b122SMauro Carvalho Chehab1. Making non-local sockets work
144ac0b122SMauro Carvalho Chehab================================
154ac0b122SMauro Carvalho Chehab
164ac0b122SMauro Carvalho ChehabThe idea is that you identify packets with destination address matching a local
174ac0b122SMauro Carvalho Chehabsocket on your box, set the packet mark to a certain value::
184ac0b122SMauro Carvalho Chehab
194ac0b122SMauro Carvalho Chehab    # iptables -t mangle -N DIVERT
204ac0b122SMauro Carvalho Chehab    # iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
214ac0b122SMauro Carvalho Chehab    # iptables -t mangle -A DIVERT -j MARK --set-mark 1
224ac0b122SMauro Carvalho Chehab    # iptables -t mangle -A DIVERT -j ACCEPT
234ac0b122SMauro Carvalho Chehab
244ac0b122SMauro Carvalho ChehabAlternatively you can do this in nft with the following commands::
254ac0b122SMauro Carvalho Chehab
264ac0b122SMauro Carvalho Chehab    # nft add table filter
274ac0b122SMauro Carvalho Chehab    # nft add chain filter divert "{ type filter hook prerouting priority -150; }"
284ac0b122SMauro Carvalho Chehab    # nft add rule filter divert meta l4proto tcp socket transparent 1 meta mark set 1 accept
294ac0b122SMauro Carvalho Chehab
304ac0b122SMauro Carvalho ChehabAnd then match on that value using policy routing to have those packets
314ac0b122SMauro Carvalho Chehabdelivered locally::
324ac0b122SMauro Carvalho Chehab
334ac0b122SMauro Carvalho Chehab    # ip rule add fwmark 1 lookup 100
344ac0b122SMauro Carvalho Chehab    # ip route add local 0.0.0.0/0 dev lo table 100
354ac0b122SMauro Carvalho Chehab
364ac0b122SMauro Carvalho ChehabBecause of certain restrictions in the IPv4 routing output code you'll have to
374ac0b122SMauro Carvalho Chehabmodify your application to allow it to send datagrams _from_ non-local IP
384ac0b122SMauro Carvalho Chehabaddresses. All you have to do is enable the (SOL_IP, IP_TRANSPARENT) socket
394ac0b122SMauro Carvalho Chehaboption before calling bind::
404ac0b122SMauro Carvalho Chehab
414ac0b122SMauro Carvalho Chehab    fd = socket(AF_INET, SOCK_STREAM, 0);
424ac0b122SMauro Carvalho Chehab    /* - 8< -*/
434ac0b122SMauro Carvalho Chehab    int value = 1;
444ac0b122SMauro Carvalho Chehab    setsockopt(fd, SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
454ac0b122SMauro Carvalho Chehab    /* - 8< -*/
464ac0b122SMauro Carvalho Chehab    name.sin_family = AF_INET;
474ac0b122SMauro Carvalho Chehab    name.sin_port = htons(0xCAFE);
484ac0b122SMauro Carvalho Chehab    name.sin_addr.s_addr = htonl(0xDEADBEEF);
494ac0b122SMauro Carvalho Chehab    bind(fd, &name, sizeof(name));
504ac0b122SMauro Carvalho Chehab
514ac0b122SMauro Carvalho ChehabA trivial patch for netcat is available here:
524ac0b122SMauro Carvalho Chehabhttp://people.netfilter.org/hidden/tproxy/netcat-ip_transparent-support.patch
534ac0b122SMauro Carvalho Chehab
544ac0b122SMauro Carvalho Chehab
554ac0b122SMauro Carvalho Chehab2. Redirecting traffic
564ac0b122SMauro Carvalho Chehab======================
574ac0b122SMauro Carvalho Chehab
584ac0b122SMauro Carvalho ChehabTransparent proxying often involves "intercepting" traffic on a router. This is
594ac0b122SMauro Carvalho Chehabusually done with the iptables REDIRECT target; however, there are serious
604ac0b122SMauro Carvalho Chehablimitations of that method. One of the major issues is that it actually
614ac0b122SMauro Carvalho Chehabmodifies the packets to change the destination address -- which might not be
624ac0b122SMauro Carvalho Chehabacceptable in certain situations. (Think of proxying UDP for example: you won't
634ac0b122SMauro Carvalho Chehabbe able to find out the original destination address. Even in case of TCP
644ac0b122SMauro Carvalho Chehabgetting the original destination address is racy.)
654ac0b122SMauro Carvalho Chehab
664ac0b122SMauro Carvalho ChehabThe 'TPROXY' target provides similar functionality without relying on NAT. Simply
674ac0b122SMauro Carvalho Chehabadd rules like this to the iptables ruleset above::
684ac0b122SMauro Carvalho Chehab
694ac0b122SMauro Carvalho Chehab    # iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY \
704ac0b122SMauro Carvalho Chehab      --tproxy-mark 0x1/0x1 --on-port 50080
714ac0b122SMauro Carvalho Chehab
724ac0b122SMauro Carvalho ChehabOr the following rule to nft:
734ac0b122SMauro Carvalho Chehab
744ac0b122SMauro Carvalho Chehab# nft add rule filter divert tcp dport 80 tproxy to :50080 meta mark set 1 accept
754ac0b122SMauro Carvalho Chehab
764ac0b122SMauro Carvalho ChehabNote that for this to work you'll have to modify the proxy to enable (SOL_IP,
774ac0b122SMauro Carvalho ChehabIP_TRANSPARENT) for the listening socket.
784ac0b122SMauro Carvalho Chehab
794ac0b122SMauro Carvalho ChehabAs an example implementation, tcprdr is available here:
804ac0b122SMauro Carvalho Chehabhttps://git.breakpoint.cc/cgit/fw/tcprdr.git/
814ac0b122SMauro Carvalho ChehabThis tool is written by Florian Westphal and it was used for testing during the
824ac0b122SMauro Carvalho Chehabnf_tables implementation.
834ac0b122SMauro Carvalho Chehab
844ac0b122SMauro Carvalho Chehab3. Iptables and nf_tables extensions
854ac0b122SMauro Carvalho Chehab====================================
864ac0b122SMauro Carvalho Chehab
874ac0b122SMauro Carvalho ChehabTo use tproxy you'll need to have the following modules compiled for iptables:
884ac0b122SMauro Carvalho Chehab
894ac0b122SMauro Carvalho Chehab - NETFILTER_XT_MATCH_SOCKET
904ac0b122SMauro Carvalho Chehab - NETFILTER_XT_TARGET_TPROXY
914ac0b122SMauro Carvalho Chehab
924ac0b122SMauro Carvalho ChehabOr the floowing modules for nf_tables:
934ac0b122SMauro Carvalho Chehab
944ac0b122SMauro Carvalho Chehab - NFT_SOCKET
954ac0b122SMauro Carvalho Chehab - NFT_TPROXY
964ac0b122SMauro Carvalho Chehab
974ac0b122SMauro Carvalho Chehab4. Application support
984ac0b122SMauro Carvalho Chehab======================
994ac0b122SMauro Carvalho Chehab
1004ac0b122SMauro Carvalho Chehab4.1. Squid
1014ac0b122SMauro Carvalho Chehab----------
1024ac0b122SMauro Carvalho Chehab
1034ac0b122SMauro Carvalho ChehabSquid 3.HEAD has support built-in. To use it, pass
1044ac0b122SMauro Carvalho Chehab'--enable-linux-netfilter' to configure and set the 'tproxy' option on
1054ac0b122SMauro Carvalho Chehabthe HTTP listener you redirect traffic to with the TPROXY iptables
1064ac0b122SMauro Carvalho Chehabtarget.
1074ac0b122SMauro Carvalho Chehab
1084ac0b122SMauro Carvalho ChehabFor more information please consult the following page on the Squid
1094ac0b122SMauro Carvalho Chehabwiki: http://wiki.squid-cache.org/Features/Tproxy4
110