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
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.
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.
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>
18 include/net/flow.h | 1 +
19 net/ipv4/route.c | 20 +++++++++++++-------
20 2 files changed, 14 insertions(+), 7 deletions(-)
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 {
30 +#define FLOWI_FLAG_ANYSRC 0x01
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))
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)
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,
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)
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;
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)
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
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.
92 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
93 Acked-by: Patrick McHardy <kaber@trash.net>
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(-)
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
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 {
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 {
135 /* And these are ours. */
136 - __u8 tw_ipv6only:1;
137 + __u8 tw_ipv6only: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;
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);
171 + case IP_TRANSPARENT:
172 + if (!capable(CAP_NET_ADMIN)) {
178 + inet->transparent = !!val;
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
192 Content-Type: text/plain; charset=utf-8
193 Content-Transfer-Encoding: 8bit
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.
199 Signed-off-by: Tóth László Attila <panther@balabit.hu>
200 Acked-by: Patrick McHardy <kaber@trash.net>
202 net/ipv4/af_inet.c | 2 +-
203 1 files changed, 1 insertions(+), 1 deletions(-)
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)
211 err = -EADDRNOTAVAIL;
212 if (!sysctl_ip_nonlocal_bind &&
214 + !(inet->freebind || inet->transparent) &&
215 nsa.saddr != htonl(INADDR_ANY) &&
216 chk_addr_ret != RTN_LOCAL &&
217 chk_addr_ret != RTN_MULTICAST &&
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
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.
230 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
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(-)
239 VSERVER patch has own (almost identical) implementation of this.
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
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.
252 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
254 include/net/route.h | 6 +++++-
255 1 files changed, 5 insertions(+), 1 deletions(-)
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
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,
272 struct net *net = sock_net(sk);
273 struct nx_info *nx_info = current->nx_info;
275 + if (inet_sk(sk)->transparent)
276 + fl.flags |= FLOWI_FLAG_ANYSRC;
279 nx_info = sk->sk_nx_info;
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
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.
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.
297 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
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(-)
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 {
318 struct ip_options *opt;
321 @@ -191,4 +192,9 @@ static inline int inet_sk_ehashfn(const struct sock *sk)
322 return inet_ehashfn(laddr, lport, faddr, fport);
325 +static inline __u8 inet_sk_flowi_flags(const struct sock *sk)
327 + return inet_sk(sk)->transparent ? FLOWI_FLAG_ANYSRC : 0;
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
337 #include <net/inet_sock.h>
338 #include <net/snmp.h>
339 +#include <net/flow.h>
343 @@ -140,12 +141,20 @@ static inline void ip_tr_mc_map(__be32 addr, char *buf)
345 struct ip_reply_arg {
349 int csumoffset; /* u16 offset of csum in iov[0].iov_base */
350 /* -1 if not needed */
354 +#define IP_REPLY_ARG_NOSRCCHECK 1
356 +static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg)
358 + return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0;
361 void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg,
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),
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),
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
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))
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),
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;
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)
424 static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
425 struct sk_buff *skb, u32 seq, u32 ack,
427 + u32 win, u32 ts, int reply_flags)
429 struct tcphdr *th = tcp_hdr(skb);
431 @@ -684,6 +685,7 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
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)
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);
449 @@ -714,7 +717,8 @@ static void tcp_v4_reqsk_send_ack(struct sk_buff *skb,
451 tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1,
452 tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
455 + inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0);
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);
466 TCP_ECN_create_request(req, tcp_hdr(skb));
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
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.
480 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
482 net/ipv4/netfilter.c | 3 +++
483 1 files changed, 3 insertions(+), 0 deletions(-)
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)
492 type = inet_addr_type(&init_net, iph->saddr);
493 + if (skb->sk && inet_sk(skb->sk)->transparent)
495 if (addr_type == RTN_UNSPEC)
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;
502 + fl.flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0;
503 if (ip_route_output_key(&init_net, &rt, &fl) != 0)
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
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.
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.
524 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
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(-)
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 */
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,
554 ireq->rmt_port = tcp_hdr(skb)->source;
555 + ireq->loc_port = tcp_hdr(skb)->dest;
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;
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;
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;
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,
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)
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
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.
608 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
610 include/net/udp.h | 4 ++++
611 net/ipv4/udp.c | 7 +++++++
612 2 files changed, 11 insertions(+), 0 deletions(-)
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 *));
622 +extern struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
623 + __be32 daddr, __be16 dport,
626 DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
627 DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6);
629 diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
630 index 1f535e3..672d0d4 100644
633 @@ -307,6 +307,13 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
637 +struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
638 + __be32 daddr, __be16 dport, int dif)
640 + return __udp4_lib_lookup(net, saddr, sport, daddr, dport, dif, udp_hash);
642 +EXPORT_SYMBOL_GPL(udp4_lib_lookup);
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,
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
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.
659 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
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(-)
668 diff --git a/include/net/netfilter/ipv4/nf_defrag_ipv4.h b/include/net/netfilter/ipv4/nf_defrag_ipv4.h
670 index 0000000..6b00ea3
672 +++ b/include/net/netfilter/ipv4/nf_defrag_ipv4.h
674 +#ifndef _NF_DEFRAG_IPV4_H
675 +#define _NF_DEFRAG_IPV4_H
677 +extern void nf_defrag_ipv4_enable(void);
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
685 menu "IP: Netfilter Configuration"
686 depends on INET && NETFILTER
688 +config NF_DEFRAG_IPV4
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
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
706 obj-$(CONFIG_NF_NAT) += nf_nat.o
709 +obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o
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
720 /* (C) 1999-2001 Paul `Rusty' Russell
721 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
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>
729 int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
731 @@ -63,23 +65,6 @@ static int ipv4_print_tuple(struct seq_file *s,
732 NIPQUAD(tuple->dst.u3.ip));
735 -/* Returns new sk_buff, or NULL */
736 -static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
742 - local_bh_disable();
743 - err = ip_defrag(skb, user);
747 - ip_send_check(ip_hdr(skb));
752 static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
753 unsigned int *dataoff, u_int8_t *protonum)
755 @@ -144,28 +129,6 @@ out:
756 return nf_conntrack_confirm(skb);
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 *))
765 - /* Previously seen (loopback)? Ignore. Do this before
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))
781 static unsigned int ipv4_conntrack_in(unsigned int hooknum,
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 = {
788 - .hook = ipv4_conntrack_defrag,
789 - .owner = THIS_MODULE,
791 - .hooknum = NF_INET_PRE_ROUTING,
792 - .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
795 .hook = ipv4_conntrack_in,
796 .owner = THIS_MODULE,
798 @@ -209,13 +165,6 @@ static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
799 .priority = NF_IP_PRI_CONNTRACK,
802 - .hook = ipv4_conntrack_defrag,
803 - .owner = THIS_MODULE,
805 - .hooknum = NF_INET_LOCAL_OUT,
806 - .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
809 .hook = ipv4_conntrack_local,
810 .owner = THIS_MODULE,
812 @@ -422,6 +371,7 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
816 + nf_defrag_ipv4_enable();
818 ret = nf_register_sockopt(&so_getorigdst);
820 diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
822 index 0000000..aa2c50a
824 +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
826 +/* (C) 1999-2001 Paul `Rusty' Russell
827 + * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
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.
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>
842 +#include <linux/netfilter_ipv4.h>
843 +#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
845 +/* Returns new sk_buff, or NULL */
846 +static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
852 + local_bh_disable();
853 + err = ip_defrag(skb, user);
857 + ip_send_check(ip_hdr(skb));
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 *))
868 +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
869 + /* Previously seen (loopback)? Ignore. Do this before
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))
886 +static struct nf_hook_ops ipv4_defrag_ops[] = {
888 + .hook = ipv4_conntrack_defrag,
889 + .owner = THIS_MODULE,
891 + .hooknum = NF_INET_PRE_ROUTING,
892 + .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
895 + .hook = ipv4_conntrack_defrag,
896 + .owner = THIS_MODULE,
898 + .hooknum = NF_INET_LOCAL_OUT,
899 + .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
903 +static int __init nf_defrag_init(void)
905 + return nf_register_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));
908 +static void __exit nf_defrag_fini(void)
910 + nf_unregister_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));
913 +void nf_defrag_ipv4_enable(void)
916 +EXPORT_SYMBOL_GPL(nf_defrag_ipv4_enable);
918 +module_init(nf_defrag_init);
919 +module_exit(nf_defrag_fini);
921 +MODULE_LICENSE("GPL");
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
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)
933 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
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(-)
941 diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h
943 index 0000000..208b46f
945 +++ b/include/net/netfilter/nf_tproxy_core.h
947 +#ifndef _NF_TPROXY_CORE_H
948 +#define _NF_TPROXY_CORE_H
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>
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);
965 +nf_tproxy_put_sock(struct sock *sk)
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));
974 +/* assign a socket to the skb -- consumes sk */
976 +nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk);
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
985 This option enables support for a netlink-based userspace interface
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
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.
1000 + To compile it as a module, choose M here. If unsure, say N.
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
1013 +# transparent proxy support
1014 +obj-$(CONFIG_NETFILTER_TPROXY) += nf_tproxy_core.o
1017 obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
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
1023 +++ b/net/netfilter/nf_tproxy_core.c
1026 + * Transparent proxy support for Linux/iptables
1028 + * Copyright (c) 2006-2007 BalaBit IT Ltd.
1029 + * Author: Balazs Scheidler, Krisztian Kovacs
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.
1037 +#include <linux/version.h>
1038 +#include <linux/module.h>
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>
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)
1054 + /* look up socket */
1055 + switch (protocol) {
1057 + if (listening_only)
1058 + sk = __inet_lookup_listener(net, &tcp_hashinfo,
1059 + daddr, ntohs(dport),
1062 + sk = __inet_lookup(net, &tcp_hashinfo,
1063 + saddr, sport, daddr, dport,
1067 + sk = udp4_lib_lookup(net, saddr, sport, daddr, dport,
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);
1080 +EXPORT_SYMBOL_GPL(nf_tproxy_get_sock_v4);
1083 +nf_tproxy_destructor(struct sk_buff *skb)
1085 + struct sock *sk = skb->sk;
1088 + skb->destructor = NULL;
1091 + nf_tproxy_put_sock(sk);
1096 +nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk)
1098 + if (inet_sk(sk)->transparent) {
1100 + skb->destructor = nf_tproxy_destructor;
1103 + nf_tproxy_put_sock(sk);
1107 +EXPORT_SYMBOL_GPL(nf_tproxy_assign_sock);
1109 +static int __init nf_tproxy_init(void)
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");
1116 +module_init(nf_tproxy_init);
1118 +MODULE_LICENSE("GPL");
1119 +MODULE_AUTHOR("Krisztian Kovacs");
1120 +MODULE_DESCRIPTION("Transparent proxy support core routines");
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
1129 Add iptables 'socket' match, which matches packets for which a TCP/UDP
1130 socket lookup succeeds.
1132 Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
1133 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
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(-)
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'.
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
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.
1161 + To compile it as a module, choose M here. If unsure, say N.
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
1182 +++ b/net/netfilter/xt_socket.c
1185 + * Transparent proxy support for Linux/iptables
1187 + * Copyright (C) 2007 BalaBit IT Ltd.
1188 + * Author: Krisztian Kovacs
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.
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>
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>
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,
1219 + unsigned int protoff,
1222 + const struct iphdr *iph = ip_hdr(skb);
1223 + struct udphdr _hdr, *hp;
1227 +#ifdef XT_SOCKET_HAVE_CONNTRACK
1228 + struct nf_conn const *ct;
1229 + enum ip_conntrack_info ctinfo;
1232 + hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr);
1236 + daddr = iph->daddr;
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;
1253 + sk = nf_tproxy_get_sock_v4(skb->dev->nd_net, iph->protocol,
1254 + iph->saddr, daddr,
1255 + hp->source, dport, in, false);
1257 + bool wildcard = (inet_sk(sk)->rcv_saddr == 0);
1259 + nf_tproxy_put_sock(sk);
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);
1269 + return (sk != NULL);
1273 +socket_mt_check(const char *tablename,
1274 + const void *entry,
1275 + const struct xt_match *match,
1277 + unsigned int hook_mask)
1279 + const struct ipt_ip *i = entry;
1281 + if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)
1282 + && !(i->invflags & IPT_INV_PROTO))
1285 + pr_info("xt_socket: Can be used only in combination with "
1286 + "either -p tcp or -p udp\n");
1290 +static struct xt_match socket_mt_reg __read_mostly = {
1292 + .family = AF_INET,
1293 + .match = socket_mt,
1294 + .checkentry = socket_mt_check,
1295 + .hooks = 1 << NF_INET_PRE_ROUTING,
1296 + .me = THIS_MODULE,
1299 +static int __init socket_mt_init(void)
1301 + nf_defrag_ipv4_enable();
1302 + return xt_register_match(&socket_mt_reg);
1305 +static void __exit socket_mt_exit(void)
1307 + xt_unregister_match(&socket_mt_reg);
1310 +module_init(socket_mt_init);
1311 +module_exit(socket_mt_exit);
1313 +MODULE_LICENSE("GPL");
1314 +MODULE_AUTHOR("Krisztian Kovacs");
1315 +MODULE_DESCRIPTION("x_tables socket match module");
1316 +MODULE_ALIAS("ipt_socket");
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
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.)
1330 Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
1331 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
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(-)
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
1343 +++ b/include/linux/netfilter/xt_TPROXY.h
1345 +#ifndef _XT_TPROXY_H_target
1346 +#define _XT_TPROXY_H_target
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;
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
1365 To compile it as a module, choose M here. If unsure, say N.
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
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.
1380 + To compile it as a module, choose M here. If unsure, say N.
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
1401 +++ b/net/netfilter/xt_TPROXY.c
1404 + * Transparent proxy support for Linux/iptables
1406 + * Copyright (c) 2006-2007 BalaBit IT Ltd.
1407 + * Author: Balazs Scheidler, Krisztian Kovacs
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.
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>
1422 +#include <linux/netfilter/x_tables.h>
1423 +#include <linux/netfilter_ipv4/ip_tables.h>
1424 +#include <linux/netfilter/xt_TPROXY.h>
1426 +#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
1427 +#include <net/netfilter/nf_tproxy_core.h>
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)
1437 + const struct iphdr *iph = ip_hdr(skb);
1438 + const struct xt_tproxy_target_info *tgi = targinfo;
1439 + struct udphdr _hdr, *hp;
1442 + hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr);
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,
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;
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);
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);
1470 +tproxy_tg_check(const char *tablename,
1471 + const void *entry,
1472 + const struct xt_target *target,
1474 + unsigned int hook_mask)
1476 + const struct ipt_ip *i = entry;
1478 + if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)
1479 + && !(i->invflags & IPT_INV_PROTO))
1482 + pr_info("xt_TPROXY: Can be used only in combination with "
1483 + "either -p tcp or -p udp\n");
1487 +static struct xt_target tproxy_tg_reg __read_mostly = {
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,
1498 +static int __init tproxy_tg_init(void)
1500 + nf_defrag_ipv4_enable();
1501 + return xt_register_target(&tproxy_tg_reg);
1504 +static void __exit tproxy_tg_exit(void)
1506 + xt_unregister_target(&tproxy_tg_reg);
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");
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
1523 Use the socket cached in the TPROXY target if it's present.
1525 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
1527 net/ipv4/tcp_ipv4.c | 9 +++++++++
1528 1 files changed, 9 insertions(+), 0 deletions(-)
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;
1538 +#if defined(CONFIG_NETFILTER_TPROXY) || defined(CONFIG_NETFILTER_TPROXY_MODULE)
1539 + if (unlikely(skb->sk)) {
1540 + /* steal reference */
1542 + skb->destructor = NULL;
1546 sk = __inet_lookup(skb->dev->nd_net, &tcp_hashinfo, iph->saddr,
1547 th->source, iph->daddr, th->dest, inet_iif(skb));
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
1560 Use the socket cached in the TPROXY target if it's present.
1562 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
1564 net/ipv4/udp.c | 16 ++++++++++++++++
1565 1 files changed, 16 insertions(+), 0 deletions(-)
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[])
1575 +#if defined(CONFIG_NETFILTER_TPROXY) || defined(CONFIG_NETFILTER_TPROXY_MODULE)
1576 + if (unlikely(skb->sk)) {
1577 + /* steal reference */
1579 + skb->destructor = NULL;
1583 sk = __udp4_lib_lookup(skb->dev->nd_net, iph->daddr, uh->dest,
1584 iph->saddr, uh->source, skb->dev->ifindex, udptable);
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);
1590 +#if defined(CONFIG_NETFILTER_TPROXY) || defined(CONFIG_NETFILTER_TPROXY_MODULE)
1591 + if (unlikely(skb->sk)) {
1592 + /* steal reference */
1594 + skb->destructor = NULL;
1598 sk = __udp4_lib_lookup(skb->dev->nd_net, saddr, uh->source, daddr,
1599 uh->dest, inet_iif(skb), udptable);
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
1609 Add basic usage instructions to Documentation/networking.
1611 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
1613 Documentation/networking/tproxy.txt | 62 +++++++++++++++++++++++++++++++++++
1614 1 files changed, 62 insertions(+), 0 deletions(-)
1616 diff --git a/Documentation/networking/tproxy.txt b/Documentation/networking/tproxy.txt
1617 new file mode 100644
1618 index 0000000..dfcb613
1620 +++ b/Documentation/networking/tproxy.txt
1622 +Transparent proxy support
1623 +=========================
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
1630 +1. Making non-local sockets work
1631 +================================
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:
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
1642 +# ip rule add fwmark 1 lookup 100
1643 +# ip route add local 0.0.0.0/0 dev lo table 100
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:
1650 +fd = socket(AF_INET, SOCK_STREAM, 0);
1653 +setsockopt(fd, SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
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));
1660 +A trivial patch for netcat is available here:
1661 +http://people.netfilter.org/hidden/tproxy/netcat-ip_transparent-support.patch
1664 +2. Redirecting traffic
1665 +======================
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.)
1675 +The 'TPROXY' target provides similar functionality without relying on NAT. Simply
1676 +add rules like this to the iptables ruleset above:
1678 +# iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY \
1679 + --tproxy-mark 0x1/0x1 --on-port 50080
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.