]> git.pld-linux.org Git - packages/kernel.git/blob - kernel-tproxy.patch
- renamed to kernel-wrr.patch
[packages/kernel.git] / kernel-tproxy.patch
1 From f01a1b1a0cb61eaadebd9d910286c5f382a4928c Mon Sep 17 00:00:00 2001
2 From: KOVACS Krisztian <hidden@sch.bme.hu>
3 Date: Mon, 28 Apr 2008 14:46:46 +0200
4 Subject: [PATCH] Loosen source address check on IPv4 output
5
6 ip_route_output() contains a check to make sure that no flows with
7 non-local source IP addresses are routed. This obviously makes using
8 such addresses impossible.
9
10 This patch introduces a flowi flag which makes omitting this check
11 possible. The new flag provides a way of handling transparent and
12 non-transparent connections differently.
13
14 Signed-off-by: Julian Anastasov <ja@ssi.bg>
15 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
16 Acked-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
22 diff --git a/include/net/flow.h b/include/net/flow.h
23 index 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;
34 diff --git a/net/ipv4/route.c b/net/ipv4/route.c
35 index 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 -- 
81 1.5.2.5
82
83 From cc2f0afbffaad66b7794e4b4e5d50609f3571fbd Mon Sep 17 00:00:00 2001
84 From: KOVACS Krisztian <hidden@sch.bme.hu>
85 Date: Mon, 28 Apr 2008 14:46:48 +0200
86 Subject: [PATCH] Implement IP_TRANSPARENT socket option
87
88 This patch introduces the IP_TRANSPARENT socket option: enabling that will make
89 the IPv4 routing omit the non-local source address check on output. Setting
90 IP_TRANSPARENT requires NET_ADMIN capability.
91
92 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
93 Acked-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
102 diff --git a/include/linux/in.h b/include/linux/in.h
103 index 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
114 diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
115 index 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;
128 diff --git a/include/net/inet_timewait_sock.h b/include/net/inet_timewait_sock.h
129 index 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;
142 diff --git a/net/ipv4/inet_timewait_sock.c b/net/ipv4/inet_timewait_sock.c
143 index 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);
154 diff --git a/net/ipv4/ip_sockglue.c b/net/ipv4/ip_sockglue.c
155 index 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 -- 
185 1.5.2.5
186
187 From b0f9031d33741ccd7745112d425d465035444859 Mon Sep 17 00:00:00 2001
188 From: KOVACS Krisztian <hidden@sch.bme.hu>
189 Date: Mon, 28 Apr 2008 14:46:48 +0200
190 Subject: [PATCH] Allow binding to non-local addresses if IP_TRANSPARENT is set
191 MIME-Version: 1.0
192 Content-Type: text/plain; charset=utf-8
193 Content-Transfer-Encoding: 8bit
194
195 Setting IP_TRANSPARENT is not really useful without allowing non-local
196 binds for the socket. To make user-space code simpler we allow these binds
197 even if IP_TRANSPARENT is set but IP_FREEBIND is not.
198
199 Signed-off-by: Tóth László Attila <panther@balabit.hu>
200 Acked-by: Patrick McHardy <kaber@trash.net>
201 ---
202  net/ipv4/af_inet.c |    2 +-
203  1 files changed, 1 insertions(+), 1 deletions(-)
204
205 diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
206 index 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) &&
215             nsa.saddr != htonl(INADDR_ANY) &&
216             chk_addr_ret != RTN_LOCAL &&
217             chk_addr_ret != RTN_MULTICAST &&
218 -- 
219 1.5.2.5
220
221 From 2b3cf4f3e3aa34ff42d17b202b945db2c5c563b2 Mon Sep 17 00:00:00 2001
222 From: KOVACS Krisztian <hidden@sch.bme.hu>
223 Date: Mon, 28 Apr 2008 14:46:49 +0200
224 Subject: [PATCH] Make inet_sock.h independent of route.h
225
226 inet_iif() in inet_sock.h requires route.h. Since users of inet_iif()
227 usually require other route.h functionality anyway this patch moves
228 inet_iif() to route.h.
229
230 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
231 ---
232  include/net/inet_sock.h            |    7 ------- VSERVER patch removed this!
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
239 VSERVER patch has own (almost identical) implementation of this.
240 -- 
241 1.5.2.5
242
243 From 03bf9d04e8a6d0dc994363c8133ff494226701ef Mon Sep 17 00:00:00 2001
244 From: KOVACS Krisztian <hidden@sch.bme.hu>
245 Date: Mon, 28 Apr 2008 14:46:50 +0200
246 Subject: [PATCH] Conditionally enable transparent flow flag when connecting
247
248 Set FLOWI_FLAG_ANYSRC in flowi->flags if the socket has the
249 transparent socket option set. This way we selectively enable certain
250 connections with non-local source addresses to be routed.
251
252 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
253 ---
254  include/net/route.h |    6 +++++-
255  1 files changed, 5 insertions(+), 1 deletions(-)
256
257 diff --git a/include/net/route.h b/include/net/route.h
258 index 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>
267  #include <linux/in_route.h>
268  #include <linux/rtnetlink.h>
269  #include <linux/route.h>
270 @@ -161,6 +161,9 @@ static inline int ip_route_connect(struct rtable **rp, __be32 dst,
271         int err;
272         struct net *net = sock_net(sk);
273         struct nx_info *nx_info = current->nx_info;
274 +
275 +       if (inet_sk(sk)->transparent)
276 +               fl.flags |= FLOWI_FLAG_ANYSRC;
277  
278         if (sk)
279                 nx_info = sk->sk_nx_info;
280 -- 
281 1.5.2.5
282
283 From 181680c6c0df4335bd8eeeafe06ea12e6918c3b7 Mon Sep 17 00:00:00 2001
284 From: KOVACS Krisztian <hidden@sch.bme.hu>
285 Date: Mon, 28 Apr 2008 14:46:50 +0200
286 Subject: [PATCH] Handle TCP SYN+ACK/ACK/RST transparency
287
288 The TCP stack sends out SYN+ACK/ACK/RST reply packets in response to
289 incoming packets. The non-local source address check on output bites
290 us again, as replies for transparently redirected traffic won't have a
291 chance to leave the node.
292
293 This patch selectively sets the FLOWI_FLAG_ANYSRC flag when doing
294 the route lookup for those replies. Transparent replies are enabled if
295 the listening socket has the transparent socket flag set.
296
297 Signed-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
307 diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
308 index 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 */
331 diff --git a/include/net/ip.h b/include/net/ip.h
332 index 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  
364 diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
365 index 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 } } };
376 diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
377 index 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;
398 diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
399 index 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 } } };
410 diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
411 index 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  
420         ip_send_reply(skb->dst->dev->nd_net->ipv4.tcp_sock, skb,
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 -- 
468 1.5.2.5
469
470 From f8be7a55d2a449d188f033d7914d2af007054fbc Mon Sep 17 00:00:00 2001
471 From: KOVACS Krisztian <hidden@sch.bme.hu>
472 Date: Mon, 28 Apr 2008 14:46:50 +0200
473 Subject: [PATCH] Make Netfilter's ip_route_me_harder() non-local address compatible
474
475 Netfilter's ip_route_me_harder() tries to re-route packets either generated or
476 re-routed by Netfilter. This patch changes ip_route_me_harder() to handle
477 packets from non-locally-bound sockets with IP_TRANSPARENT set as local and to
478 set the appropriate flowi flags when re-doing the routing lookup.
479
480 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
481 ---
482  net/ipv4/netfilter.c |    3 +++
483  1 files changed, 3 insertions(+), 0 deletions(-)
484
485 diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
486 index 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 -- 
507 1.5.2.5
508
509 From 7797a39b59dae015e06bd4860affbdb250c312b7 Mon Sep 17 00:00:00 2001
510 From: KOVACS Krisztian <hidden@sch.bme.hu>
511 Date: Mon, 28 Apr 2008 14:46:50 +0200
512 Subject: [PATCH] Port redirection support for TCP
513
514 Current TCP code relies on the local port of the listening socket
515 being the same as the destination address of the incoming
516 connection. Port redirection used by many transparent proxying
517 techniques obviously breaks this, so we have to store the original
518 destination port address.
519
520 This patch extends struct inet_request_sock and stores the incoming
521 destination port value there. It also modifies the handshake code to
522 use that value as the source port when sending reply packets.
523
524 Signed-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
533 diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
534 index 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;
547 diff --git a/include/net/tcp.h b/include/net/tcp.h
548 index 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);
559 diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
560 index 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;
572 diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
573 index 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;
584 diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
585 index 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 -- 
598 1.5.2.5
599
600 From 4feb1a188b6bd0ff8cab5c8d817fbfc7d7788802 Mon Sep 17 00:00:00 2001
601 From: KOVACS Krisztian <hidden@sch.bme.hu>
602 Date: Mon, 28 Apr 2008 14:46:51 +0200
603 Subject: [PATCH] Export UDP socket lookup function
604
605 The iptables tproxy code has to be able to do UDP socket hash lookups,
606 so we have to provide an exported lookup function for this purpose.
607
608 Signed-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
614 diff --git a/include/net/udp.h b/include/net/udp.h
615 index 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  
629 diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
630 index 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 -- 
648 1.5.2.5
649
650 From d49cee38069417f3cb83ca67baa65a2034d2d2ce Mon Sep 17 00:00:00 2001
651 From: KOVACS Krisztian <hidden@sch.bme.hu>
652 Date: Mon, 28 Apr 2008 14:46:51 +0200
653 Subject: [PATCH] Split Netfilter IPv4 defragmentation into a separate module
654
655 Netfilter connection tracking requires all IPv4 packets to be defragmented.
656 Both the socket match and the TPROXY target depend on this functionality, so
657 this patch separates the Netfilter IPv4 defrag hooks into a separate module.
658
659 Signed-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
668 diff --git a/include/net/netfilter/ipv4/nf_defrag_ipv4.h b/include/net/netfilter/ipv4/nf_defrag_ipv4.h
669 new file mode 100644
670 index 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 */
680 diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
681 index 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
700 diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
701 index 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
714 diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
715 index 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   *
723 @@ -24,6 +25,7 @@
724  #include <net/netfilter/nf_conntrack_l3proto.h>
725  #include <net/netfilter/nf_conntrack_core.h>
726  #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
727 +#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
728  
729  int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
730                               struct nf_conn *ct,
731 @@ -63,23 +65,6 @@ static int ipv4_print_tuple(struct seq_file *s,
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  {
755 @@ -144,28 +129,6 @@ out:
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,
784 @@ -195,13 +158,6 @@ static unsigned int ipv4_conntrack_local(unsigned int hooknum,
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,
798 @@ -209,13 +165,6 @@ static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
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,
812 @@ -422,6 +371,7 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
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) {
820 diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
821 new file mode 100644
822 index 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 -- 
923 1.5.2.5
924
925 From 40b01b3ada99906bb5818e15cddfe49344d09fd9 Mon Sep 17 00:00:00 2001
926 From: KOVACS Krisztian <hidden@sch.bme.hu>
927 Date: Mon, 28 Apr 2008 14:46:51 +0200
928 Subject: [PATCH] iptables tproxy core
929
930 The iptables tproxy core is a module that contains the common routines used by
931 various tproxy related modules (TPROXY target and socket match)
932
933 Signed-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
941 diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h
942 new file mode 100644
943 index 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
979 diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
980 index 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
1005 diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
1006 index 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  
1019 diff --git a/net/netfilter/nf_tproxy_core.c b/net/netfilter/nf_tproxy_core.c
1020 new file mode 100644
1021 index 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 -- 
1122 1.5.2.5
1123
1124 From 7962977079ac28db798ab5b11ee31df6566fb472 Mon Sep 17 00:00:00 2001
1125 From: KOVACS Krisztian <hidden@sch.bme.hu>
1126 Date: Mon, 28 Apr 2008 14:46:52 +0200
1127 Subject: [PATCH] iptables socket match
1128
1129 Add iptables 'socket' match, which matches packets for which a TCP/UDP
1130 socket lookup succeeds.
1131
1132 Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
1133 Signed-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
1140 diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
1141 index 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
1166 diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
1167 index 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
1178 diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
1179 new file mode 100644
1180 index 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 +
1253 +       sk = nf_tproxy_get_sock_v4(skb->dev->nd_net, iph->protocol,
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 -- 
1318 1.5.2.5
1319
1320 From cb15c50f3d6419fec98bc309b5e4ea31b665cb8d Mon Sep 17 00:00:00 2001
1321 From: KOVACS Krisztian <hidden@sch.bme.hu>
1322 Date: Mon, 28 Apr 2008 14:46:52 +0200
1323 Subject: [PATCH] iptables TPROXY target
1324
1325 The TPROXY target implements redirection of non-local TCP/UDP traffic to local
1326 sockets. Additionally, it's possible to manipulate the packet mark if and only
1327 if a socket has been found. (We need this because we cannot use multiple
1328 targets in the same iptables rule.)
1329
1330 Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
1331 Signed-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
1339 diff --git a/include/linux/netfilter/xt_TPROXY.h b/include/linux/netfilter/xt_TPROXY.h
1340 new file mode 100644
1341 index 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 */
1359 diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
1360 index 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
1385 diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
1386 index 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
1397 diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
1398 new file mode 100644
1399 index 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 +
1446 +       sk = nf_tproxy_get_sock_v4(skb->dev->nd_net, iph->protocol,
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 -- 
1516 1.5.2.5
1517
1518 From 1ba926a05e2c25585f15e7c9f895557e6a48407f Mon Sep 17 00:00:00 2001
1519 From: KOVACS Krisztian <hidden@sch.bme.hu>
1520 Date: Mon, 28 Apr 2008 14:46:53 +0200
1521 Subject: [PATCH] Don't lookup the socket if there's a socket attached to the skb
1522
1523 Use the socket cached in the TPROXY target if it's present.
1524
1525 Signed-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
1530 diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
1531 index 58873ad..8937675 100644
1532 --- a/net/ipv4/tcp_ipv4.c
1533 +++ b/net/ipv4/tcp_ipv4.c
1534 @@ -1647,8 +1647,17 @@ int tcp_v4_rcv(struct sk_buff *skb)
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
1546         sk = __inet_lookup(skb->dev->nd_net, &tcp_hashinfo, iph->saddr,
1547                         th->source, iph->daddr, th->dest, inet_iif(skb));
1548 +
1549         if (!sk)
1550                 goto no_tcp_socket;
1551  
1552 -- 
1553 1.5.2.5
1554
1555 From 8b291305fd4891a92118cf358666f25a0e42ca00 Mon Sep 17 00:00:00 2001
1556 From: KOVACS Krisztian <hidden@sch.bme.hu>
1557 Date: Mon, 28 Apr 2008 14:46:53 +0200
1558 Subject: [PATCH] Don't lookup the socket if there's a socket attached to the skb
1559
1560 Use the socket cached in the TPROXY target if it's present.
1561
1562 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
1563 ---
1564  net/ipv4/udp.c |   16 ++++++++++++++++
1565  1 files changed, 16 insertions(+), 0 deletions(-)
1566
1567 diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
1568 index 672d0d4..c29597c 100644
1569 --- a/net/ipv4/udp.c
1570 +++ b/net/ipv4/udp.c
1571 @@ -364,6 +364,14 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[])
1572         int harderr;
1573         int err;
1574  
1575 +#if defined(CONFIG_NETFILTER_TPROXY) || defined(CONFIG_NETFILTER_TPROXY_MODULE)
1576 +       if (unlikely(skb->sk)) {
1577 +               /* steal reference */
1578 +               sk = skb->sk;
1579 +               skb->destructor = NULL;
1580 +               skb->sk = NULL;
1581 +       } else
1582 +#endif
1583         sk = __udp4_lib_lookup(skb->dev->nd_net, iph->daddr, uh->dest,
1584                         iph->saddr, uh->source, skb->dev->ifindex, udptable);
1585         if (sk == NULL) {
1586 @@ -1188,6 +1196,14 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
1587         if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
1588                 return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
1589  
1590 +#if defined(CONFIG_NETFILTER_TPROXY) || defined(CONFIG_NETFILTER_TPROXY_MODULE)
1591 +       if (unlikely(skb->sk)) {
1592 +               /* steal reference */
1593 +               sk = skb->sk;
1594 +               skb->destructor = NULL;
1595 +               skb->sk = NULL;
1596 +       } else
1597 +#endif
1598         sk = __udp4_lib_lookup(skb->dev->nd_net, saddr, uh->source, daddr,
1599                         uh->dest, inet_iif(skb), udptable);
1600  
1601 -- 
1602 1.5.2.5
1603
1604 From 6e33de49987ecc73930148c88f07f61527929dcc Mon Sep 17 00:00:00 2001
1605 From: KOVACS Krisztian <hidden@sch.bme.hu>
1606 Date: Mon, 28 Apr 2008 14:46:53 +0200
1607 Subject: [PATCH] Add documentation
1608
1609 Add basic usage instructions to Documentation/networking.
1610
1611 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
1612 ---
1613  Documentation/networking/tproxy.txt |   62 +++++++++++++++++++++++++++++++++++
1614  1 files changed, 62 insertions(+), 0 deletions(-)
1615
1616 diff --git a/Documentation/networking/tproxy.txt b/Documentation/networking/tproxy.txt
1617 new file mode 100644
1618 index 0000000..dfcb613
1619 --- /dev/null
1620 +++ b/Documentation/networking/tproxy.txt
1621 @@ -0,0 +1,62 @@
1622 +Transparent proxy support
1623 +=========================
1624 +
1625 +This feature adds Linux 2.2-like transparent proxy support to current kernels.
1626 +To use it, enable NETFILTER_TPROXY, the socket match and the TPROXY target in
1627 +your kernel config. You will need policy routing too, so be sure to enable that
1628 +as well.
1629 +
1630 +1. Making non-local sockets work
1631 +================================
1632 +
1633 +The idea is that you identify packets with destination address matching a local
1634 +socket your box, set the packet mark to a certain value, and then match on that
1635 +value using policy routing to have those packets delivered locally:
1636 +
1637 +# iptables -t mangle -N DIVERT
1638 +# iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
1639 +# iptables -t mangle -A DIVERT -j MARK --set-mark 1
1640 +# iptables -t mangle -A DIVERT -j ACCEPT
1641 +
1642 +# ip rule add fwmark 1 lookup 100
1643 +# ip route add local 0.0.0.0/0 dev lo table 100
1644 +
1645 +Because of certain restrictions in the IPv4 routing output code you'll have to
1646 +modify your application to allow it sending datagrams _from_ non-local IP
1647 +addresses. All you have to do is to enable the (SOL_IP, IP_TRANSPARENT) socket
1648 +option before calling bind:
1649 +
1650 +fd = socket(AF_INET, SOCK_STREAM, 0);
1651 +/* - 8< -*/
1652 +int value = 1;
1653 +setsockopt(fd, SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
1654 +/* - 8< -*/
1655 +name.sin_family = AF_INET;
1656 +name.sin_port = htons(0xCAFE);
1657 +name.sin_addr.s_addr = htonl(0xDEADBEEF);
1658 +bind(fd, &name, sizeof(name));
1659 +
1660 +A trivial patch for netcat is available here:
1661 +http://people.netfilter.org/hidden/tproxy/netcat-ip_transparent-support.patch
1662 +
1663 +
1664 +2. Redirecting traffic
1665 +======================
1666 +
1667 +Transparent proxying often involves "intercepting" traffic on a router. This is
1668 +usually done with the iptables REDIRECT target, however, there are serious
1669 +limitations of that method. One of the major issues is that it actually
1670 +modifies the packets to change the destination address -- which might not be
1671 +acceptable in certain situations. (Think of proxying UDP for example: you won't
1672 +be able to find out the original destination address. Even in case of TCP
1673 +getting the original destination address is racy.)
1674 +
1675 +The 'TPROXY' target provides similar functionality without relying on NAT. Simply
1676 +add rules like this to the iptables ruleset above:
1677 +
1678 +# iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY \
1679 +  --tproxy-mark 0x1/0x1 --on-port 50080
1680 +
1681 +Note that for this to work you'll have to modify the proxy to enable (SOL_IP,
1682 +IP_TRANSPARENT) for the listening socket.
1683 +
1684 -- 
1685 1.5.2.5
1686
This page took 0.141713 seconds and 3 git commands to generate.