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