← Documents Documentation/networking/tproxy.rst GitHub 원문 ↗

Linux 6.18.37 · Networking

Transparent proxy support

iptables 또는 nf_tables의 socket match와 TPROXY, policy routing 및 IP_TRANSPARENT로 non-local traffic을 proxy에 전달하는 방법입니다.

Source pathDocumentation/networking/tproxy.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

tproxy.rst:1-109

TPROXY는 NAT로 destination을 바꾸지 않고 router의 traffic을 local proxy socket으로 전달합니다. Firewall에서 packet을 mark하고 policy routing으로 loopback local route에 보내며, proxy socket은 bind 전에 `IP_TRANSPARENT`를 활성화해야 합니다.

iptables와 nf_tables 모두 지원하지만 각 backend의 socket match와 TPROXY kernel module이 필요합니다. UDP의 원래 destination 보존과 TCP REDIRECT의 race를 피해야 할 때 특히 유용합니다.

Transparent proxy 구성
socket match/TPROXYpacket markpolicy routinglocal routeIP_TRANSPARENT listenerproxy application

Packet classification부터 proxy listener까지의 필수 경로입니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

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

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Transparent proxy 개요

1-11

이 기능은 현재 kernel에 Linux 2.2와 유사한 transparent proxy 지원을 추가합니다. 사용하려면 kernel configuration에서 socket match와 `TPROXY` target을 활성화해야 합니다.

Packet을 local proxy로 전달하려면 policy routing도 필요하므로 함께 활성화해야 합니다. Linux 4.18부터는 `nf_tables`에서도 transparent proxy를 사용할 수 있습니다.

.. SPDX-License-Identifier: GPL-2.0

=========================
Transparent proxy support
=========================

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.

From Linux 4.18 transparent proxy support is also available in nf_tables.

Non-local socket 동작 구성

12-53

기본 아이디어는 destination address가 이 host의 local socket과 일치하는 packet을 식별하고 packet mark를 특정 값으로 설정하는 것입니다.

iptables 예제는 mangle table에 `DIVERT` chain을 만들고, `PREROUTING`에서 transparent socket과 일치하는 TCP packet을 그 chain으로 보냅니다. `DIVERT`에서는 mark를 1로 설정한 뒤 packet을 accept합니다.

같은 작업은 nft에서도 가능합니다. `prerouting` hook과 priority -150을 사용하는 `divert` chain을 만든 뒤, TCP의 transparent socket match가 1인 packet에 mark 1을 설정하고 accept합니다.

그 다음 policy routing이 mark 1을 match하도록 `fwmark 1` rule을 만들고 table 100을 조회하게 합니다. Table 100의 `local 0.0.0.0/0 dev lo` route가 해당 packet을 local host로 전달합니다.

IPv4 routing output code의 제약 때문에 application도 non-local IP address를 source로 한 datagram을 보낼 수 있도록 수정해야 합니다. `bind()` 호출 전에 `(SOL_IP, IP_TRANSPARENT)` socket option을 활성화하면 됩니다.

예제 C code는 TCP socket을 만든 뒤 `IP_TRANSPARENT`를 1로 설정하고, non-local address와 port에 `bind()`합니다. 문서에는 이를 적용한 간단한 netcat patch 링크도 제공합니다.

Non-local packet의 local delivery
PREROUTING TCP packetsocket --transparent matchmark=1fwmark rule table 100local route dev lotransparent socket

Socket match와 policy routing을 연결합니다.


1. Making non-local sockets work
================================

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::

    # iptables -t mangle -N DIVERT
    # iptables -t mangle -A PREROUTING -p tcp -m socket --transparent -j DIVERT
    # iptables -t mangle -A DIVERT -j MARK --set-mark 1
    # iptables -t mangle -A DIVERT -j ACCEPT

Alternatively you can do this in nft with the following commands::

    # 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

And then match on that value using policy routing to have those packets
delivered locally::

    # 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::

    fd = socket(AF_INET, SOCK_STREAM, 0);
    /* - 8< -*/
    int value = 1;
    setsockopt(fd, SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
    /* - 8< -*/
    name.sin_family = AF_INET;
    name.sin_port = htons(0xCAFE);
    name.sin_addr.s_addr = htonl(0xDEADBEEF);
    bind(fd, &name, sizeof(name));

A trivial patch for netcat is available here:
http://people.netfilter.org/hidden/tproxy/netcat-ip_transparent-support.patch

Traffic interception과 TPROXY

54-83

Transparent proxy는 흔히 router에서 traffic을 가로채는 방식으로 사용합니다. 보통 iptables `REDIRECT` target을 쓰지만 이 방법에는 중대한 제약이 있습니다.

`REDIRECT`는 packet의 destination address를 실제로 변경합니다. UDP proxy에서는 원래 destination address를 알아낼 수 없고, TCP에서도 원래 destination address를 얻는 과정에 race가 있으므로 일부 환경에서는 받아들일 수 없습니다.

`TPROXY` target은 NAT에 의존하지 않고 비슷한 기능을 제공합니다. iptables 예제는 destination port 80의 TCP packet을 port 50080으로 넘기고 `0x1/0x1` mark를 설정합니다.

nft 예제도 TCP destination port 80을 `:50080`으로 tproxy하고 mark 1을 설정한 뒤 accept합니다.

이 구성이 동작하려면 proxy가 listening socket에 `(SOL_IP, IP_TRANSPARENT)`를 활성화해야 합니다. 예제 구현인 `tcprdr`는 Florian Westphal이 작성했으며 nf_tables 구현을 시험하는 데 사용되었습니다.

REDIRECT와 TPROXY
방식NAT 의존원래 destination
REDIRECTPacket destination을 변경하므로 UDP에서 손실, TCP도 race 가능
TPROXY아니요Destination을 변경하지 않고 proxy socket으로 전달

원래 destination 보존 여부가 핵심 차이입니다.


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.

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.

iptables와 nf_tables extension

84-96

iptables에서 tproxy를 사용하려면 `NETFILTER_XT_MATCH_SOCKET`과 `NETFILTER_XT_TARGET_TPROXY` module을 kernel에 compile해야 합니다.

nf_tables를 사용한다면 `NFT_SOCKET`과 `NFT_TPROXY` module이 필요합니다.

필수 kernel module
BackendModules
iptablesNETFILTER_XT_MATCH_SOCKET, NETFILTER_XT_TARGET_TPROXY
nf_tablesNFT_SOCKET, NFT_TPROXY

Firewall backend별 socket match와 TPROXY 지원입니다.

3. Iptables and nf_tables extensions
====================================

To use tproxy you'll need to have the following modules compiled for iptables:

 - NETFILTER_XT_MATCH_SOCKET
 - NETFILTER_XT_TARGET_TPROXY

Or the floowing modules for nf_tables:

 - NFT_SOCKET
 - NFT_TPROXY

Application 지원: Squid

97-109

Squid 3.HEAD에는 transparent proxy 지원이 내장되어 있습니다. 사용하려면 configure에 `--enable-linux-netfilter`를 전달하고, TPROXY iptables target으로 traffic을 redirect하는 HTTP listener에 `tproxy` option을 설정합니다.

자세한 내용은 원문에 연결된 Squid wiki의 Tproxy4 page를 참조합니다.

4. Application support
======================

4.1. Squid
----------

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.

For more information please consult the following page on the Squid
wiki: http://wiki.squid-cache.org/Features/Tproxy4