]> git.pld-linux.org Git - packages/kernel.git/blame - kernel-tproxy.patch
- applies
[packages/kernel.git] / kernel-tproxy.patch
CommitLineData
2d1341b2 1From f01a1b1a0cb61eaadebd9d910286c5f382a4928c Mon Sep 17 00:00:00 2001
2From: KOVACS Krisztian <hidden@sch.bme.hu>
3Date: Mon, 28 Apr 2008 14:46:46 +0200
4Subject: [PATCH] Loosen source address check on IPv4 output
5
6ip_route_output() contains a check to make sure that no flows with
7non-local source IP addresses are routed. This obviously makes using
8such addresses impossible.
9
10This patch introduces a flowi flag which makes omitting this check
11possible. The new flag provides a way of handling transparent and
12non-transparent connections differently.
13
14Signed-off-by: Julian Anastasov <ja@ssi.bg>
15Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
16Acked-by: Patrick McHardy <kaber@trash.net>
17---
18 include/net/flow.h | 1 +
19 net/ipv4/route.c | 20 +++++++++++++-------
20 2 files changed, 14 insertions(+), 7 deletions(-)
21
22diff --git a/include/net/flow.h b/include/net/flow.h
23index ad16e00..b45a5e4 100644
24--- a/include/net/flow.h
25+++ b/include/net/flow.h
26@@ -48,6 +48,7 @@ struct flowi {
27
28 __u8 proto;
29 __u8 flags;
30+#define FLOWI_FLAG_ANYSRC 0x01
31 union {
32 struct {
33 __be16 sport;
34diff --git a/net/ipv4/route.c b/net/ipv4/route.c
35index ce25a13..c0ed024 100644
36--- a/net/ipv4/route.c
37+++ b/net/ipv4/route.c
38@@ -2307,11 +2307,6 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,
39 ipv4_is_zeronet(oldflp->fl4_src))
40 goto out;
41
42- /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
43- dev_out = ip_dev_find(net, oldflp->fl4_src);
44- if (dev_out == NULL)
45- goto out;
46-
47 /* I removed check for oif == dev_out->oif here.
48 It was wrong for two reasons:
49 1. ip_dev_find(net, saddr) can return wrong iface, if saddr
50@@ -2323,6 +2318,11 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,
51 if (oldflp->oif == 0
52 && (ipv4_is_multicast(oldflp->fl4_dst) ||
53 oldflp->fl4_dst == htonl(0xFFFFFFFF))) {
54+ /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
55+ dev_out = ip_dev_find(net, oldflp->fl4_src);
56+ if (dev_out == NULL)
57+ goto out;
58+
59 /* Special hack: user can direct multicasts
60 and limited broadcast via necessary interface
61 without fiddling with IP_MULTICAST_IF or IP_PKTINFO.
62@@ -2341,9 +2341,15 @@ static int ip_route_output_slow(struct net *net, struct rtable **rp,
63 fl.oif = dev_out->ifindex;
64 goto make_route;
65 }
66- if (dev_out)
67+
68+ if (!(oldflp->flags & FLOWI_FLAG_ANYSRC)) {
69+ /* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */
70+ dev_out = ip_dev_find(net, oldflp->fl4_src);
71+ if (dev_out == NULL)
72+ goto out;
73 dev_put(dev_out);
74- dev_out = NULL;
75+ dev_out = NULL;
76+ }
77 }
78
79
80--
811.5.2.5
82
83From cc2f0afbffaad66b7794e4b4e5d50609f3571fbd Mon Sep 17 00:00:00 2001
84From: KOVACS Krisztian <hidden@sch.bme.hu>
85Date: Mon, 28 Apr 2008 14:46:48 +0200
86Subject: [PATCH] Implement IP_TRANSPARENT socket option
87
88This patch introduces the IP_TRANSPARENT socket option: enabling that will make
89the IPv4 routing omit the non-local source address check on output. Setting
90IP_TRANSPARENT requires NET_ADMIN capability.
91
92Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
93Acked-by: Patrick McHardy <kaber@trash.net>
94---
95 include/linux/in.h | 1 +
96 include/net/inet_sock.h | 3 ++-
97 include/net/inet_timewait_sock.h | 3 ++-
98 net/ipv4/inet_timewait_sock.c | 1 +
99 net/ipv4/ip_sockglue.c | 12 +++++++++++-
100 5 files changed, 17 insertions(+), 3 deletions(-)
101
102diff --git a/include/linux/in.h b/include/linux/in.h
103index 4065313..db458be 100644
104--- a/include/linux/in.h
105+++ b/include/linux/in.h
106@@ -75,6 +75,7 @@ struct in_addr {
107 #define IP_IPSEC_POLICY 16
108 #define IP_XFRM_POLICY 17
109 #define IP_PASSSEC 18
110+#define IP_TRANSPARENT 19
111
112 /* BSD compatibility */
113 #define IP_RECVRETOPTS IP_RETOPTS
114diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
115index a42cd63..2fafaab 100644
116--- a/include/net/inet_sock.h
117+++ b/include/net/inet_sock.h
118@@ -128,7 +128,8 @@ struct inet_sock {
119 is_icsk:1,
120 freebind:1,
121 hdrincl:1,
122- mc_loop:1;
123+ mc_loop:1,
124+ transparent:1;
125 int mc_index;
126 __be32 mc_addr;
127 struct ip_mc_socklist *mc_list;
128diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
129index 95c660c..8d983a2 100644
130--- a/include/net/inet_timewait_sock.h
131+++ b/include/net/inet_timewait_sock.h
132@@ -128,7 +128,8 @@ struct inet_timewait_sock {
133 __be16 tw_dport;
134 __u16 tw_num;
135 /* And these are ours. */
136- __u8 tw_ipv6only:1;
137+ __u8 tw_ipv6only:1,
138+ tw_transparent:1;
139 /* 15 bits hole, try to pack */
140 __u16 tw_ipv6_offset;
141 unsigned long tw_ttd;
142diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
143index ce16e9a..af16fd4 100644
144--- a/net/ipv4/inet_timewait_sock.c
145+++ b/net/ipv4/inet_timewait_sock.c
146@@ -124,6 +124,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat
147 tw->tw_reuse = sk->sk_reuse;
148 tw->tw_hash = sk->sk_hash;
149 tw->tw_ipv6only = 0;
150+ tw->tw_transparent = inet->transparent;
151 tw->tw_prot = sk->sk_prot_creator;
152 twsk_net_set(tw, hold_net(sock_net(sk)));
153 atomic_set(&tw->tw_refcnt, 1);
154diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
155index d8adfd4..a05bec6 100644
156--- a/net/ipv4/ip_sockglue.c
157+++ b/net/ipv4/ip_sockglue.c
158@@ -420,7 +420,7 @@ static int do_ip_setsockopt(struct sock *sk, int level,
159 (1<<IP_TTL) | (1<<IP_HDRINCL) |
160 (1<<IP_MTU_DISCOVER) | (1<<IP_RECVERR) |
161 (1<<IP_ROUTER_ALERT) | (1<<IP_FREEBIND) |
162- (1<<IP_PASSSEC))) ||
163+ (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT))) ||
164 optname == IP_MULTICAST_TTL ||
165 optname == IP_MULTICAST_LOOP) {
166 if (optlen >= sizeof(int)) {
167@@ -879,6 +879,16 @@ static int do_ip_setsockopt(struct sock *sk, int level,
168 err = xfrm_user_policy(sk, optname, optval, optlen);
169 break;
170
171+ case IP_TRANSPARENT:
172+ if (!capable(CAP_NET_ADMIN)) {
173+ err = -EPERM;
174+ break;
175+ }
176+ if (optlen < 1)
177+ goto e_inval;
178+ inet->transparent = !!val;
179+ break;
180+
181 default:
182 err = -ENOPROTOOPT;
183 break;
184--
1851.5.2.5
186
187From b0f9031d33741ccd7745112d425d465035444859 Mon Sep 17 00:00:00 2001
188From: KOVACS Krisztian <hidden@sch.bme.hu>
189Date: Mon, 28 Apr 2008 14:46:48 +0200
190Subject: [PATCH] Allow binding to non-local addresses if IP_TRANSPARENT is set
191MIME-Version: 1.0
192Content-Type: text/plain; charset=utf-8
193Content-Transfer-Encoding: 8bit
194
195Setting IP_TRANSPARENT is not really useful without allowing non-local
196binds for the socket. To make user-space code simpler we allow these binds
197even if IP_TRANSPARENT is set but IP_FREEBIND is not.
198
199Signed-off-by: Tóth László Attila <panther@balabit.hu>
200Acked-by: Patrick McHardy <kaber@trash.net>
201---
202 net/ipv4/af_inet.c | 2 +-
203 1 files changed, 1 insertions(+), 1 deletions(-)
204
205diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
206index f2b5270..d2d1001 100644
207--- a/net/ipv4/af_inet.c
208+++ b/net/ipv4/af_inet.c
209@@ -475,7 +475,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
210 */
211 err = -EADDRNOTAVAIL;
212 if (!sysctl_ip_nonlocal_bind &&
213- !inet->freebind &&
214+ !(inet->freebind || inet->transparent) &&
9fc9ba83 215 nsa.saddr != htonl(INADDR_ANY) &&
2d1341b2 216 chk_addr_ret != RTN_LOCAL &&
217 chk_addr_ret != RTN_MULTICAST &&
218--
2191.5.2.5
220
221From 2b3cf4f3e3aa34ff42d17b202b945db2c5c563b2 Mon Sep 17 00:00:00 2001
222From: KOVACS Krisztian <hidden@sch.bme.hu>
223Date: Mon, 28 Apr 2008 14:46:49 +0200
224Subject: [PATCH] Make inet_sock.h independent of route.h
225
226inet_iif() in inet_sock.h requires route.h. Since users of inet_iif()
227usually require other route.h functionality anyway this patch moves
228inet_iif() to route.h.
229
230Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
231---
9fc9ba83 232 include/net/inet_sock.h | 7 ------- VSERVER patch removed this!
2d1341b2 233 include/net/route.h | 5 +++++
234 net/ipv4/netfilter/nf_nat_helper.c | 1 +
235 net/ipv4/syncookies.c | 1 +
236 net/ipv6/af_inet6.c | 1 +
237 5 files changed, 8 insertions(+), 7 deletions(-)
238
9fc9ba83 239VSERVER patch has own (almost identical) implementation of this.
2d1341b2 240--
2411.5.2.5
242
243From 03bf9d04e8a6d0dc994363c8133ff494226701ef Mon Sep 17 00:00:00 2001
244From: KOVACS Krisztian <hidden@sch.bme.hu>
245Date: Mon, 28 Apr 2008 14:46:50 +0200
246Subject: [PATCH] Conditionally enable transparent flow flag when connecting
247
248Set FLOWI_FLAG_ANYSRC in flowi->flags if the socket has the
249transparent socket option set. This way we selectively enable certain
250connections with non-local source addresses to be routed.
251
252Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
253---
254 include/net/route.h | 6 +++++-
255 1 files changed, 5 insertions(+), 1 deletions(-)
256
257diff --git a/include/net/route.h b/include/net/route.h
258index 13e464f..2928618 100644
259--- a/include/net/route.h
260+++ b/include/net/route.h
261@@ -27,7 +27,7 @@
262 #include <net/dst.h>
263 #include <net/inetpeer.h>
264 #include <net/flow.h>
265-#include <net/sock.h>
266+#include <net/inet_sock.h>
dc278809 267 // #include <linux/in.h>
2d1341b2 268 #include <linux/in_route.h>
269 #include <linux/rtnetlink.h>
dc278809 270@@ -175,6 +175,9 @@
2d1341b2 271 struct net *net = sock_net(sk);
9fc9ba83 272 struct nx_info *nx_info = current->nx_info;
dc278809 273
2d1341b2 274+ if (inet_sk(sk)->transparent)
275+ fl.flags |= FLOWI_FLAG_ANYSRC;
dc278809 276+
9fc9ba83 277 if (sk)
278 nx_info = sk->sk_nx_info;
dc278809 279
2d1341b2 280--
2811.5.2.5
282
283From 181680c6c0df4335bd8eeeafe06ea12e6918c3b7 Mon Sep 17 00:00:00 2001
284From: KOVACS Krisztian <hidden@sch.bme.hu>
285Date: Mon, 28 Apr 2008 14:46:50 +0200
286Subject: [PATCH] Handle TCP SYN+ACK/ACK/RST transparency
287
288The TCP stack sends out SYN+ACK/ACK/RST reply packets in response to
289incoming packets. The non-local source address check on output bites
290us again, as replies for transparently redirected traffic won't have a
291chance to leave the node.
292
293This patch selectively sets the FLOWI_FLAG_ANYSRC flag when doing
294the route lookup for those replies. Transparent replies are enabled if
295the listening socket has the transparent socket flag set.
296
297Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
298---
299 include/net/inet_sock.h | 8 +++++++-
300 include/net/ip.h | 9 +++++++++
301 net/ipv4/inet_connection_sock.c | 1 +
302 net/ipv4/ip_output.c | 4 +++-
303 net/ipv4/syncookies.c | 1 +
304 net/ipv4/tcp_ipv4.c | 11 ++++++++---
305 6 files changed, 29 insertions(+), 5 deletions(-)
306
307diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
308index 5ca683e..013e41d 100644
309--- a/include/net/inet_sock.h
310+++ b/include/net/inet_sock.h
311@@ -71,7 +71,8 @@ struct inet_request_sock {
312 sack_ok : 1,
313 wscale_ok : 1,
314 ecn_ok : 1,
315- acked : 1;
316+ acked : 1,
317+ no_srccheck: 1;
318 struct ip_options *opt;
319 };
320
321@@ -191,4 +192,9 @@ static inline int inet_sk_ehashfn(const struct sock *sk)
322 return inet_ehashfn(laddr, lport, faddr, fport);
323 }
324
325+static inline __u8 inet_sk_flowi_flags(const struct sock *sk)
326+{
327+ return inet_sk(sk)->transparent ? FLOWI_FLAG_ANYSRC : 0;
328+}
329+
330 #endif /* _INET_SOCK_H */
331diff --git a/include/net/ip.h b/include/net/ip.h
332index 6d7bcd5..c611608 100644
333--- a/include/net/ip.h
334+++ b/include/net/ip.h
335@@ -29,6 +29,7 @@
336
337 #include <net/inet_sock.h>
338 #include <net/snmp.h>
339+#include <net/flow.h>
340
341 struct sock;
342
343@@ -140,12 +141,20 @@ static inline void ip_tr_mc_map(__be32 addr, char *buf)
344
345 struct ip_reply_arg {
346 struct kvec iov[1];
347+ int flags;
348 __wsum csum;
349 int csumoffset; /* u16 offset of csum in iov[0].iov_base */
350 /* -1 if not needed */
351 int bound_dev_if;
352 };
353
354+#define IP_REPLY_ARG_NOSRCCHECK 1
355+
356+static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg)
357+{
358+ return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0;
359+}
360+
361 void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg,
362 unsigned int len);
363
364diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
365index 828ea21..6d70d51 100644
366--- a/net/ipv4/inet_connection_sock.c
367+++ b/net/ipv4/inet_connection_sock.c
368@@ -333,6 +333,7 @@ struct dst_entry* inet_csk_route_req(struct sock *sk,
369 .saddr = ireq->loc_addr,
370 .tos = RT_CONN_FLAGS(sk) } },
371 .proto = sk->sk_protocol,
372+ .flags = inet_sk_flowi_flags(sk),
373 .uli_u = { .ports =
374 { .sport = inet_sk(sk)->sport,
375 .dport = ireq->rmt_port } } };
376diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
377index 0834926..9ac5270 100644
378--- a/net/ipv4/ip_output.c
379+++ b/net/ipv4/ip_output.c
380@@ -342,6 +342,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
381 .saddr = inet->saddr,
382 .tos = RT_CONN_FLAGS(sk) } },
383 .proto = sk->sk_protocol,
384+ .flags = inet_sk_flowi_flags(sk),
385 .uli_u = { .ports =
386 { .sport = inet->sport,
387 .dport = inet->dport } } };
388@@ -1380,7 +1381,8 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
389 .uli_u = { .ports =
390 { .sport = tcp_hdr(skb)->dest,
391 .dport = tcp_hdr(skb)->source } },
392- .proto = sk->sk_protocol };
393+ .proto = sk->sk_protocol,
394+ .flags = ip_reply_arg_flowi_flags(arg) };
395 security_skb_classify_flow(skb, &fl);
396 if (ip_route_output_key(sock_net(sk), &rt, &fl))
397 return;
398diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
399index 19a1037..d5fa8c7 100644
400--- a/net/ipv4/syncookies.c
401+++ b/net/ipv4/syncookies.c
402@@ -340,6 +340,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
403 .saddr = ireq->loc_addr,
404 .tos = RT_CONN_FLAGS(sk) } },
405 .proto = IPPROTO_TCP,
406+ .flags = inet_sk_flowi_flags(sk),
407 .uli_u = { .ports =
408 { .sport = th->dest,
409 .dport = th->source } } };
410diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
411index 0e9bc12..58873ad 100644
412--- a/net/ipv4/tcp_ipv4.c
413+++ b/net/ipv4/tcp_ipv4.c
414@@ -594,6 +594,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
415 ip_hdr(skb)->saddr, /* XXX */
416 sizeof(struct tcphdr), IPPROTO_TCP, 0);
417 arg.csumoffset = offsetof(struct tcphdr, check) / 2;
418+ arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0;
419
9fc9ba83 420 ip_send_reply(skb->dst->dev->nd_net->ipv4.tcp_sock, skb,
2d1341b2 421 &arg, arg.iov[0].iov_len);
422@@ -608,7 +609,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
423
424 static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
425 struct sk_buff *skb, u32 seq, u32 ack,
426- u32 win, u32 ts)
427+ u32 win, u32 ts, int reply_flags)
428 {
429 struct tcphdr *th = tcp_hdr(skb);
430 struct {
431@@ -684,6 +685,7 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
432 arg.iov[0].iov_len);
433 }
434 #endif
435+ arg.flags = reply_flags;
436 arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
437 ip_hdr(skb)->saddr, /* XXX */
438 arg.iov[0].iov_len, IPPROTO_TCP, 0);
439@@ -704,7 +706,8 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
440
441 tcp_v4_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
442 tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
443- tcptw->tw_ts_recent);
444+ tcptw->tw_ts_recent,
445+ tw->tw_transparent ? IP_REPLY_ARG_NOSRCCHECK : 0);
446
447 inet_twsk_put(tw);
448 }
449@@ -714,7 +717,8 @@ static void tcp_v4_reqsk_send_ack(struct sk_buff *skb,
450 {
451 tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1,
452 tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
453- req->ts_recent);
454+ req->ts_recent,
455+ inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0);
456 }
457
458 /*
459@@ -1321,6 +1325,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
460 ireq = inet_rsk(req);
461 ireq->loc_addr = daddr;
462 ireq->rmt_addr = saddr;
463+ ireq->no_srccheck = inet_sk(sk)->transparent;
464 ireq->opt = tcp_v4_save_options(sk, skb);
465 if (!want_cookie)
466 TCP_ECN_create_request(req, tcp_hdr(skb));
467--
4681.5.2.5
469
470From f8be7a55d2a449d188f033d7914d2af007054fbc Mon Sep 17 00:00:00 2001
471From: KOVACS Krisztian <hidden@sch.bme.hu>
472Date: Mon, 28 Apr 2008 14:46:50 +0200
473Subject: [PATCH] Make Netfilter's ip_route_me_harder() non-local address compatible
474
475Netfilter's ip_route_me_harder() tries to re-route packets either generated or
476re-routed by Netfilter. This patch changes ip_route_me_harder() to handle
477packets from non-locally-bound sockets with IP_TRANSPARENT set as local and to
478set the appropriate flowi flags when re-doing the routing lookup.
479
480Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
481---
482 net/ipv4/netfilter.c | 3 +++
483 1 files changed, 3 insertions(+), 0 deletions(-)
484
485diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
486index f8edacd..01671ad 100644
487--- a/net/ipv4/netfilter.c
488+++ b/net/ipv4/netfilter.c
489@@ -20,6 +20,8 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
490 unsigned int type;
491
492 type = inet_addr_type(&init_net, iph->saddr);
493+ if (skb->sk && inet_sk(skb->sk)->transparent)
494+ type = RTN_LOCAL;
495 if (addr_type == RTN_UNSPEC)
496 addr_type = type;
497
498@@ -33,6 +35,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
499 fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
500 fl.oif = skb->sk ? skb->sk->sk_bound_dev_if : 0;
501 fl.mark = skb->mark;
502+ fl.flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0;
503 if (ip_route_output_key(&init_net, &rt, &fl) != 0)
504 return -1;
505
506--
5071.5.2.5
508
509From 7797a39b59dae015e06bd4860affbdb250c312b7 Mon Sep 17 00:00:00 2001
510From: KOVACS Krisztian <hidden@sch.bme.hu>
511Date: Mon, 28 Apr 2008 14:46:50 +0200
512Subject: [PATCH] Port redirection support for TCP
513
514Current TCP code relies on the local port of the listening socket
515being the same as the destination address of the incoming
516connection. Port redirection used by many transparent proxying
517techniques obviously breaks this, so we have to store the original
518destination port address.
519
520This patch extends struct inet_request_sock and stores the incoming
521destination port value there. It also modifies the handshake code to
522use that value as the source port when sending reply packets.
523
524Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
525---
526 include/net/inet_sock.h | 2 +-
527 include/net/tcp.h | 1 +
528 net/ipv4/inet_connection_sock.c | 2 ++
529 net/ipv4/syncookies.c | 1 +
530 net/ipv4/tcp_output.c | 2 +-
531 5 files changed, 6 insertions(+), 2 deletions(-)
532
533diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
534index 013e41d..42b5d36 100644
535--- a/include/net/inet_sock.h
536+++ b/include/net/inet_sock.h
537@@ -60,8 +60,8 @@ struct inet_request_sock {
538 struct request_sock req;
539 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
540 u16 inet6_rsk_offset;
541- /* 2 bytes hole, try to pack */
542 #endif
543+ __be16 loc_port;
544 __be32 loc_addr;
545 __be32 rmt_addr;
546 __be16 rmt_port;
547diff --git a/include/net/tcp.h b/include/net/tcp.h
548index 633147c..3c6a549 100644
549--- a/include/net/tcp.h
550+++ b/include/net/tcp.h
551@@ -975,6 +975,7 @@ static inline void tcp_openreq_init(struct request_sock *req,
552 ireq->acked = 0;
553 ireq->ecn_ok = 0;
554 ireq->rmt_port = tcp_hdr(skb)->source;
555+ ireq->loc_port = tcp_hdr(skb)->dest;
556 }
557
558 extern void tcp_enter_memory_pressure(void);
559diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
560index 6d70d51..33dc826 100644
561--- a/net/ipv4/inet_connection_sock.c
562+++ b/net/ipv4/inet_connection_sock.c
563@@ -508,6 +508,8 @@ struct sock *inet_csk_clone(struct sock *sk, const struct request_sock *req,
564 newicsk->icsk_bind_hash = NULL;
565
566 inet_sk(newsk)->dport = inet_rsk(req)->rmt_port;
567+ inet_sk(newsk)->num = ntohs(inet_rsk(req)->loc_port);
568+ inet_sk(newsk)->sport = inet_rsk(req)->loc_port;
569 newsk->sk_write_space = sk_stream_write_space;
570
571 newicsk->icsk_retransmits = 0;
572diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
573index d5fa8c7..676c550 100644
574--- a/net/ipv4/syncookies.c
575+++ b/net/ipv4/syncookies.c
576@@ -299,6 +299,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
577 treq->rcv_isn = ntohl(th->seq) - 1;
578 treq->snt_isn = cookie;
579 req->mss = mss;
580+ ireq->loc_port = th->dest;
581 ireq->rmt_port = th->source;
582 ireq->loc_addr = ip_hdr(skb)->daddr;
583 ireq->rmt_addr = ip_hdr(skb)->saddr;
584diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
585index debf235..2b1d34d 100644
586--- a/net/ipv4/tcp_output.c
587+++ b/net/ipv4/tcp_output.c
588@@ -2211,7 +2211,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
589 th->syn = 1;
590 th->ack = 1;
591 TCP_ECN_make_synack(req, th);
592- th->source = inet_sk(sk)->sport;
593+ th->source = ireq->loc_port;
594 th->dest = ireq->rmt_port;
595 /* Setting of flags are superfluous here for callers (and ECE is
596 * not even correctly set)
597--
5981.5.2.5
599
600From 4feb1a188b6bd0ff8cab5c8d817fbfc7d7788802 Mon Sep 17 00:00:00 2001
601From: KOVACS Krisztian <hidden@sch.bme.hu>
602Date: Mon, 28 Apr 2008 14:46:51 +0200
603Subject: [PATCH] Export UDP socket lookup function
604
605The iptables tproxy code has to be able to do UDP socket hash lookups,
606so we have to provide an exported lookup function for this purpose.
607
608Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
609---
610 include/net/udp.h | 4 ++++
611 net/ipv4/udp.c | 7 +++++++
612 2 files changed, 11 insertions(+), 0 deletions(-)
613
614diff --git a/include/net/udp.h b/include/net/udp.h
615index 3e55a99..b88a196 100644
616--- a/include/net/udp.h
617+++ b/include/net/udp.h
618@@ -147,6 +147,10 @@ extern int udp_lib_setsockopt(struct sock *sk, int level, int optname,
619 char __user *optval, int optlen,
620 int (*push_pending_frames)(struct sock *));
621
622+extern struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
623+ __be32 daddr, __be16 dport,
624+ int dif);
625+
626 DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
627 DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6);
628
629diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
630index 1f535e3..672d0d4 100644
631--- a/net/ipv4/udp.c
632+++ b/net/ipv4/udp.c
633@@ -307,6 +307,13 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
634 return result;
635 }
636
637+struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
638+ __be32 daddr, __be16 dport, int dif)
639+{
640+ return __udp4_lib_lookup(net, saddr, sport, daddr, dport, dif, udp_hash);
641+}
642+EXPORT_SYMBOL_GPL(udp4_lib_lookup);
643+
644 static inline struct sock *udp_v4_mcast_next(struct sock *sk,
645 __be16 loc_port, __be32 loc_addr,
646 __be16 rmt_port, __be32 rmt_addr,
647--
6481.5.2.5
649
650From d49cee38069417f3cb83ca67baa65a2034d2d2ce Mon Sep 17 00:00:00 2001
651From: KOVACS Krisztian <hidden@sch.bme.hu>
652Date: Mon, 28 Apr 2008 14:46:51 +0200
653Subject: [PATCH] Split Netfilter IPv4 defragmentation into a separate module
654
655Netfilter connection tracking requires all IPv4 packets to be defragmented.
656Both the socket match and the TPROXY target depend on this functionality, so
657this patch separates the Netfilter IPv4 defrag hooks into a separate module.
658
659Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
660---
661 include/net/netfilter/ipv4/nf_defrag_ipv4.h | 6 ++
662 net/ipv4/netfilter/Kconfig | 5 +
663 net/ipv4/netfilter/Makefile | 3 +
664 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 56 +-------------
665 net/ipv4/netfilter/nf_defrag_ipv4.c | 96 ++++++++++++++++++++++++
666 5 files changed, 113 insertions(+), 53 deletions(-)
667
668diff --git a/include/net/netfilter/ipv4/nf_defrag_ipv4.h b/include/net/netfilter/ipv4/nf_defrag_ipv4.h
669new file mode 100644
670index 0000000..6b00ea3
671--- /dev/null
672+++ b/include/net/netfilter/ipv4/nf_defrag_ipv4.h
673@@ -0,0 +1,6 @@
674+#ifndef _NF_DEFRAG_IPV4_H
675+#define _NF_DEFRAG_IPV4_H
676+
677+extern void nf_defrag_ipv4_enable(void);
678+
679+#endif /* _NF_DEFRAG_IPV4_H */
680diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
681index 2767841..3520c01 100644
682--- a/net/ipv4/netfilter/Kconfig
683+++ b/net/ipv4/netfilter/Kconfig
684@@ -5,10 +5,15 @@
685 menu "IP: Netfilter Configuration"
686 depends on INET && NETFILTER
687
688+config NF_DEFRAG_IPV4
689+ tristate
690+ default n
691+
692 config NF_CONNTRACK_IPV4
693 tristate "IPv4 connection tracking support (required for NAT)"
694 depends on NF_CONNTRACK
695 default m if NETFILTER_ADVANCED=n
696+ select NF_DEFRAG_IPV4
697 ---help---
698 Connection tracking keeps a record of what packets have passed
699 through your machine, in order to figure out how they are related
700diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
701index d9b92fb..782b1e7 100644
702--- a/net/ipv4/netfilter/Makefile
703+++ b/net/ipv4/netfilter/Makefile
704@@ -18,6 +18,9 @@ obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o
705
706 obj-$(CONFIG_NF_NAT) += nf_nat.o
707
708+# defrag
709+obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o
710+
711 # NAT helpers (nf_conntrack)
712 obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o
713 obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o
714diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
715index cacb9cb..9da59f3 100644
716--- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
717+++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
718@@ -1,3 +1,4 @@
719+
720 /* (C) 1999-2001 Paul `Rusty' Russell
721 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
722 *
dc278809 723@@ -23,6 +24,7 @@
9fc9ba83 724 #include <net/netfilter/nf_conntrack_l3proto.h>
2d1341b2 725 #include <net/netfilter/nf_conntrack_core.h>
726 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
2d1341b2 727+#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
dc278809 728 #include <net/netfilter/nf_nat_helper.h>
2d1341b2 729
730 int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
dc278809 731@@ -63,23 +65,6 @@
2d1341b2 732 NIPQUAD(tuple->dst.u3.ip));
733 }
734
735-/* Returns new sk_buff, or NULL */
736-static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
737-{
738- int err;
739-
740- skb_orphan(skb);
741-
742- local_bh_disable();
743- err = ip_defrag(skb, user);
744- local_bh_enable();
745-
746- if (!err)
747- ip_send_check(ip_hdr(skb));
748-
749- return err;
750-}
751-
752 static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
753 unsigned int *dataoff, u_int8_t *protonum)
754 {
dc278809 755@@ -144,28 +129,6 @@
2d1341b2 756 return nf_conntrack_confirm(skb);
757 }
758
759-static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
760- struct sk_buff *skb,
761- const struct net_device *in,
762- const struct net_device *out,
763- int (*okfn)(struct sk_buff *))
764-{
765- /* Previously seen (loopback)? Ignore. Do this before
766- fragment check. */
767- if (skb->nfct)
768- return NF_ACCEPT;
769-
770- /* Gather fragments. */
771- if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
772- if (nf_ct_ipv4_gather_frags(skb,
773- hooknum == NF_INET_PRE_ROUTING ?
774- IP_DEFRAG_CONNTRACK_IN :
775- IP_DEFRAG_CONNTRACK_OUT))
776- return NF_STOLEN;
777- }
778- return NF_ACCEPT;
779-}
780-
781 static unsigned int ipv4_conntrack_in(unsigned int hooknum,
782 struct sk_buff *skb,
783 const struct net_device *in,
dc278809 784@@ -195,13 +158,6 @@
2d1341b2 785 make it the first hook. */
786 static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
787 {
788- .hook = ipv4_conntrack_defrag,
789- .owner = THIS_MODULE,
790- .pf = PF_INET,
791- .hooknum = NF_INET_PRE_ROUTING,
792- .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
793- },
794- {
795 .hook = ipv4_conntrack_in,
796 .owner = THIS_MODULE,
797 .pf = PF_INET,
dc278809 798@@ -209,13 +165,6 @@
2d1341b2 799 .priority = NF_IP_PRI_CONNTRACK,
800 },
801 {
802- .hook = ipv4_conntrack_defrag,
803- .owner = THIS_MODULE,
804- .pf = PF_INET,
805- .hooknum = NF_INET_LOCAL_OUT,
806- .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
807- },
808- {
809 .hook = ipv4_conntrack_local,
810 .owner = THIS_MODULE,
811 .pf = PF_INET,
dc278809 812@@ -422,6 +371,7 @@
2d1341b2 813 int ret = 0;
814
815 need_conntrack();
816+ nf_defrag_ipv4_enable();
817
818 ret = nf_register_sockopt(&so_getorigdst);
819 if (ret < 0) {
820diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
821new file mode 100644
822index 0000000..aa2c50a
823--- /dev/null
824+++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
825@@ -0,0 +1,96 @@
826+/* (C) 1999-2001 Paul `Rusty' Russell
827+ * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
828+ *
829+ * This program is free software; you can redistribute it and/or modify
830+ * it under the terms of the GNU General Public License version 2 as
831+ * published by the Free Software Foundation.
832+ */
833+
834+#include <linux/types.h>
835+#include <linux/ip.h>
836+#include <linux/netfilter.h>
837+#include <linux/module.h>
838+#include <linux/skbuff.h>
839+#include <net/route.h>
840+#include <net/ip.h>
841+
842+#include <linux/netfilter_ipv4.h>
843+#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
844+
845+/* Returns new sk_buff, or NULL */
846+static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
847+{
848+ int err;
849+
850+ skb_orphan(skb);
851+
852+ local_bh_disable();
853+ err = ip_defrag(skb, user);
854+ local_bh_enable();
855+
856+ if (!err)
857+ ip_send_check(ip_hdr(skb));
858+
859+ return err;
860+}
861+
862+static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
863+ struct sk_buff *skb,
864+ const struct net_device *in,
865+ const struct net_device *out,
866+ int (*okfn)(struct sk_buff *))
867+{
868+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
869+ /* Previously seen (loopback)? Ignore. Do this before
870+ fragment check. */
871+ if (skb->nfct)
872+ return NF_ACCEPT;
873+#endif
874+
875+ /* Gather fragments. */
876+ if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
877+ if (nf_ct_ipv4_gather_frags(skb,
878+ hooknum == NF_INET_PRE_ROUTING ?
879+ IP_DEFRAG_CONNTRACK_IN :
880+ IP_DEFRAG_CONNTRACK_OUT))
881+ return NF_STOLEN;
882+ }
883+ return NF_ACCEPT;
884+}
885+
886+static struct nf_hook_ops ipv4_defrag_ops[] = {
887+ {
888+ .hook = ipv4_conntrack_defrag,
889+ .owner = THIS_MODULE,
890+ .pf = PF_INET,
891+ .hooknum = NF_INET_PRE_ROUTING,
892+ .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
893+ },
894+ {
895+ .hook = ipv4_conntrack_defrag,
896+ .owner = THIS_MODULE,
897+ .pf = PF_INET,
898+ .hooknum = NF_INET_LOCAL_OUT,
899+ .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
900+ },
901+};
902+
903+static int __init nf_defrag_init(void)
904+{
905+ return nf_register_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));
906+}
907+
908+static void __exit nf_defrag_fini(void)
909+{
910+ nf_unregister_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));
911+}
912+
913+void nf_defrag_ipv4_enable(void)
914+{
915+}
916+EXPORT_SYMBOL_GPL(nf_defrag_ipv4_enable);
917+
918+module_init(nf_defrag_init);
919+module_exit(nf_defrag_fini);
920+
921+MODULE_LICENSE("GPL");
922--
9231.5.2.5
924
925From 40b01b3ada99906bb5818e15cddfe49344d09fd9 Mon Sep 17 00:00:00 2001
926From: KOVACS Krisztian <hidden@sch.bme.hu>
927Date: Mon, 28 Apr 2008 14:46:51 +0200
928Subject: [PATCH] iptables tproxy core
929
930The iptables tproxy core is a module that contains the common routines used by
931various tproxy related modules (TPROXY target and socket match)
932
933Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
934---
935 include/net/netfilter/nf_tproxy_core.h | 32 +++++++++++
936 net/netfilter/Kconfig | 15 +++++
937 net/netfilter/Makefile | 3 +
938 net/netfilter/nf_tproxy_core.c | 96 ++++++++++++++++++++++++++++++++
939 4 files changed, 146 insertions(+), 0 deletions(-)
940
941diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h
942new file mode 100644
943index 0000000..208b46f
944--- /dev/null
945+++ b/include/net/netfilter/nf_tproxy_core.h
946@@ -0,0 +1,32 @@
947+#ifndef _NF_TPROXY_CORE_H
948+#define _NF_TPROXY_CORE_H
949+
950+#include <linux/types.h>
951+#include <linux/in.h>
952+#include <linux/skbuff.h>
953+#include <net/sock.h>
954+#include <net/inet_sock.h>
955+#include <net/tcp.h>
956+
957+/* look up and get a reference to a matching socket */
958+extern struct sock *
959+nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
960+ const __be32 saddr, const __be32 daddr,
961+ const __be16 sport, const __be16 dport,
962+ const struct net_device *in, bool listening);
963+
964+static inline void
965+nf_tproxy_put_sock(struct sock *sk)
966+{
967+ /* TIME_WAIT inet sockets have to be handled differently */
968+ if ((sk->sk_protocol == IPPROTO_TCP) && (sk->sk_state == TCP_TIME_WAIT))
969+ inet_twsk_put(inet_twsk(sk));
970+ else
971+ sock_put(sk);
972+}
973+
974+/* assign a socket to the skb -- consumes sk */
975+int
976+nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk);
977+
978+#endif
979diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
980index c1fc0f1..de42858 100644
981--- a/net/netfilter/Kconfig
982+++ b/net/netfilter/Kconfig
983@@ -277,6 +277,21 @@ config NF_CT_NETLINK
984 help
985 This option enables support for a netlink-based userspace interface
986
987+# transparent proxy support
988+config NETFILTER_TPROXY
989+ tristate "Transparent proxying support (EXPERIMENTAL)"
990+ depends on EXPERIMENTAL
991+ depends on IP_NF_MANGLE
992+ depends on NETFILTER_ADVANCED
993+ help
994+ This option enables transparent proxying support, that is,
995+ support for handling non-locally bound IPv4 TCP and UDP sockets.
996+ For it to work you will have to configure certain iptables rules
997+ and use policy routing. For more information on how to set it up
998+ see Documentation/networking/tproxy.txt.
999+
1000+ To compile it as a module, choose M here. If unsure, say N.
1001+
1002 config NETFILTER_XTABLES
1003 tristate "Netfilter Xtables support (required for ip_tables)"
1004 default m if NETFILTER_ADVANCED=n
1005diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
1006index 5c4b183..d644e82 100644
1007--- a/net/netfilter/Makefile
1008+++ b/net/netfilter/Makefile
1009@@ -34,6 +34,9 @@ obj-$(CONFIG_NF_CONNTRACK_SANE) += nf_conntrack_sane.o
1010 obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o
1011 obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o
1012
1013+# transparent proxy support
1014+obj-$(CONFIG_NETFILTER_TPROXY) += nf_tproxy_core.o
1015+
1016 # generic X tables
1017 obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
1018
1019diff --git a/net/netfilter/nf_tproxy_core.c b/net/netfilter/nf_tproxy_core.c
1020new file mode 100644
1021index 0000000..8a6075d
1022--- /dev/null
1023+++ b/net/netfilter/nf_tproxy_core.c
1024@@ -0,0 +1,96 @@
1025+/*
1026+ * Transparent proxy support for Linux/iptables
1027+ *
1028+ * Copyright (c) 2006-2007 BalaBit IT Ltd.
1029+ * Author: Balazs Scheidler, Krisztian Kovacs
1030+ *
1031+ * This program is free software; you can redistribute it and/or modify
1032+ * it under the terms of the GNU General Public License version 2 as
1033+ * published by the Free Software Foundation.
1034+ *
1035+ */
1036+
1037+#include <linux/version.h>
1038+#include <linux/module.h>
1039+
1040+#include <linux/net.h>
1041+#include <linux/if.h>
1042+#include <linux/netdevice.h>
1043+#include <net/udp.h>
1044+#include <net/netfilter/nf_tproxy_core.h>
1045+
1046+struct sock *
1047+nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
1048+ const __be32 saddr, const __be32 daddr,
1049+ const __be16 sport, const __be16 dport,
1050+ const struct net_device *in, bool listening_only)
1051+{
1052+ struct sock *sk;
1053+
1054+ /* look up socket */
1055+ switch (protocol) {
1056+ case IPPROTO_TCP:
1057+ if (listening_only)
1058+ sk = __inet_lookup_listener(net, &tcp_hashinfo,
1059+ daddr, ntohs(dport),
1060+ in->ifindex);
1061+ else
1062+ sk = __inet_lookup(net, &tcp_hashinfo,
1063+ saddr, sport, daddr, dport,
1064+ in->ifindex);
1065+ break;
1066+ case IPPROTO_UDP:
1067+ sk = udp4_lib_lookup(net, saddr, sport, daddr, dport,
1068+ in->ifindex);
1069+ break;
1070+ default:
1071+ WARN_ON(1);
1072+ sk = NULL;
1073+ }
1074+
1075+ pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u sock %p\n",
1076+ protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), sk);
1077+
1078+ return sk;
1079+}
1080+EXPORT_SYMBOL_GPL(nf_tproxy_get_sock_v4);
1081+
1082+static void
1083+nf_tproxy_destructor(struct sk_buff *skb)
1084+{
1085+ struct sock *sk = skb->sk;
1086+
1087+ skb->sk = NULL;
1088+ skb->destructor = NULL;
1089+
1090+ if (sk)
1091+ nf_tproxy_put_sock(sk);
1092+}
1093+
1094+/* consumes sk */
1095+int
1096+nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk)
1097+{
1098+ if (inet_sk(sk)->transparent) {
1099+ skb->sk = sk;
1100+ skb->destructor = nf_tproxy_destructor;
1101+ return 1;
1102+ } else
1103+ nf_tproxy_put_sock(sk);
1104+
1105+ return 0;
1106+}
1107+EXPORT_SYMBOL_GPL(nf_tproxy_assign_sock);
1108+
1109+static int __init nf_tproxy_init(void)
1110+{
1111+ pr_info("NF_TPROXY: Transparent proxy support initialized, version 4.1.0\n");
1112+ pr_info("NF_TPROXY: Copyright (c) 2006-2007 BalaBit IT Ltd.\n");
1113+ return 0;
1114+}
1115+
1116+module_init(nf_tproxy_init);
1117+
1118+MODULE_LICENSE("GPL");
1119+MODULE_AUTHOR("Krisztian Kovacs");
1120+MODULE_DESCRIPTION("Transparent proxy support core routines");
1121--
11221.5.2.5
1123
1124From 7962977079ac28db798ab5b11ee31df6566fb472 Mon Sep 17 00:00:00 2001
1125From: KOVACS Krisztian <hidden@sch.bme.hu>
1126Date: Mon, 28 Apr 2008 14:46:52 +0200
1127Subject: [PATCH] iptables socket match
1128
1129Add iptables 'socket' match, which matches packets for which a TCP/UDP
1130socket lookup succeeds.
1131
1132Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
1133Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
1134---
1135 net/netfilter/Kconfig | 15 +++++
1136 net/netfilter/Makefile | 1 +
1137 net/netfilter/xt_socket.c | 133 +++++++++++++++++++++++++++++++++++++++++++++
1138 3 files changed, 149 insertions(+), 0 deletions(-)
1139
1140diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
1141index de42858..ce21278 100644
1142--- a/net/netfilter/Kconfig
1143+++ b/net/netfilter/Kconfig
1144@@ -748,6 +748,21 @@ config NETFILTER_XT_MATCH_SCTP
1145 If you want to compile it as a module, say M here and read
1146 <file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
1147
1148+config NETFILTER_XT_MATCH_SOCKET
1149+ tristate '"socket" match support (EXPERIMENTAL)'
1150+ depends on EXPERIMENTAL
1151+ depends on NETFILTER_TPROXY
1152+ depends on NETFILTER_XTABLES
1153+ depends on NETFILTER_ADVANCED
1154+ select NF_DEFRAG_IPV4
1155+ help
1156+ This option adds a `socket' match, which can be used to match
1157+ packets for which a TCP or UDP socket lookup finds a valid socket.
1158+ It can be used in combination with the MARK target and policy
1159+ routing to implement full featured non-locally bound sockets.
1160+
1161+ To compile it as a module, choose M here. If unsure, say N.
1162+
1163 config NETFILTER_XT_MATCH_STATE
1164 tristate '"state" match support'
1165 depends on NETFILTER_XTABLES
1166diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
1167index d644e82..6d2eee6 100644
1168--- a/net/netfilter/Makefile
1169+++ b/net/netfilter/Makefile
1170@@ -80,6 +80,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_QUOTA) += xt_quota.o
1171 obj-$(CONFIG_NETFILTER_XT_MATCH_RATEEST) += xt_rateest.o
1172 obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
1173 obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
1174+obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o
1175 obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
1176 obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
1177 obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
1178diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
1179new file mode 100644
1180index 0000000..fa33358
1181--- /dev/null
1182+++ b/net/netfilter/xt_socket.c
1183@@ -0,0 +1,133 @@
1184+/*
1185+ * Transparent proxy support for Linux/iptables
1186+ *
1187+ * Copyright (C) 2007 BalaBit IT Ltd.
1188+ * Author: Krisztian Kovacs
1189+ *
1190+ * This program is free software; you can redistribute it and/or modify
1191+ * it under the terms of the GNU General Public License version 2 as
1192+ * published by the Free Software Foundation.
1193+ *
1194+ */
1195+
1196+#include <linux/module.h>
1197+#include <linux/skbuff.h>
1198+#include <linux/netfilter/x_tables.h>
1199+#include <linux/netfilter_ipv4/ip_tables.h>
1200+#include <net/tcp.h>
1201+#include <net/udp.h>
1202+#include <net/sock.h>
1203+#include <net/inet_sock.h>
1204+#include <net/netfilter/nf_tproxy_core.h>
1205+#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
1206+
1207+#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
1208+#define XT_SOCKET_HAVE_CONNTRACK 1
1209+#include <net/netfilter/nf_conntrack.h>
1210+#endif
1211+
1212+static bool
1213+socket_mt(const struct sk_buff *skb,
1214+ const struct net_device *in,
1215+ const struct net_device *out,
1216+ const struct xt_match *match,
1217+ const void *matchinfo,
1218+ int offset,
1219+ unsigned int protoff,
1220+ bool *hotdrop)
1221+{
1222+ const struct iphdr *iph = ip_hdr(skb);
1223+ struct udphdr _hdr, *hp;
1224+ struct sock *sk;
1225+ __be32 daddr;
1226+ __be16 dport;
1227+#ifdef XT_SOCKET_HAVE_CONNTRACK
1228+ struct nf_conn const *ct;
1229+ enum ip_conntrack_info ctinfo;
1230+#endif
1231+
1232+ hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr);
1233+ if (hp == NULL)
1234+ return false;
1235+
1236+ daddr = iph->daddr;
1237+ dport = hp->dest;
1238+
1239+#ifdef XT_SOCKET_HAVE_CONNTRACK
1240+ /* Do the lookup with the original socket address in case this is a
1241+ * reply packet of an established SNAT-ted connection. */
1242+ ct = nf_ct_get(skb, &ctinfo);
1243+ if (ct && (ct != &nf_conntrack_untracked) &&
1244+ (ctinfo == IP_CT_IS_REPLY + IP_CT_ESTABLISHED) &&
1245+ (ct->status & IPS_SRC_NAT_DONE)) {
1246+ daddr = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
1247+ dport = (iph->protocol == IPPROTO_TCP) ?
1248+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.tcp.port :
1249+ ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
1250+ }
1251+#endif
1252+
9fc9ba83 1253+ sk = nf_tproxy_get_sock_v4(skb->dev->nd_net, iph->protocol,
2d1341b2 1254+ iph->saddr, daddr,
1255+ hp->source, dport, in, false);
1256+ if (sk != NULL) {
1257+ bool wildcard = (inet_sk(sk)->rcv_saddr == 0);
1258+
1259+ nf_tproxy_put_sock(sk);
1260+ if (wildcard)
1261+ sk = NULL;
1262+ }
1263+
1264+ pr_debug("socket match: proto %u %08x:%u -> %08x:%u (orig %08x:%u) sock %p\n",
1265+ iph->protocol, ntohl(iph->saddr), ntohs(hp->source),
1266+ ntohl(daddr), ntohs(dport),
1267+ ntohl(iph->daddr), ntohs(hp->dest), sk);
1268+
1269+ return (sk != NULL);
1270+}
1271+
1272+static bool
1273+socket_mt_check(const char *tablename,
1274+ const void *entry,
1275+ const struct xt_match *match,
1276+ void *matchinfo,
1277+ unsigned int hook_mask)
1278+{
1279+ const struct ipt_ip *i = entry;
1280+
1281+ if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)
1282+ && !(i->invflags & IPT_INV_PROTO))
1283+ return true;
1284+
1285+ pr_info("xt_socket: Can be used only in combination with "
1286+ "either -p tcp or -p udp\n");
1287+ return false;
1288+}
1289+
1290+static struct xt_match socket_mt_reg __read_mostly = {
1291+ .name = "socket",
1292+ .family = AF_INET,
1293+ .match = socket_mt,
1294+ .checkentry = socket_mt_check,
1295+ .hooks = 1 << NF_INET_PRE_ROUTING,
1296+ .me = THIS_MODULE,
1297+};
1298+
1299+static int __init socket_mt_init(void)
1300+{
1301+ nf_defrag_ipv4_enable();
1302+ return xt_register_match(&socket_mt_reg);
1303+}
1304+
1305+static void __exit socket_mt_exit(void)
1306+{
1307+ xt_unregister_match(&socket_mt_reg);
1308+}
1309+
1310+module_init(socket_mt_init);
1311+module_exit(socket_mt_exit);
1312+
1313+MODULE_LICENSE("GPL");
1314+MODULE_AUTHOR("Krisztian Kovacs");
1315+MODULE_DESCRIPTION("x_tables socket match module");
1316+MODULE_ALIAS("ipt_socket");
1317--
13181.5.2.5
1319
1320From cb15c50f3d6419fec98bc309b5e4ea31b665cb8d Mon Sep 17 00:00:00 2001
1321From: KOVACS Krisztian <hidden@sch.bme.hu>
1322Date: Mon, 28 Apr 2008 14:46:52 +0200
1323Subject: [PATCH] iptables TPROXY target
1324
1325The TPROXY target implements redirection of non-local TCP/UDP traffic to local
1326sockets. Additionally, it's possible to manipulate the packet mark if and only
1327if a socket has been found. (We need this because we cannot use multiple
1328targets in the same iptables rule.)
1329
1330Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
1331Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
1332---
1333 include/linux/netfilter/xt_TPROXY.h | 14 ++++
1334 net/netfilter/Kconfig | 15 +++++
1335 net/netfilter/Makefile | 1 +
1336 net/netfilter/xt_TPROXY.c | 112 +++++++++++++++++++++++++++++++++++
1337 4 files changed, 142 insertions(+), 0 deletions(-)
1338
1339diff --git a/include/linux/netfilter/xt_TPROXY.h b/include/linux/netfilter/xt_TPROXY.h
1340new file mode 100644
1341index 0000000..152e8f9
1342--- /dev/null
1343+++ b/include/linux/netfilter/xt_TPROXY.h
1344@@ -0,0 +1,14 @@
1345+#ifndef _XT_TPROXY_H_target
1346+#define _XT_TPROXY_H_target
1347+
1348+/* TPROXY target is capable of marking the packet to perform
1349+ * redirection. We can get rid of that whenever we get support for
1350+ * mutliple targets in the same rule. */
1351+struct xt_tproxy_target_info {
1352+ u_int32_t mark_mask;
1353+ u_int32_t mark_value;
1354+ __be32 laddr;
1355+ __be16 lport;
1356+};
1357+
1358+#endif /* _XT_TPROXY_H_target */
1359diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
1360index ce21278..d36018d 100644
1361--- a/net/netfilter/Kconfig
1362+++ b/net/netfilter/Kconfig
1363@@ -411,6 +411,21 @@ config NETFILTER_XT_TARGET_RATEEST
1364
1365 To compile it as a module, choose M here. If unsure, say N.
1366
1367+config NETFILTER_XT_TARGET_TPROXY
1368+ tristate '"TPROXY" target support (EXPERIMENTAL)'
1369+ depends on EXPERIMENTAL
1370+ depends on NETFILTER_TPROXY
1371+ depends on NETFILTER_XTABLES
1372+ depends on NETFILTER_ADVANCED
1373+ select NF_DEFRAG_IPV4
1374+ help
1375+ This option adds a `TPROXY' target, which is somewhat similar to
1376+ REDIRECT. It can only be used in the mangle table and is useful
1377+ to redirect traffic to a transparent proxy. It does _not_ depend
1378+ on Netfilter connection tracking and NAT, unlike REDIRECT.
1379+
1380+ To compile it as a module, choose M here. If unsure, say N.
1381+
1382 config NETFILTER_XT_TARGET_TRACE
1383 tristate '"TRACE" target support'
1384 depends on NETFILTER_XTABLES
1385diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
1386index 6d2eee6..04844d0 100644
1387--- a/net/netfilter/Makefile
1388+++ b/net/netfilter/Makefile
1389@@ -51,6 +51,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
1390 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
1391 obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o
1392 obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
1393+obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o
1394 obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
1395 obj-$(CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP) += xt_TCPOPTSTRIP.o
1396 obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
1397diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
1398new file mode 100644
1399index 0000000..183f251
1400--- /dev/null
1401+++ b/net/netfilter/xt_TPROXY.c
1402@@ -0,0 +1,112 @@
1403+/*
1404+ * Transparent proxy support for Linux/iptables
1405+ *
1406+ * Copyright (c) 2006-2007 BalaBit IT Ltd.
1407+ * Author: Balazs Scheidler, Krisztian Kovacs
1408+ *
1409+ * This program is free software; you can redistribute it and/or modify
1410+ * it under the terms of the GNU General Public License version 2 as
1411+ * published by the Free Software Foundation.
1412+ *
1413+ */
1414+
1415+#include <linux/module.h>
1416+#include <linux/skbuff.h>
1417+#include <linux/ip.h>
1418+#include <net/checksum.h>
1419+#include <net/udp.h>
1420+#include <net/inet_sock.h>
1421+
1422+#include <linux/netfilter/x_tables.h>
1423+#include <linux/netfilter_ipv4/ip_tables.h>
1424+#include <linux/netfilter/xt_TPROXY.h>
1425+
1426+#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
1427+#include <net/netfilter/nf_tproxy_core.h>
1428+
1429+static unsigned int
1430+tproxy_tg(struct sk_buff *skb,
1431+ const struct net_device *in,
1432+ const struct net_device *out,
1433+ unsigned int hooknum,
1434+ const struct xt_target *target,
1435+ const void *targinfo)
1436+{
1437+ const struct iphdr *iph = ip_hdr(skb);
1438+ const struct xt_tproxy_target_info *tgi = targinfo;
1439+ struct udphdr _hdr, *hp;
1440+ struct sock *sk;
1441+
1442+ hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr);
1443+ if (hp == NULL)
1444+ return NF_DROP;
1445+
9fc9ba83 1446+ sk = nf_tproxy_get_sock_v4(skb->dev->nd_net, iph->protocol,
2d1341b2 1447+ iph->saddr, tgi->laddr ? tgi->laddr : iph->daddr,
1448+ hp->source, tgi->lport ? tgi->lport : hp->dest,
1449+ in, true);
1450+
1451+ /* NOTE: assign_sock consumes our sk reference */
1452+ if (sk && nf_tproxy_assign_sock(skb, sk)) {
1453+ /* This should be in a separate target, but we don't do multiple
1454+ targets on the same rule yet */
1455+ skb->mark = (skb->mark & ~tgi->mark_mask) ^ tgi->mark_value;
1456+
1457+ pr_debug("redirecting: proto %u %08x:%u -> %08x:%u, mark: %x\n",
1458+ iph->protocol, ntohl(iph->daddr), ntohs(hp->dest),
1459+ ntohl(tgi->laddr), ntohs(tgi->lport), skb->mark);
1460+ return NF_ACCEPT;
1461+ }
1462+
1463+ pr_debug("no socket, dropping: proto %u %08x:%u -> %08x:%u, mark: %x\n",
1464+ iph->protocol, ntohl(iph->daddr), ntohs(hp->dest),
1465+ ntohl(tgi->laddr), ntohs(tgi->lport), skb->mark);
1466+ return NF_DROP;
1467+}
1468+
1469+static bool
1470+tproxy_tg_check(const char *tablename,
1471+ const void *entry,
1472+ const struct xt_target *target,
1473+ void *targetinfo,
1474+ unsigned int hook_mask)
1475+{
1476+ const struct ipt_ip *i = entry;
1477+
1478+ if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)
1479+ && !(i->invflags & IPT_INV_PROTO))
1480+ return true;
1481+
1482+ pr_info("xt_TPROXY: Can be used only in combination with "
1483+ "either -p tcp or -p udp\n");
1484+ return false;
1485+}
1486+
1487+static struct xt_target tproxy_tg_reg __read_mostly = {
1488+ .name = "TPROXY",
1489+ .family = AF_INET,
1490+ .table = "mangle",
1491+ .target = tproxy_tg,
1492+ .targetsize = sizeof(struct xt_tproxy_target_info),
1493+ .checkentry = tproxy_tg_check,
1494+ .hooks = 1 << NF_INET_PRE_ROUTING,
1495+ .me = THIS_MODULE,
1496+};
1497+
1498+static int __init tproxy_tg_init(void)
1499+{
1500+ nf_defrag_ipv4_enable();
1501+ return xt_register_target(&tproxy_tg_reg);
1502+}
1503+
1504+static void __exit tproxy_tg_exit(void)
1505+{
1506+ xt_unregister_target(&tproxy_tg_reg);
1507+}
1508+
1509+module_init(tproxy_tg_init);
1510+module_exit(tproxy_tg_exit);
1511+MODULE_LICENSE("GPL");
1512+MODULE_AUTHOR("Krisztian Kovacs");
1513+MODULE_DESCRIPTION("Netfilter transparent proxy (TPROXY) target module.");
1514+MODULE_ALIAS("ipt_TPROXY");
1515--
15161.5.2.5
1517
1518From 1ba926a05e2c25585f15e7c9f895557e6a48407f Mon Sep 17 00:00:00 2001
1519From: KOVACS Krisztian <hidden@sch.bme.hu>
1520Date: Mon, 28 Apr 2008 14:46:53 +0200
1521Subject: [PATCH] Don't lookup the socket if there's a socket attached to the skb
1522
1523Use the socket cached in the TPROXY target if it's present.
1524
1525Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
1526---
1527 net/ipv4/tcp_ipv4.c | 9 +++++++++
1528 1 files changed, 9 insertions(+), 0 deletions(-)
1529
1530diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
1531index 58873ad..8937675 100644
1532--- a/net/ipv4/tcp_ipv4.c
1533+++ b/net/ipv4/tcp_ipv4.c
dc278809 1534@@ -1643,6 +1643,15 @@
2d1341b2 1535 TCP_SKB_CB(skb)->flags = iph->tos;
1536 TCP_SKB_CB(skb)->sacked = 0;
1537
1538+#if defined(CONFIG_NETFILTER_TPROXY) || defined(CONFIG_NETFILTER_TPROXY_MODULE)
1539+ if (unlikely(skb->sk)) {
1540+ /* steal reference */
1541+ sk = skb->sk;
1542+ skb->destructor = NULL;
1543+ skb->sk = NULL;
1544+ } else
1545+#endif
2d1341b2 1546+
dc278809
PS
1547 sk = __inet_lookup(dev_net(skb->dev), &tcp_hashinfo, iph->saddr,
1548 th->source, iph->daddr, th->dest, inet_iif(skb));
2d1341b2 1549 if (!sk)
2d1341b2 1550--
15511.5.2.5
1552
1553From 8b291305fd4891a92118cf358666f25a0e42ca00 Mon Sep 17 00:00:00 2001
1554From: KOVACS Krisztian <hidden@sch.bme.hu>
1555Date: Mon, 28 Apr 2008 14:46:53 +0200
1556Subject: [PATCH] Don't lookup the socket if there's a socket attached to the skb
1557
1558Use the socket cached in the TPROXY target if it's present.
1559
1560Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
1561---
1562 net/ipv4/udp.c | 16 ++++++++++++++++
1563 1 files changed, 16 insertions(+), 0 deletions(-)
1564
1565diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
1566index 672d0d4..c29597c 100644
1567--- a/net/ipv4/udp.c
1568+++ b/net/ipv4/udp.c
dc278809 1569@@ -365,6 +365,14 @@
2d1341b2 1570 int harderr;
1571 int err;
1572
1573+#if defined(CONFIG_NETFILTER_TPROXY) || defined(CONFIG_NETFILTER_TPROXY_MODULE)
1574+ if (unlikely(skb->sk)) {
1575+ /* steal reference */
1576+ sk = skb->sk;
1577+ skb->destructor = NULL;
1578+ skb->sk = NULL;
1579+ } else
1580+#endif
dc278809 1581 sk = __udp4_lib_lookup(dev_net(skb->dev), iph->daddr, uh->dest,
2d1341b2 1582 iph->saddr, uh->source, skb->dev->ifindex, udptable);
1583 if (sk == NULL) {
dc278809 1584@@ -1199,6 +1207,14 @@
2d1341b2 1585 if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
1586 return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
1587
1588+#if defined(CONFIG_NETFILTER_TPROXY) || defined(CONFIG_NETFILTER_TPROXY_MODULE)
1589+ if (unlikely(skb->sk)) {
1590+ /* steal reference */
1591+ sk = skb->sk;
1592+ skb->destructor = NULL;
1593+ skb->sk = NULL;
1594+ } else
1595+#endif
dc278809 1596 sk = __udp4_lib_lookup(dev_net(skb->dev), saddr, uh->source, daddr,
2d1341b2 1597 uh->dest, inet_iif(skb), udptable);
1598
1599--
16001.5.2.5
1601
1602From 6e33de49987ecc73930148c88f07f61527929dcc Mon Sep 17 00:00:00 2001
1603From: KOVACS Krisztian <hidden@sch.bme.hu>
1604Date: Mon, 28 Apr 2008 14:46:53 +0200
1605Subject: [PATCH] Add documentation
1606
1607Add basic usage instructions to Documentation/networking.
1608
1609Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
1610---
1611 Documentation/networking/tproxy.txt | 62 +++++++++++++++++++++++++++++++++++
1612 1 files changed, 62 insertions(+), 0 deletions(-)
1613
1614diff --git a/Documentation/networking/tproxy.txt b/Documentation/networking/tproxy.txt
1615new file mode 100644
1616index 0000000..dfcb613
1617--- /dev/null
1618+++ b/Documentation/networking/tproxy.txt
1619@@ -0,0 +1,62 @@
1620+Transparent proxy support
1621+=========================
1622+
1623+This feature adds Linux 2.2-like transparent proxy support to current kernels.
1624+To use it, enable NETFILTER_TPROXY, the socket match and the TPROXY target in
1625+your kernel config. You will need policy routing too, so be sure to enable that
1626+as well.
1627+
1628+1. Making non-local sockets work
1629+================================
1630+
1631+The idea is that you identify packets with destination address matching a local
1632+socket your box, set the packet mark to a certain value, and then match on that
1633+value using policy routing to have those packets delivered locally:
1634+
1635+# iptables -t mangle -N DIVERT
1636+# iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
1637+# iptables -t mangle -A DIVERT -j MARK --set-mark 1
1638+# iptables -t mangle -A DIVERT -j ACCEPT
1639+
1640+# ip rule add fwmark 1 lookup 100
1641+# ip route add local 0.0.0.0/0 dev lo table 100
1642+
1643+Because of certain restrictions in the IPv4 routing output code you'll have to
1644+modify your application to allow it sending datagrams _from_ non-local IP
1645+addresses. All you have to do is to enable the (SOL_IP, IP_TRANSPARENT) socket
1646+option before calling bind:
1647+
1648+fd = socket(AF_INET, SOCK_STREAM, 0);
1649+/* - 8< -*/
1650+int value = 1;
1651+setsockopt(fd, SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
1652+/* - 8< -*/
1653+name.sin_family = AF_INET;
1654+name.sin_port = htons(0xCAFE);
1655+name.sin_addr.s_addr = htonl(0xDEADBEEF);
1656+bind(fd, &name, sizeof(name));
1657+
1658+A trivial patch for netcat is available here:
1659+http://people.netfilter.org/hidden/tproxy/netcat-ip_transparent-support.patch
1660+
1661+
1662+2. Redirecting traffic
1663+======================
1664+
1665+Transparent proxying often involves "intercepting" traffic on a router. This is
1666+usually done with the iptables REDIRECT target, however, there are serious
1667+limitations of that method. One of the major issues is that it actually
1668+modifies the packets to change the destination address -- which might not be
1669+acceptable in certain situations. (Think of proxying UDP for example: you won't
1670+be able to find out the original destination address. Even in case of TCP
1671+getting the original destination address is racy.)
1672+
1673+The 'TPROXY' target provides similar functionality without relying on NAT. Simply
1674+add rules like this to the iptables ruleset above:
1675+
1676+# iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY \
1677+ --tproxy-mark 0x1/0x1 --on-port 50080
1678+
1679+Note that for this to work you'll have to modify the proxy to enable (SOL_IP,
1680+IP_TRANSPARENT) for the listening socket.
1681+
1682--
16831.5.2.5
1684
This page took 0.235973 seconds and 4 git commands to generate.