xref: /openbmc/linux/Documentation/networking/tproxy.rst (revision 4b4193256c8d3bc3a5397b5cd9494c2ad386317d)
1*4ac0b122SMauro Carvalho Chehab.. SPDX-License-Identifier: GPL-2.0
2*4ac0b122SMauro Carvalho Chehab
3*4ac0b122SMauro Carvalho Chehab=========================
4*4ac0b122SMauro Carvalho ChehabTransparent proxy support
5*4ac0b122SMauro Carvalho Chehab=========================
6*4ac0b122SMauro Carvalho Chehab
7*4ac0b122SMauro Carvalho ChehabThis feature adds Linux 2.2-like transparent proxy support to current kernels.
8*4ac0b122SMauro Carvalho ChehabTo use it, enable the socket match and the TPROXY target in your kernel config.
9*4ac0b122SMauro Carvalho ChehabYou will need policy routing too, so be sure to enable that as well.
10*4ac0b122SMauro Carvalho Chehab
11*4ac0b122SMauro Carvalho ChehabFrom Linux 4.18 transparent proxy support is also available in nf_tables.
12*4ac0b122SMauro Carvalho Chehab
13*4ac0b122SMauro Carvalho Chehab1. Making non-local sockets work
14*4ac0b122SMauro Carvalho Chehab================================
15*4ac0b122SMauro Carvalho Chehab
16*4ac0b122SMauro Carvalho ChehabThe idea is that you identify packets with destination address matching a local
17*4ac0b122SMauro Carvalho Chehabsocket on your box, set the packet mark to a certain value::
18*4ac0b122SMauro Carvalho Chehab
19*4ac0b122SMauro Carvalho Chehab    # iptables -t mangle -N DIVERT
20*4ac0b122SMauro Carvalho Chehab    # iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
21*4ac0b122SMauro Carvalho Chehab    # iptables -t mangle -A DIVERT -j MARK --set-mark 1
22*4ac0b122SMauro Carvalho Chehab    # iptables -t mangle -A DIVERT -j ACCEPT
23*4ac0b122SMauro Carvalho Chehab
24*4ac0b122SMauro Carvalho ChehabAlternatively you can do this in nft with the following commands::
25*4ac0b122SMauro Carvalho Chehab
26*4ac0b122SMauro Carvalho Chehab    # nft add table filter
27*4ac0b122SMauro Carvalho Chehab    # nft add chain filter divert "{ type filter hook prerouting priority -150; }"
28*4ac0b122SMauro Carvalho Chehab    # nft add rule filter divert meta l4proto tcp socket transparent 1 meta mark set 1 accept
29*4ac0b122SMauro Carvalho Chehab
30*4ac0b122SMauro Carvalho ChehabAnd then match on that value using policy routing to have those packets
31*4ac0b122SMauro Carvalho Chehabdelivered locally::
32*4ac0b122SMauro Carvalho Chehab
33*4ac0b122SMauro Carvalho Chehab    # ip rule add fwmark 1 lookup 100
34*4ac0b122SMauro Carvalho Chehab    # ip route add local 0.0.0.0/0 dev lo table 100
35*4ac0b122SMauro Carvalho Chehab
36*4ac0b122SMauro Carvalho ChehabBecause of certain restrictions in the IPv4 routing output code you'll have to
37*4ac0b122SMauro Carvalho Chehabmodify your application to allow it to send datagrams _from_ non-local IP
38*4ac0b122SMauro Carvalho Chehabaddresses. All you have to do is enable the (SOL_IP, IP_TRANSPARENT) socket
39*4ac0b122SMauro Carvalho Chehaboption before calling bind::
40*4ac0b122SMauro Carvalho Chehab
41*4ac0b122SMauro Carvalho Chehab    fd = socket(AF_INET, SOCK_STREAM, 0);
42*4ac0b122SMauro Carvalho Chehab    /* - 8< -*/
43*4ac0b122SMauro Carvalho Chehab    int value = 1;
44*4ac0b122SMauro Carvalho Chehab    setsockopt(fd, SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
45*4ac0b122SMauro Carvalho Chehab    /* - 8< -*/
46*4ac0b122SMauro Carvalho Chehab    name.sin_family = AF_INET;
47*4ac0b122SMauro Carvalho Chehab    name.sin_port = htons(0xCAFE);
48*4ac0b122SMauro Carvalho Chehab    name.sin_addr.s_addr = htonl(0xDEADBEEF);
49*4ac0b122SMauro Carvalho Chehab    bind(fd, &name, sizeof(name));
50*4ac0b122SMauro Carvalho Chehab
51*4ac0b122SMauro Carvalho ChehabA trivial patch for netcat is available here:
52*4ac0b122SMauro Carvalho Chehabhttp://people.netfilter.org/hidden/tproxy/netcat-ip_transparent-support.patch
53*4ac0b122SMauro Carvalho Chehab
54*4ac0b122SMauro Carvalho Chehab
55*4ac0b122SMauro Carvalho Chehab2. Redirecting traffic
56*4ac0b122SMauro Carvalho Chehab======================
57*4ac0b122SMauro Carvalho Chehab
58*4ac0b122SMauro Carvalho ChehabTransparent proxying often involves "intercepting" traffic on a router. This is
59*4ac0b122SMauro Carvalho Chehabusually done with the iptables REDIRECT target; however, there are serious
60*4ac0b122SMauro Carvalho Chehablimitations of that method. One of the major issues is that it actually
61*4ac0b122SMauro Carvalho Chehabmodifies the packets to change the destination address -- which might not be
62*4ac0b122SMauro Carvalho Chehabacceptable in certain situations. (Think of proxying UDP for example: you won't
63*4ac0b122SMauro Carvalho Chehabbe able to find out the original destination address. Even in case of TCP
64*4ac0b122SMauro Carvalho Chehabgetting the original destination address is racy.)
65*4ac0b122SMauro Carvalho Chehab
66*4ac0b122SMauro Carvalho ChehabThe 'TPROXY' target provides similar functionality without relying on NAT. Simply
67*4ac0b122SMauro Carvalho Chehabadd rules like this to the iptables ruleset above::
68*4ac0b122SMauro Carvalho Chehab
69*4ac0b122SMauro Carvalho Chehab    # iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY \
70*4ac0b122SMauro Carvalho Chehab      --tproxy-mark 0x1/0x1 --on-port 50080
71*4ac0b122SMauro Carvalho Chehab
72*4ac0b122SMauro Carvalho ChehabOr the following rule to nft:
73*4ac0b122SMauro Carvalho Chehab
74*4ac0b122SMauro Carvalho Chehab# nft add rule filter divert tcp dport 80 tproxy to :50080 meta mark set 1 accept
75*4ac0b122SMauro Carvalho Chehab
76*4ac0b122SMauro Carvalho ChehabNote that for this to work you'll have to modify the proxy to enable (SOL_IP,
77*4ac0b122SMauro Carvalho ChehabIP_TRANSPARENT) for the listening socket.
78*4ac0b122SMauro Carvalho Chehab
79*4ac0b122SMauro Carvalho ChehabAs an example implementation, tcprdr is available here:
80*4ac0b122SMauro Carvalho Chehabhttps://git.breakpoint.cc/cgit/fw/tcprdr.git/
81*4ac0b122SMauro Carvalho ChehabThis tool is written by Florian Westphal and it was used for testing during the
82*4ac0b122SMauro Carvalho Chehabnf_tables implementation.
83*4ac0b122SMauro Carvalho Chehab
84*4ac0b122SMauro Carvalho Chehab3. Iptables and nf_tables extensions
85*4ac0b122SMauro Carvalho Chehab====================================
86*4ac0b122SMauro Carvalho Chehab
87*4ac0b122SMauro Carvalho ChehabTo use tproxy you'll need to have the following modules compiled for iptables:
88*4ac0b122SMauro Carvalho Chehab
89*4ac0b122SMauro Carvalho Chehab - NETFILTER_XT_MATCH_SOCKET
90*4ac0b122SMauro Carvalho Chehab - NETFILTER_XT_TARGET_TPROXY
91*4ac0b122SMauro Carvalho Chehab
92*4ac0b122SMauro Carvalho ChehabOr the floowing modules for nf_tables:
93*4ac0b122SMauro Carvalho Chehab
94*4ac0b122SMauro Carvalho Chehab - NFT_SOCKET
95*4ac0b122SMauro Carvalho Chehab - NFT_TPROXY
96*4ac0b122SMauro Carvalho Chehab
97*4ac0b122SMauro Carvalho Chehab4. Application support
98*4ac0b122SMauro Carvalho Chehab======================
99*4ac0b122SMauro Carvalho Chehab
100*4ac0b122SMauro Carvalho Chehab4.1. Squid
101*4ac0b122SMauro Carvalho Chehab----------
102*4ac0b122SMauro Carvalho Chehab
103*4ac0b122SMauro Carvalho ChehabSquid 3.HEAD has support built-in. To use it, pass
104*4ac0b122SMauro Carvalho Chehab'--enable-linux-netfilter' to configure and set the 'tproxy' option on
105*4ac0b122SMauro Carvalho Chehabthe HTTP listener you redirect traffic to with the TPROXY iptables
106*4ac0b122SMauro Carvalho Chehabtarget.
107*4ac0b122SMauro Carvalho Chehab
108*4ac0b122SMauro Carvalho ChehabFor more information please consult the following page on the Squid
109*4ac0b122SMauro Carvalho Chehabwiki: http://wiki.squid-cache.org/Features/Tproxy4
110