요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. 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.
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
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.
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
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
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 링크도 제공합니다.
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-83Transparent 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 구현을 시험하는 데 사용되었습니다.
원래 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-96iptables에서 tproxy를 사용하려면 `NETFILTER_XT_MATCH_SOCKET`과 `NETFILTER_XT_TARGET_TPROXY` module을 kernel에 compile해야 합니다.
nf_tables를 사용한다면 `NFT_SOCKET`과 `NFT_TPROXY` module이 필요합니다.
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-109Squid 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
요약·해설
tproxy.rst:1-109TPROXY는 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를 피해야 할 때 특히 유용합니다.
Packet classification부터 proxy listener까지의 필수 경로입니다.