Clarify tproxy odcumentation, so it's easier to read/understand without a-priori in-kernel transparent proxying knowledge: - re-shuffle the sections, as the "router" section is easier to understand when getting started. - add a link to HAProxy page. This is where I learned most about what tproxy is, so I believe it is reasonable to include. - removed a reference to linux 2.2. Plus Sphinx formatting/cosmetic changes. Signed-off-by: Motiejus Jakštys <desired.mta@xxxxxxxxx> --- Documentation/networking/tproxy.rst | 155 +++++++++++++++------------- 1 file changed, 83 insertions(+), 72 deletions(-) diff --git a/Documentation/networking/tproxy.rst b/Documentation/networking/tproxy.rst index 00dc3a1a66b4..0f43159046fb 100644 --- a/Documentation/networking/tproxy.rst +++ b/Documentation/networking/tproxy.rst @@ -1,42 +1,77 @@ .. SPDX-License-Identifier: GPL-2.0 -========================= -Transparent proxy support -========================= +========================== +Transparent proxy (TPROXY) +========================== -This feature adds Linux 2.2-like transparent proxy support to current kernels. -To use it, enable the socket match and the TPROXY target in your kernel config. -You will need policy routing too, so be sure to enable that as well. +TPROXY enables forwarding and intercepting packets that were destined +for other destination IPs, without using NAT chain or REDIRECT targets. -From Linux 4.18 transparent proxy support is also available in nf_tables. +Redirecting traffic +=================== -1. Making non-local sockets work -================================ +TPROXY is often used to "intercept" traffic on a router. This is usually done +with the iptables ``REDIRECT`` target, however, there are serious limitations: +it modifies the packets to change the destination address -- which might not be +acceptable in certain situations, e.g.: +- UDP: you won't be able to find out the original destination address. +- TCP: getting the original destination address is racy. -The idea is that you identify packets with destination address matching a local -socket on your box, set the packet mark to a certain value:: +The ``TPROXY`` target provides similar functionality without relying on NAT. +Simply add rules like this to the iptables ruleset above: - # iptables -t mangle -N DIVERT - # iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT - # iptables -t mangle -A DIVERT -j MARK --set-mark 1 - # iptables -t mangle -A DIVERT -j ACCEPT +.. code-block:: sh -Alternatively you can do this in nft with the following commands:: + iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY \ + --tproxy-mark 0x1/0x1 --on-port 50080 + +Or the following rule to nft: + +.. code-block:: sh + + nft add rule filter divert tcp dport 80 tproxy to :50080 meta mark set 1 accept + +Note that for this to work you'll have to modify the proxy to enable +(``SOL_IP``, ``IP_TRANSPARENT``) for the listening socket. + +As an example implementation, tcprdr is available here: +https://git.breakpoint.cc/cgit/fw/tcprdr.git/ +This tool is written by Florian Westphal and it was used for testing during the +nf_tables implementation. + +Intercepting non-local packets +============================== + +To identify packets with destination address matching a local socket on your +box, set the packet mark to a certain value: + +.. code-block:: sh + + iptables -t mangle -N DIVERT + iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT + iptables -t mangle -A DIVERT -j MARK --set-mark 1 + iptables -t mangle -A DIVERT -j ACCEPT + +Alternatively in nft: + +.. code-block:: sh + + nft add table filter + nft add chain filter divert "{ type filter hook prerouting priority -150; }" + nft add rule filter divert meta l4proto tcp socket transparent 1 meta mark set 1 accept - # nft add table filter - # nft add chain filter divert "{ type filter hook prerouting priority -150; }" - # nft add rule filter divert meta l4proto tcp socket transparent 1 meta mark set 1 accept +Then match on that value using policy routing to deliver those packets locally: -And then match on that value using policy routing to have those packets -delivered locally:: +.. code-block:: sh - # ip rule add fwmark 1 lookup 100 - # ip route add local 0.0.0.0/0 dev lo table 100 + ip rule add fwmark 1 lookup 100 + ip route add local 0.0.0.0/0 dev lo table 100 -Because of certain restrictions in the IPv4 routing output code you'll have to -modify your application to allow it to send datagrams _from_ non-local IP -addresses. All you have to do is enable the (SOL_IP, IP_TRANSPARENT) socket -option before calling bind:: +Because of certain restrictions in the IPv4 routing application will need to be +modified to allow it to send datagrams *from* non-local IP addresses. Enable +the ``SOL_IP``, ``IP_TRANSPARENT`` socket options before calling ``bind``: + +.. code-block:: c fd = socket(AF_INET, SOCK_STREAM, 0); /* - 8< -*/ @@ -51,59 +86,35 @@ option before calling bind:: A trivial patch for netcat is available here: http://people.netfilter.org/hidden/tproxy/netcat-ip_transparent-support.patch +Kernel configuration +==================== -2. Redirecting traffic -====================== - -Transparent proxying often involves "intercepting" traffic on a router. This is -usually done with the iptables REDIRECT target; however, there are serious -limitations of that method. One of the major issues is that it actually -modifies the packets to change the destination address -- which might not be -acceptable in certain situations. (Think of proxying UDP for example: you won't -be able to find out the original destination address. Even in case of TCP -getting the original destination address is racy.) - -The 'TPROXY' target provides similar functionality without relying on NAT. Simply -add rules like this to the iptables ruleset above:: - - # iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY \ - --tproxy-mark 0x1/0x1 --on-port 50080 - -Or the following rule to nft: - -# nft add rule filter divert tcp dport 80 tproxy to :50080 meta mark set 1 accept - -Note that for this to work you'll have to modify the proxy to enable (SOL_IP, -IP_TRANSPARENT) for the listening socket. +To use tproxy you'll need to have the following modules compiled for iptables: -As an example implementation, tcprdr is available here: -https://git.breakpoint.cc/cgit/fw/tcprdr.git/ -This tool is written by Florian Westphal and it was used for testing during the -nf_tables implementation. + - ``NETFILTER_XT_MATCH_SOCKET`` + - ``NETFILTER_XT_TARGET_TPROXY`` -3. Iptables and nf_tables extensions -==================================== +For nf_tables: -To use tproxy you'll need to have the following modules compiled for iptables: + - ``NFT_TPROXY`` + - ``NFT_SOCKET`` - - NETFILTER_XT_MATCH_SOCKET - - NETFILTER_XT_TARGET_TPROXY +Application support +====================== -Or the floowing modules for nf_tables: +Squid +----- - - NFT_SOCKET - - NFT_TPROXY +Squid 3.1+ has built-in support for TPROXY. To use it, pass +``--enable-linux-netfilter`` to configure and set the 'tproxy' option on the +HTTP listener you redirect traffic to with the TPROXY iptables target. -4. Application support -====================== +For more information please consult the `Squid wiki`_. -4.1. Squid ----------- +HAproxy +------- -Squid 3.HEAD has support built-in. To use it, pass -'--enable-linux-netfilter' to configure and set the 'tproxy' option on -the HTTP listener you redirect traffic to with the TPROXY iptables -target. +Documented in `Haproxy blog`_. -For more information please consult the following page on the Squid -wiki: http://wiki.squid-cache.org/Features/Tproxy4 +.. _`Squid wiki`: http://wiki.squid-cache.org/Features/Tproxy4 +.. _`HAproxy blog`: https://www.haproxy.com/blog/howto-transparent-proxying-and-binding-with-haproxy-and-aloha-load-balancer/ base-commit: 4525c8781ec0701ce824e8bd379ae1b129e26568 -- 2.28.0