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 addr->sin_addr.s_addr != 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 -------
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 diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
240 index 2fafaab..5ca683e 100644
241 --- a/include/net/inet_sock.h
242 +++ b/include/net/inet_sock.h
244 #include <net/flow.h>
245 #include <net/sock.h>
246 #include <net/request_sock.h>
247 -#include <net/route.h>
249 /** struct ip_options - IP Options
251 @@ -192,10 +191,4 @@ static inline int inet_sk_ehashfn(const struct sock *sk)
252 return inet_ehashfn(laddr, lport, faddr, fport);
256 -static inline int inet_iif(const struct sk_buff *skb)
258 - return skb->rtable->rt_iif;
261 #endif /* _INET_SOCK_H */
262 diff --git a/include/net/route.h b/include/net/route.h
263 index c633880..13e464f 100644
264 --- a/include/net/route.h
265 +++ b/include/net/route.h
266 @@ -204,6 +204,11 @@ static inline struct inet_peer *rt_get_peer(struct rtable *rt)
270 +static inline int inet_iif(const struct sk_buff *skb)
272 + return skb->rtable->rt_iif;
275 extern ctl_table ipv4_route_table[];
277 #endif /* _ROUTE_H */
278 diff --git a/net/ipv4/netfilter/nf_nat_helper.c b/net/ipv4/netfilter/nf_nat_helper.c
279 index 11976ea..112dcfa 100644
280 --- a/net/ipv4/netfilter/nf_nat_helper.c
281 +++ b/net/ipv4/netfilter/nf_nat_helper.c
283 #include <linux/udp.h>
284 #include <net/checksum.h>
286 +#include <net/route.h>
288 #include <linux/netfilter_ipv4.h>
289 #include <net/netfilter/nf_conntrack.h>
290 diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
291 index 73ba989..19a1037 100644
292 --- a/net/ipv4/syncookies.c
293 +++ b/net/ipv4/syncookies.c
295 #include <linux/cryptohash.h>
296 #include <linux/kernel.h>
298 +#include <net/route.h>
300 /* Timestamps: lowest 9 bits store TCP options */
302 diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
303 index 3c6aafb..f6645d2 100644
304 --- a/net/ipv6/af_inet6.c
305 +++ b/net/ipv6/af_inet6.c
307 #include <net/ipip.h>
308 #include <net/protocol.h>
309 #include <net/inet_common.h>
310 +#include <net/route.h>
311 #include <net/transp_v6.h>
312 #include <net/ip6_route.h>
313 #include <net/addrconf.h>
317 From 03bf9d04e8a6d0dc994363c8133ff494226701ef Mon Sep 17 00:00:00 2001
318 From: KOVACS Krisztian <hidden@sch.bme.hu>
319 Date: Mon, 28 Apr 2008 14:46:50 +0200
320 Subject: [PATCH] Conditionally enable transparent flow flag when connecting
322 Set FLOWI_FLAG_ANYSRC in flowi->flags if the socket has the
323 transparent socket option set. This way we selectively enable certain
324 connections with non-local source addresses to be routed.
326 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
328 include/net/route.h | 6 +++++-
329 1 files changed, 5 insertions(+), 1 deletions(-)
331 diff --git a/include/net/route.h b/include/net/route.h
332 index 13e464f..2928618 100644
333 --- a/include/net/route.h
334 +++ b/include/net/route.h
337 #include <net/inetpeer.h>
338 #include <net/flow.h>
339 -#include <net/sock.h>
340 +#include <net/inet_sock.h>
341 #include <linux/in_route.h>
342 #include <linux/rtnetlink.h>
343 #include <linux/route.h>
344 @@ -161,6 +161,10 @@ static inline int ip_route_connect(struct rtable **rp, __be32 dst,
347 struct net *net = sock_net(sk);
349 + if (inet_sk(sk)->transparent)
350 + fl.flags |= FLOWI_FLAG_ANYSRC;
353 err = __ip_route_output_key(net, rp, &fl);
358 From 181680c6c0df4335bd8eeeafe06ea12e6918c3b7 Mon Sep 17 00:00:00 2001
359 From: KOVACS Krisztian <hidden@sch.bme.hu>
360 Date: Mon, 28 Apr 2008 14:46:50 +0200
361 Subject: [PATCH] Handle TCP SYN+ACK/ACK/RST transparency
363 The TCP stack sends out SYN+ACK/ACK/RST reply packets in response to
364 incoming packets. The non-local source address check on output bites
365 us again, as replies for transparently redirected traffic won't have a
366 chance to leave the node.
368 This patch selectively sets the FLOWI_FLAG_ANYSRC flag when doing
369 the route lookup for those replies. Transparent replies are enabled if
370 the listening socket has the transparent socket flag set.
372 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
374 include/net/inet_sock.h | 8 +++++++-
375 include/net/ip.h | 9 +++++++++
376 net/ipv4/inet_connection_sock.c | 1 +
377 net/ipv4/ip_output.c | 4 +++-
378 net/ipv4/syncookies.c | 1 +
379 net/ipv4/tcp_ipv4.c | 11 ++++++++---
380 6 files changed, 29 insertions(+), 5 deletions(-)
382 diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
383 index 5ca683e..013e41d 100644
384 --- a/include/net/inet_sock.h
385 +++ b/include/net/inet_sock.h
386 @@ -71,7 +71,8 @@ struct inet_request_sock {
393 struct ip_options *opt;
396 @@ -191,4 +192,9 @@ static inline int inet_sk_ehashfn(const struct sock *sk)
397 return inet_ehashfn(laddr, lport, faddr, fport);
400 +static inline __u8 inet_sk_flowi_flags(const struct sock *sk)
402 + return inet_sk(sk)->transparent ? FLOWI_FLAG_ANYSRC : 0;
405 #endif /* _INET_SOCK_H */
406 diff --git a/include/net/ip.h b/include/net/ip.h
407 index 6d7bcd5..c611608 100644
408 --- a/include/net/ip.h
409 +++ b/include/net/ip.h
412 #include <net/inet_sock.h>
413 #include <net/snmp.h>
414 +#include <net/flow.h>
418 @@ -140,12 +141,20 @@ static inline void ip_tr_mc_map(__be32 addr, char *buf)
420 struct ip_reply_arg {
424 int csumoffset; /* u16 offset of csum in iov[0].iov_base */
425 /* -1 if not needed */
429 +#define IP_REPLY_ARG_NOSRCCHECK 1
431 +static inline __u8 ip_reply_arg_flowi_flags(const struct ip_reply_arg *arg)
433 + return (arg->flags & IP_REPLY_ARG_NOSRCCHECK) ? FLOWI_FLAG_ANYSRC : 0;
436 void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *arg,
439 diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
440 index 828ea21..6d70d51 100644
441 --- a/net/ipv4/inet_connection_sock.c
442 +++ b/net/ipv4/inet_connection_sock.c
443 @@ -333,6 +333,7 @@ struct dst_entry* inet_csk_route_req(struct sock *sk,
444 .saddr = ireq->loc_addr,
445 .tos = RT_CONN_FLAGS(sk) } },
446 .proto = sk->sk_protocol,
447 + .flags = inet_sk_flowi_flags(sk),
449 { .sport = inet_sk(sk)->sport,
450 .dport = ireq->rmt_port } } };
451 diff --git a/net/ipv4/ip_output.c b/net/ipv4/ip_output.c
452 index 0834926..9ac5270 100644
453 --- a/net/ipv4/ip_output.c
454 +++ b/net/ipv4/ip_output.c
455 @@ -342,6 +342,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok)
456 .saddr = inet->saddr,
457 .tos = RT_CONN_FLAGS(sk) } },
458 .proto = sk->sk_protocol,
459 + .flags = inet_sk_flowi_flags(sk),
461 { .sport = inet->sport,
462 .dport = inet->dport } } };
463 @@ -1380,7 +1381,8 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar
465 { .sport = tcp_hdr(skb)->dest,
466 .dport = tcp_hdr(skb)->source } },
467 - .proto = sk->sk_protocol };
468 + .proto = sk->sk_protocol,
469 + .flags = ip_reply_arg_flowi_flags(arg) };
470 security_skb_classify_flow(skb, &fl);
471 if (ip_route_output_key(sock_net(sk), &rt, &fl))
473 diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
474 index 19a1037..d5fa8c7 100644
475 --- a/net/ipv4/syncookies.c
476 +++ b/net/ipv4/syncookies.c
477 @@ -340,6 +340,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
478 .saddr = ireq->loc_addr,
479 .tos = RT_CONN_FLAGS(sk) } },
480 .proto = IPPROTO_TCP,
481 + .flags = inet_sk_flowi_flags(sk),
484 .dport = th->source } } };
485 diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
486 index 0e9bc12..58873ad 100644
487 --- a/net/ipv4/tcp_ipv4.c
488 +++ b/net/ipv4/tcp_ipv4.c
489 @@ -594,6 +594,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
490 ip_hdr(skb)->saddr, /* XXX */
491 sizeof(struct tcphdr), IPPROTO_TCP, 0);
492 arg.csumoffset = offsetof(struct tcphdr, check) / 2;
493 + arg.flags = (sk && inet_sk(sk)->transparent) ? IP_REPLY_ARG_NOSRCCHECK : 0;
495 ip_send_reply(dev_net(skb->dst->dev)->ipv4.tcp_sock, skb,
496 &arg, arg.iov[0].iov_len);
497 @@ -608,7 +609,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
499 static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
500 struct sk_buff *skb, u32 seq, u32 ack,
502 + u32 win, u32 ts, int reply_flags)
504 struct tcphdr *th = tcp_hdr(skb);
506 @@ -684,6 +685,7 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk,
510 + arg.flags = reply_flags;
511 arg.csum = csum_tcpudp_nofold(ip_hdr(skb)->daddr,
512 ip_hdr(skb)->saddr, /* XXX */
513 arg.iov[0].iov_len, IPPROTO_TCP, 0);
514 @@ -704,7 +706,8 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)
516 tcp_v4_send_ack(tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt,
517 tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale,
518 - tcptw->tw_ts_recent);
519 + tcptw->tw_ts_recent,
520 + tw->tw_transparent ? IP_REPLY_ARG_NOSRCCHECK : 0);
524 @@ -714,7 +717,8 @@ static void tcp_v4_reqsk_send_ack(struct sk_buff *skb,
526 tcp_v4_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1,
527 tcp_rsk(req)->rcv_isn + 1, req->rcv_wnd,
530 + inet_rsk(req)->no_srccheck ? IP_REPLY_ARG_NOSRCCHECK : 0);
534 @@ -1321,6 +1325,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb)
535 ireq = inet_rsk(req);
536 ireq->loc_addr = daddr;
537 ireq->rmt_addr = saddr;
538 + ireq->no_srccheck = inet_sk(sk)->transparent;
539 ireq->opt = tcp_v4_save_options(sk, skb);
541 TCP_ECN_create_request(req, tcp_hdr(skb));
545 From f8be7a55d2a449d188f033d7914d2af007054fbc Mon Sep 17 00:00:00 2001
546 From: KOVACS Krisztian <hidden@sch.bme.hu>
547 Date: Mon, 28 Apr 2008 14:46:50 +0200
548 Subject: [PATCH] Make Netfilter's ip_route_me_harder() non-local address compatible
550 Netfilter's ip_route_me_harder() tries to re-route packets either generated or
551 re-routed by Netfilter. This patch changes ip_route_me_harder() to handle
552 packets from non-locally-bound sockets with IP_TRANSPARENT set as local and to
553 set the appropriate flowi flags when re-doing the routing lookup.
555 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
557 net/ipv4/netfilter.c | 3 +++
558 1 files changed, 3 insertions(+), 0 deletions(-)
560 diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
561 index f8edacd..01671ad 100644
562 --- a/net/ipv4/netfilter.c
563 +++ b/net/ipv4/netfilter.c
564 @@ -20,6 +20,8 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
567 type = inet_addr_type(&init_net, iph->saddr);
568 + if (skb->sk && inet_sk(skb->sk)->transparent)
570 if (addr_type == RTN_UNSPEC)
573 @@ -33,6 +35,7 @@ int ip_route_me_harder(struct sk_buff *skb, unsigned addr_type)
574 fl.nl_u.ip4_u.tos = RT_TOS(iph->tos);
575 fl.oif = skb->sk ? skb->sk->sk_bound_dev_if : 0;
577 + fl.flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0;
578 if (ip_route_output_key(&init_net, &rt, &fl) != 0)
584 From 7797a39b59dae015e06bd4860affbdb250c312b7 Mon Sep 17 00:00:00 2001
585 From: KOVACS Krisztian <hidden@sch.bme.hu>
586 Date: Mon, 28 Apr 2008 14:46:50 +0200
587 Subject: [PATCH] Port redirection support for TCP
589 Current TCP code relies on the local port of the listening socket
590 being the same as the destination address of the incoming
591 connection. Port redirection used by many transparent proxying
592 techniques obviously breaks this, so we have to store the original
593 destination port address.
595 This patch extends struct inet_request_sock and stores the incoming
596 destination port value there. It also modifies the handshake code to
597 use that value as the source port when sending reply packets.
599 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
601 include/net/inet_sock.h | 2 +-
602 include/net/tcp.h | 1 +
603 net/ipv4/inet_connection_sock.c | 2 ++
604 net/ipv4/syncookies.c | 1 +
605 net/ipv4/tcp_output.c | 2 +-
606 5 files changed, 6 insertions(+), 2 deletions(-)
608 diff --git a/include/net/inet_sock.h b/include/net/inet_sock.h
609 index 013e41d..42b5d36 100644
610 --- a/include/net/inet_sock.h
611 +++ b/include/net/inet_sock.h
612 @@ -60,8 +60,8 @@ struct inet_request_sock {
613 struct request_sock req;
614 #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
615 u16 inet6_rsk_offset;
616 - /* 2 bytes hole, try to pack */
622 diff --git a/include/net/tcp.h b/include/net/tcp.h
623 index 633147c..3c6a549 100644
624 --- a/include/net/tcp.h
625 +++ b/include/net/tcp.h
626 @@ -975,6 +975,7 @@ static inline void tcp_openreq_init(struct request_sock *req,
629 ireq->rmt_port = tcp_hdr(skb)->source;
630 + ireq->loc_port = tcp_hdr(skb)->dest;
633 extern void tcp_enter_memory_pressure(void);
634 diff --git a/net/ipv4/inet_connection_sock.c b/net/ipv4/inet_connection_sock.c
635 index 6d70d51..33dc826 100644
636 --- a/net/ipv4/inet_connection_sock.c
637 +++ b/net/ipv4/inet_connection_sock.c
638 @@ -508,6 +508,8 @@ struct sock *inet_csk_clone(struct sock *sk, const struct request_sock *req,
639 newicsk->icsk_bind_hash = NULL;
641 inet_sk(newsk)->dport = inet_rsk(req)->rmt_port;
642 + inet_sk(newsk)->num = ntohs(inet_rsk(req)->loc_port);
643 + inet_sk(newsk)->sport = inet_rsk(req)->loc_port;
644 newsk->sk_write_space = sk_stream_write_space;
646 newicsk->icsk_retransmits = 0;
647 diff --git a/net/ipv4/syncookies.c b/net/ipv4/syncookies.c
648 index d5fa8c7..676c550 100644
649 --- a/net/ipv4/syncookies.c
650 +++ b/net/ipv4/syncookies.c
651 @@ -299,6 +299,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb,
652 treq->rcv_isn = ntohl(th->seq) - 1;
653 treq->snt_isn = cookie;
655 + ireq->loc_port = th->dest;
656 ireq->rmt_port = th->source;
657 ireq->loc_addr = ip_hdr(skb)->daddr;
658 ireq->rmt_addr = ip_hdr(skb)->saddr;
659 diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c
660 index debf235..2b1d34d 100644
661 --- a/net/ipv4/tcp_output.c
662 +++ b/net/ipv4/tcp_output.c
663 @@ -2211,7 +2211,7 @@ struct sk_buff *tcp_make_synack(struct sock *sk, struct dst_entry *dst,
666 TCP_ECN_make_synack(req, th);
667 - th->source = inet_sk(sk)->sport;
668 + th->source = ireq->loc_port;
669 th->dest = ireq->rmt_port;
670 /* Setting of flags are superfluous here for callers (and ECE is
671 * not even correctly set)
675 From 4feb1a188b6bd0ff8cab5c8d817fbfc7d7788802 Mon Sep 17 00:00:00 2001
676 From: KOVACS Krisztian <hidden@sch.bme.hu>
677 Date: Mon, 28 Apr 2008 14:46:51 +0200
678 Subject: [PATCH] Export UDP socket lookup function
680 The iptables tproxy code has to be able to do UDP socket hash lookups,
681 so we have to provide an exported lookup function for this purpose.
683 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
685 include/net/udp.h | 4 ++++
686 net/ipv4/udp.c | 7 +++++++
687 2 files changed, 11 insertions(+), 0 deletions(-)
689 diff --git a/include/net/udp.h b/include/net/udp.h
690 index 3e55a99..b88a196 100644
691 --- a/include/net/udp.h
692 +++ b/include/net/udp.h
693 @@ -147,6 +147,10 @@ extern int udp_lib_setsockopt(struct sock *sk, int level, int optname,
694 char __user *optval, int optlen,
695 int (*push_pending_frames)(struct sock *));
697 +extern struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
698 + __be32 daddr, __be16 dport,
701 DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);
702 DECLARE_SNMP_STAT(struct udp_mib, udp_stats_in6);
704 diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
705 index 1f535e3..672d0d4 100644
708 @@ -307,6 +307,13 @@ static struct sock *__udp4_lib_lookup(struct net *net, __be32 saddr,
712 +struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport,
713 + __be32 daddr, __be16 dport, int dif)
715 + return __udp4_lib_lookup(net, saddr, sport, daddr, dport, dif, udp_hash);
717 +EXPORT_SYMBOL_GPL(udp4_lib_lookup);
719 static inline struct sock *udp_v4_mcast_next(struct sock *sk,
720 __be16 loc_port, __be32 loc_addr,
721 __be16 rmt_port, __be32 rmt_addr,
725 From d49cee38069417f3cb83ca67baa65a2034d2d2ce Mon Sep 17 00:00:00 2001
726 From: KOVACS Krisztian <hidden@sch.bme.hu>
727 Date: Mon, 28 Apr 2008 14:46:51 +0200
728 Subject: [PATCH] Split Netfilter IPv4 defragmentation into a separate module
730 Netfilter connection tracking requires all IPv4 packets to be defragmented.
731 Both the socket match and the TPROXY target depend on this functionality, so
732 this patch separates the Netfilter IPv4 defrag hooks into a separate module.
734 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
736 include/net/netfilter/ipv4/nf_defrag_ipv4.h | 6 ++
737 net/ipv4/netfilter/Kconfig | 5 +
738 net/ipv4/netfilter/Makefile | 3 +
739 net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 56 +-------------
740 net/ipv4/netfilter/nf_defrag_ipv4.c | 96 ++++++++++++++++++++++++
741 5 files changed, 113 insertions(+), 53 deletions(-)
743 diff --git a/include/net/netfilter/ipv4/nf_defrag_ipv4.h b/include/net/netfilter/ipv4/nf_defrag_ipv4.h
745 index 0000000..6b00ea3
747 +++ b/include/net/netfilter/ipv4/nf_defrag_ipv4.h
749 +#ifndef _NF_DEFRAG_IPV4_H
750 +#define _NF_DEFRAG_IPV4_H
752 +extern void nf_defrag_ipv4_enable(void);
754 +#endif /* _NF_DEFRAG_IPV4_H */
755 diff --git a/net/ipv4/netfilter/Kconfig b/net/ipv4/netfilter/Kconfig
756 index 2767841..3520c01 100644
757 --- a/net/ipv4/netfilter/Kconfig
758 +++ b/net/ipv4/netfilter/Kconfig
760 menu "IP: Netfilter Configuration"
761 depends on INET && NETFILTER
763 +config NF_DEFRAG_IPV4
767 config NF_CONNTRACK_IPV4
768 tristate "IPv4 connection tracking support (required for NAT)"
769 depends on NF_CONNTRACK
770 default m if NETFILTER_ADVANCED=n
771 + select NF_DEFRAG_IPV4
773 Connection tracking keeps a record of what packets have passed
774 through your machine, in order to figure out how they are related
775 diff --git a/net/ipv4/netfilter/Makefile b/net/ipv4/netfilter/Makefile
776 index d9b92fb..782b1e7 100644
777 --- a/net/ipv4/netfilter/Makefile
778 +++ b/net/ipv4/netfilter/Makefile
779 @@ -18,6 +18,9 @@ obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o
781 obj-$(CONFIG_NF_NAT) += nf_nat.o
784 +obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o
786 # NAT helpers (nf_conntrack)
787 obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o
788 obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o
789 diff --git a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
790 index cacb9cb..9da59f3 100644
791 --- a/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
792 +++ b/net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c
795 /* (C) 1999-2001 Paul `Rusty' Russell
796 * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
799 #include <net/netfilter/nf_conntrack_core.h>
800 #include <net/netfilter/ipv4/nf_conntrack_ipv4.h>
801 #include <net/netfilter/nf_nat_helper.h>
802 +#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
804 int (*nf_nat_seq_adjust_hook)(struct sk_buff *skb,
806 @@ -63,23 +65,6 @@ static int ipv4_print_tuple(struct seq_file *s,
807 NIPQUAD(tuple->dst.u3.ip));
810 -/* Returns new sk_buff, or NULL */
811 -static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
817 - local_bh_disable();
818 - err = ip_defrag(skb, user);
822 - ip_send_check(ip_hdr(skb));
827 static int ipv4_get_l4proto(const struct sk_buff *skb, unsigned int nhoff,
828 unsigned int *dataoff, u_int8_t *protonum)
830 @@ -144,28 +129,6 @@ out:
831 return nf_conntrack_confirm(skb);
834 -static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
835 - struct sk_buff *skb,
836 - const struct net_device *in,
837 - const struct net_device *out,
838 - int (*okfn)(struct sk_buff *))
840 - /* Previously seen (loopback)? Ignore. Do this before
845 - /* Gather fragments. */
846 - if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
847 - if (nf_ct_ipv4_gather_frags(skb,
848 - hooknum == NF_INET_PRE_ROUTING ?
849 - IP_DEFRAG_CONNTRACK_IN :
850 - IP_DEFRAG_CONNTRACK_OUT))
856 static unsigned int ipv4_conntrack_in(unsigned int hooknum,
858 const struct net_device *in,
859 @@ -195,13 +158,6 @@ static unsigned int ipv4_conntrack_local(unsigned int hooknum,
860 make it the first hook. */
861 static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
863 - .hook = ipv4_conntrack_defrag,
864 - .owner = THIS_MODULE,
866 - .hooknum = NF_INET_PRE_ROUTING,
867 - .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
870 .hook = ipv4_conntrack_in,
871 .owner = THIS_MODULE,
873 @@ -209,13 +165,6 @@ static struct nf_hook_ops ipv4_conntrack_ops[] __read_mostly = {
874 .priority = NF_IP_PRI_CONNTRACK,
877 - .hook = ipv4_conntrack_defrag,
878 - .owner = THIS_MODULE,
880 - .hooknum = NF_INET_LOCAL_OUT,
881 - .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
884 .hook = ipv4_conntrack_local,
885 .owner = THIS_MODULE,
887 @@ -422,6 +371,7 @@ static int __init nf_conntrack_l3proto_ipv4_init(void)
891 + nf_defrag_ipv4_enable();
893 ret = nf_register_sockopt(&so_getorigdst);
895 diff --git a/net/ipv4/netfilter/nf_defrag_ipv4.c b/net/ipv4/netfilter/nf_defrag_ipv4.c
897 index 0000000..aa2c50a
899 +++ b/net/ipv4/netfilter/nf_defrag_ipv4.c
901 +/* (C) 1999-2001 Paul `Rusty' Russell
902 + * (C) 2002-2004 Netfilter Core Team <coreteam@netfilter.org>
904 + * This program is free software; you can redistribute it and/or modify
905 + * it under the terms of the GNU General Public License version 2 as
906 + * published by the Free Software Foundation.
909 +#include <linux/types.h>
910 +#include <linux/ip.h>
911 +#include <linux/netfilter.h>
912 +#include <linux/module.h>
913 +#include <linux/skbuff.h>
914 +#include <net/route.h>
917 +#include <linux/netfilter_ipv4.h>
918 +#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
920 +/* Returns new sk_buff, or NULL */
921 +static int nf_ct_ipv4_gather_frags(struct sk_buff *skb, u_int32_t user)
927 + local_bh_disable();
928 + err = ip_defrag(skb, user);
932 + ip_send_check(ip_hdr(skb));
937 +static unsigned int ipv4_conntrack_defrag(unsigned int hooknum,
938 + struct sk_buff *skb,
939 + const struct net_device *in,
940 + const struct net_device *out,
941 + int (*okfn)(struct sk_buff *))
943 +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
944 + /* Previously seen (loopback)? Ignore. Do this before
950 + /* Gather fragments. */
951 + if (ip_hdr(skb)->frag_off & htons(IP_MF | IP_OFFSET)) {
952 + if (nf_ct_ipv4_gather_frags(skb,
953 + hooknum == NF_INET_PRE_ROUTING ?
954 + IP_DEFRAG_CONNTRACK_IN :
955 + IP_DEFRAG_CONNTRACK_OUT))
961 +static struct nf_hook_ops ipv4_defrag_ops[] = {
963 + .hook = ipv4_conntrack_defrag,
964 + .owner = THIS_MODULE,
966 + .hooknum = NF_INET_PRE_ROUTING,
967 + .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
970 + .hook = ipv4_conntrack_defrag,
971 + .owner = THIS_MODULE,
973 + .hooknum = NF_INET_LOCAL_OUT,
974 + .priority = NF_IP_PRI_CONNTRACK_DEFRAG,
978 +static int __init nf_defrag_init(void)
980 + return nf_register_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));
983 +static void __exit nf_defrag_fini(void)
985 + nf_unregister_hooks(ipv4_defrag_ops, ARRAY_SIZE(ipv4_defrag_ops));
988 +void nf_defrag_ipv4_enable(void)
991 +EXPORT_SYMBOL_GPL(nf_defrag_ipv4_enable);
993 +module_init(nf_defrag_init);
994 +module_exit(nf_defrag_fini);
996 +MODULE_LICENSE("GPL");
1000 From 40b01b3ada99906bb5818e15cddfe49344d09fd9 Mon Sep 17 00:00:00 2001
1001 From: KOVACS Krisztian <hidden@sch.bme.hu>
1002 Date: Mon, 28 Apr 2008 14:46:51 +0200
1003 Subject: [PATCH] iptables tproxy core
1005 The iptables tproxy core is a module that contains the common routines used by
1006 various tproxy related modules (TPROXY target and socket match)
1008 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
1010 include/net/netfilter/nf_tproxy_core.h | 32 +++++++++++
1011 net/netfilter/Kconfig | 15 +++++
1012 net/netfilter/Makefile | 3 +
1013 net/netfilter/nf_tproxy_core.c | 96 ++++++++++++++++++++++++++++++++
1014 4 files changed, 146 insertions(+), 0 deletions(-)
1016 diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h
1017 new file mode 100644
1018 index 0000000..208b46f
1020 +++ b/include/net/netfilter/nf_tproxy_core.h
1022 +#ifndef _NF_TPROXY_CORE_H
1023 +#define _NF_TPROXY_CORE_H
1025 +#include <linux/types.h>
1026 +#include <linux/in.h>
1027 +#include <linux/skbuff.h>
1028 +#include <net/sock.h>
1029 +#include <net/inet_sock.h>
1030 +#include <net/tcp.h>
1032 +/* look up and get a reference to a matching socket */
1033 +extern struct sock *
1034 +nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
1035 + const __be32 saddr, const __be32 daddr,
1036 + const __be16 sport, const __be16 dport,
1037 + const struct net_device *in, bool listening);
1040 +nf_tproxy_put_sock(struct sock *sk)
1042 + /* TIME_WAIT inet sockets have to be handled differently */
1043 + if ((sk->sk_protocol == IPPROTO_TCP) && (sk->sk_state == TCP_TIME_WAIT))
1044 + inet_twsk_put(inet_twsk(sk));
1049 +/* assign a socket to the skb -- consumes sk */
1051 +nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk);
1054 diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
1055 index c1fc0f1..de42858 100644
1056 --- a/net/netfilter/Kconfig
1057 +++ b/net/netfilter/Kconfig
1058 @@ -277,6 +277,21 @@ config NF_CT_NETLINK
1060 This option enables support for a netlink-based userspace interface
1062 +# transparent proxy support
1063 +config NETFILTER_TPROXY
1064 + tristate "Transparent proxying support (EXPERIMENTAL)"
1065 + depends on EXPERIMENTAL
1066 + depends on IP_NF_MANGLE
1067 + depends on NETFILTER_ADVANCED
1069 + This option enables transparent proxying support, that is,
1070 + support for handling non-locally bound IPv4 TCP and UDP sockets.
1071 + For it to work you will have to configure certain iptables rules
1072 + and use policy routing. For more information on how to set it up
1073 + see Documentation/networking/tproxy.txt.
1075 + To compile it as a module, choose M here. If unsure, say N.
1077 config NETFILTER_XTABLES
1078 tristate "Netfilter Xtables support (required for ip_tables)"
1079 default m if NETFILTER_ADVANCED=n
1080 diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
1081 index 5c4b183..d644e82 100644
1082 --- a/net/netfilter/Makefile
1083 +++ b/net/netfilter/Makefile
1084 @@ -34,6 +34,9 @@ obj-$(CONFIG_NF_CONNTRACK_SANE) += nf_conntrack_sane.o
1085 obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o
1086 obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o
1088 +# transparent proxy support
1089 +obj-$(CONFIG_NETFILTER_TPROXY) += nf_tproxy_core.o
1092 obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
1094 diff --git a/net/netfilter/nf_tproxy_core.c b/net/netfilter/nf_tproxy_core.c
1095 new file mode 100644
1096 index 0000000..8a6075d
1098 +++ b/net/netfilter/nf_tproxy_core.c
1101 + * Transparent proxy support for Linux/iptables
1103 + * Copyright (c) 2006-2007 BalaBit IT Ltd.
1104 + * Author: Balazs Scheidler, Krisztian Kovacs
1106 + * This program is free software; you can redistribute it and/or modify
1107 + * it under the terms of the GNU General Public License version 2 as
1108 + * published by the Free Software Foundation.
1112 +#include <linux/version.h>
1113 +#include <linux/module.h>
1115 +#include <linux/net.h>
1116 +#include <linux/if.h>
1117 +#include <linux/netdevice.h>
1118 +#include <net/udp.h>
1119 +#include <net/netfilter/nf_tproxy_core.h>
1122 +nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
1123 + const __be32 saddr, const __be32 daddr,
1124 + const __be16 sport, const __be16 dport,
1125 + const struct net_device *in, bool listening_only)
1129 + /* look up socket */
1130 + switch (protocol) {
1132 + if (listening_only)
1133 + sk = __inet_lookup_listener(net, &tcp_hashinfo,
1134 + daddr, ntohs(dport),
1137 + sk = __inet_lookup(net, &tcp_hashinfo,
1138 + saddr, sport, daddr, dport,
1142 + sk = udp4_lib_lookup(net, saddr, sport, daddr, dport,
1150 + pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u sock %p\n",
1151 + protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), sk);
1155 +EXPORT_SYMBOL_GPL(nf_tproxy_get_sock_v4);
1158 +nf_tproxy_destructor(struct sk_buff *skb)
1160 + struct sock *sk = skb->sk;
1163 + skb->destructor = NULL;
1166 + nf_tproxy_put_sock(sk);
1171 +nf_tproxy_assign_sock(struct sk_buff *skb, struct sock *sk)
1173 + if (inet_sk(sk)->transparent) {
1175 + skb->destructor = nf_tproxy_destructor;
1178 + nf_tproxy_put_sock(sk);
1182 +EXPORT_SYMBOL_GPL(nf_tproxy_assign_sock);
1184 +static int __init nf_tproxy_init(void)
1186 + pr_info("NF_TPROXY: Transparent proxy support initialized, version 4.1.0\n");
1187 + pr_info("NF_TPROXY: Copyright (c) 2006-2007 BalaBit IT Ltd.\n");
1191 +module_init(nf_tproxy_init);
1193 +MODULE_LICENSE("GPL");
1194 +MODULE_AUTHOR("Krisztian Kovacs");
1195 +MODULE_DESCRIPTION("Transparent proxy support core routines");
1199 From 7962977079ac28db798ab5b11ee31df6566fb472 Mon Sep 17 00:00:00 2001
1200 From: KOVACS Krisztian <hidden@sch.bme.hu>
1201 Date: Mon, 28 Apr 2008 14:46:52 +0200
1202 Subject: [PATCH] iptables socket match
1204 Add iptables 'socket' match, which matches packets for which a TCP/UDP
1205 socket lookup succeeds.
1207 Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
1208 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
1210 net/netfilter/Kconfig | 15 +++++
1211 net/netfilter/Makefile | 1 +
1212 net/netfilter/xt_socket.c | 133 +++++++++++++++++++++++++++++++++++++++++++++
1213 3 files changed, 149 insertions(+), 0 deletions(-)
1215 diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
1216 index de42858..ce21278 100644
1217 --- a/net/netfilter/Kconfig
1218 +++ b/net/netfilter/Kconfig
1219 @@ -748,6 +748,21 @@ config NETFILTER_XT_MATCH_SCTP
1220 If you want to compile it as a module, say M here and read
1221 <file:Documentation/kbuild/modules.txt>. If unsure, say `N'.
1223 +config NETFILTER_XT_MATCH_SOCKET
1224 + tristate '"socket" match support (EXPERIMENTAL)'
1225 + depends on EXPERIMENTAL
1226 + depends on NETFILTER_TPROXY
1227 + depends on NETFILTER_XTABLES
1228 + depends on NETFILTER_ADVANCED
1229 + select NF_DEFRAG_IPV4
1231 + This option adds a `socket' match, which can be used to match
1232 + packets for which a TCP or UDP socket lookup finds a valid socket.
1233 + It can be used in combination with the MARK target and policy
1234 + routing to implement full featured non-locally bound sockets.
1236 + To compile it as a module, choose M here. If unsure, say N.
1238 config NETFILTER_XT_MATCH_STATE
1239 tristate '"state" match support'
1240 depends on NETFILTER_XTABLES
1241 diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
1242 index d644e82..6d2eee6 100644
1243 --- a/net/netfilter/Makefile
1244 +++ b/net/netfilter/Makefile
1245 @@ -80,6 +80,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_QUOTA) += xt_quota.o
1246 obj-$(CONFIG_NETFILTER_XT_MATCH_RATEEST) += xt_rateest.o
1247 obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o
1248 obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o
1249 +obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o
1250 obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o
1251 obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o
1252 obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
1253 diff --git a/net/netfilter/xt_socket.c b/net/netfilter/xt_socket.c
1254 new file mode 100644
1255 index 0000000..fa33358
1257 +++ b/net/netfilter/xt_socket.c
1260 + * Transparent proxy support for Linux/iptables
1262 + * Copyright (C) 2007 BalaBit IT Ltd.
1263 + * Author: Krisztian Kovacs
1265 + * This program is free software; you can redistribute it and/or modify
1266 + * it under the terms of the GNU General Public License version 2 as
1267 + * published by the Free Software Foundation.
1271 +#include <linux/module.h>
1272 +#include <linux/skbuff.h>
1273 +#include <linux/netfilter/x_tables.h>
1274 +#include <linux/netfilter_ipv4/ip_tables.h>
1275 +#include <net/tcp.h>
1276 +#include <net/udp.h>
1277 +#include <net/sock.h>
1278 +#include <net/inet_sock.h>
1279 +#include <net/netfilter/nf_tproxy_core.h>
1280 +#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
1282 +#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
1283 +#define XT_SOCKET_HAVE_CONNTRACK 1
1284 +#include <net/netfilter/nf_conntrack.h>
1288 +socket_mt(const struct sk_buff *skb,
1289 + const struct net_device *in,
1290 + const struct net_device *out,
1291 + const struct xt_match *match,
1292 + const void *matchinfo,
1294 + unsigned int protoff,
1297 + const struct iphdr *iph = ip_hdr(skb);
1298 + struct udphdr _hdr, *hp;
1302 +#ifdef XT_SOCKET_HAVE_CONNTRACK
1303 + struct nf_conn const *ct;
1304 + enum ip_conntrack_info ctinfo;
1307 + hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr);
1311 + daddr = iph->daddr;
1314 +#ifdef XT_SOCKET_HAVE_CONNTRACK
1315 + /* Do the lookup with the original socket address in case this is a
1316 + * reply packet of an established SNAT-ted connection. */
1317 + ct = nf_ct_get(skb, &ctinfo);
1318 + if (ct && (ct != &nf_conntrack_untracked) &&
1319 + (ctinfo == IP_CT_IS_REPLY + IP_CT_ESTABLISHED) &&
1320 + (ct->status & IPS_SRC_NAT_DONE)) {
1321 + daddr = ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u3.ip;
1322 + dport = (iph->protocol == IPPROTO_TCP) ?
1323 + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.tcp.port :
1324 + ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple.src.u.udp.port;
1328 + sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
1329 + iph->saddr, daddr,
1330 + hp->source, dport, in, false);
1332 + bool wildcard = (inet_sk(sk)->rcv_saddr == 0);
1334 + nf_tproxy_put_sock(sk);
1339 + pr_debug("socket match: proto %u %08x:%u -> %08x:%u (orig %08x:%u) sock %p\n",
1340 + iph->protocol, ntohl(iph->saddr), ntohs(hp->source),
1341 + ntohl(daddr), ntohs(dport),
1342 + ntohl(iph->daddr), ntohs(hp->dest), sk);
1344 + return (sk != NULL);
1348 +socket_mt_check(const char *tablename,
1349 + const void *entry,
1350 + const struct xt_match *match,
1352 + unsigned int hook_mask)
1354 + const struct ipt_ip *i = entry;
1356 + if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)
1357 + && !(i->invflags & IPT_INV_PROTO))
1360 + pr_info("xt_socket: Can be used only in combination with "
1361 + "either -p tcp or -p udp\n");
1365 +static struct xt_match socket_mt_reg __read_mostly = {
1367 + .family = AF_INET,
1368 + .match = socket_mt,
1369 + .checkentry = socket_mt_check,
1370 + .hooks = 1 << NF_INET_PRE_ROUTING,
1371 + .me = THIS_MODULE,
1374 +static int __init socket_mt_init(void)
1376 + nf_defrag_ipv4_enable();
1377 + return xt_register_match(&socket_mt_reg);
1380 +static void __exit socket_mt_exit(void)
1382 + xt_unregister_match(&socket_mt_reg);
1385 +module_init(socket_mt_init);
1386 +module_exit(socket_mt_exit);
1388 +MODULE_LICENSE("GPL");
1389 +MODULE_AUTHOR("Krisztian Kovacs");
1390 +MODULE_DESCRIPTION("x_tables socket match module");
1391 +MODULE_ALIAS("ipt_socket");
1395 From cb15c50f3d6419fec98bc309b5e4ea31b665cb8d Mon Sep 17 00:00:00 2001
1396 From: KOVACS Krisztian <hidden@sch.bme.hu>
1397 Date: Mon, 28 Apr 2008 14:46:52 +0200
1398 Subject: [PATCH] iptables TPROXY target
1400 The TPROXY target implements redirection of non-local TCP/UDP traffic to local
1401 sockets. Additionally, it's possible to manipulate the packet mark if and only
1402 if a socket has been found. (We need this because we cannot use multiple
1403 targets in the same iptables rule.)
1405 Signed-off-by: Jan Engelhardt <jengelh@computergmbh.de>
1406 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
1408 include/linux/netfilter/xt_TPROXY.h | 14 ++++
1409 net/netfilter/Kconfig | 15 +++++
1410 net/netfilter/Makefile | 1 +
1411 net/netfilter/xt_TPROXY.c | 112 +++++++++++++++++++++++++++++++++++
1412 4 files changed, 142 insertions(+), 0 deletions(-)
1414 diff --git a/include/linux/netfilter/xt_TPROXY.h b/include/linux/netfilter/xt_TPROXY.h
1415 new file mode 100644
1416 index 0000000..152e8f9
1418 +++ b/include/linux/netfilter/xt_TPROXY.h
1420 +#ifndef _XT_TPROXY_H_target
1421 +#define _XT_TPROXY_H_target
1423 +/* TPROXY target is capable of marking the packet to perform
1424 + * redirection. We can get rid of that whenever we get support for
1425 + * mutliple targets in the same rule. */
1426 +struct xt_tproxy_target_info {
1427 + u_int32_t mark_mask;
1428 + u_int32_t mark_value;
1433 +#endif /* _XT_TPROXY_H_target */
1434 diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig
1435 index ce21278..d36018d 100644
1436 --- a/net/netfilter/Kconfig
1437 +++ b/net/netfilter/Kconfig
1438 @@ -411,6 +411,21 @@ config NETFILTER_XT_TARGET_RATEEST
1440 To compile it as a module, choose M here. If unsure, say N.
1442 +config NETFILTER_XT_TARGET_TPROXY
1443 + tristate '"TPROXY" target support (EXPERIMENTAL)'
1444 + depends on EXPERIMENTAL
1445 + depends on NETFILTER_TPROXY
1446 + depends on NETFILTER_XTABLES
1447 + depends on NETFILTER_ADVANCED
1448 + select NF_DEFRAG_IPV4
1450 + This option adds a `TPROXY' target, which is somewhat similar to
1451 + REDIRECT. It can only be used in the mangle table and is useful
1452 + to redirect traffic to a transparent proxy. It does _not_ depend
1453 + on Netfilter connection tracking and NAT, unlike REDIRECT.
1455 + To compile it as a module, choose M here. If unsure, say N.
1457 config NETFILTER_XT_TARGET_TRACE
1458 tristate '"TRACE" target support'
1459 depends on NETFILTER_XTABLES
1460 diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile
1461 index 6d2eee6..04844d0 100644
1462 --- a/net/netfilter/Makefile
1463 +++ b/net/netfilter/Makefile
1464 @@ -51,6 +51,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o
1465 obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o
1466 obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o
1467 obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o
1468 +obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o
1469 obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o
1470 obj-$(CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP) += xt_TCPOPTSTRIP.o
1471 obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o
1472 diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c
1473 new file mode 100644
1474 index 0000000..183f251
1476 +++ b/net/netfilter/xt_TPROXY.c
1479 + * Transparent proxy support for Linux/iptables
1481 + * Copyright (c) 2006-2007 BalaBit IT Ltd.
1482 + * Author: Balazs Scheidler, Krisztian Kovacs
1484 + * This program is free software; you can redistribute it and/or modify
1485 + * it under the terms of the GNU General Public License version 2 as
1486 + * published by the Free Software Foundation.
1490 +#include <linux/module.h>
1491 +#include <linux/skbuff.h>
1492 +#include <linux/ip.h>
1493 +#include <net/checksum.h>
1494 +#include <net/udp.h>
1495 +#include <net/inet_sock.h>
1497 +#include <linux/netfilter/x_tables.h>
1498 +#include <linux/netfilter_ipv4/ip_tables.h>
1499 +#include <linux/netfilter/xt_TPROXY.h>
1501 +#include <net/netfilter/ipv4/nf_defrag_ipv4.h>
1502 +#include <net/netfilter/nf_tproxy_core.h>
1504 +static unsigned int
1505 +tproxy_tg(struct sk_buff *skb,
1506 + const struct net_device *in,
1507 + const struct net_device *out,
1508 + unsigned int hooknum,
1509 + const struct xt_target *target,
1510 + const void *targinfo)
1512 + const struct iphdr *iph = ip_hdr(skb);
1513 + const struct xt_tproxy_target_info *tgi = targinfo;
1514 + struct udphdr _hdr, *hp;
1517 + hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr);
1521 + sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol,
1522 + iph->saddr, tgi->laddr ? tgi->laddr : iph->daddr,
1523 + hp->source, tgi->lport ? tgi->lport : hp->dest,
1526 + /* NOTE: assign_sock consumes our sk reference */
1527 + if (sk && nf_tproxy_assign_sock(skb, sk)) {
1528 + /* This should be in a separate target, but we don't do multiple
1529 + targets on the same rule yet */
1530 + skb->mark = (skb->mark & ~tgi->mark_mask) ^ tgi->mark_value;
1532 + pr_debug("redirecting: proto %u %08x:%u -> %08x:%u, mark: %x\n",
1533 + iph->protocol, ntohl(iph->daddr), ntohs(hp->dest),
1534 + ntohl(tgi->laddr), ntohs(tgi->lport), skb->mark);
1538 + pr_debug("no socket, dropping: proto %u %08x:%u -> %08x:%u, mark: %x\n",
1539 + iph->protocol, ntohl(iph->daddr), ntohs(hp->dest),
1540 + ntohl(tgi->laddr), ntohs(tgi->lport), skb->mark);
1545 +tproxy_tg_check(const char *tablename,
1546 + const void *entry,
1547 + const struct xt_target *target,
1549 + unsigned int hook_mask)
1551 + const struct ipt_ip *i = entry;
1553 + if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP)
1554 + && !(i->invflags & IPT_INV_PROTO))
1557 + pr_info("xt_TPROXY: Can be used only in combination with "
1558 + "either -p tcp or -p udp\n");
1562 +static struct xt_target tproxy_tg_reg __read_mostly = {
1564 + .family = AF_INET,
1565 + .table = "mangle",
1566 + .target = tproxy_tg,
1567 + .targetsize = sizeof(struct xt_tproxy_target_info),
1568 + .checkentry = tproxy_tg_check,
1569 + .hooks = 1 << NF_INET_PRE_ROUTING,
1570 + .me = THIS_MODULE,
1573 +static int __init tproxy_tg_init(void)
1575 + nf_defrag_ipv4_enable();
1576 + return xt_register_target(&tproxy_tg_reg);
1579 +static void __exit tproxy_tg_exit(void)
1581 + xt_unregister_target(&tproxy_tg_reg);
1584 +module_init(tproxy_tg_init);
1585 +module_exit(tproxy_tg_exit);
1586 +MODULE_LICENSE("GPL");
1587 +MODULE_AUTHOR("Krisztian Kovacs");
1588 +MODULE_DESCRIPTION("Netfilter transparent proxy (TPROXY) target module.");
1589 +MODULE_ALIAS("ipt_TPROXY");
1593 From 1ba926a05e2c25585f15e7c9f895557e6a48407f Mon Sep 17 00:00:00 2001
1594 From: KOVACS Krisztian <hidden@sch.bme.hu>
1595 Date: Mon, 28 Apr 2008 14:46:53 +0200
1596 Subject: [PATCH] Don't lookup the socket if there's a socket attached to the skb
1598 Use the socket cached in the TPROXY target if it's present.
1600 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
1602 net/ipv4/tcp_ipv4.c | 9 +++++++++
1603 1 files changed, 9 insertions(+), 0 deletions(-)
1605 diff --git a/net/ipv4/tcp_ipv4.c b/net/ipv4/tcp_ipv4.c
1606 index 58873ad..8937675 100644
1607 --- a/net/ipv4/tcp_ipv4.c
1608 +++ b/net/ipv4/tcp_ipv4.c
1609 @@ -1647,8 +1647,17 @@ int tcp_v4_rcv(struct sk_buff *skb)
1610 TCP_SKB_CB(skb)->flags = iph->tos;
1611 TCP_SKB_CB(skb)->sacked = 0;
1613 +#if defined(CONFIG_NETFILTER_TPROXY) || defined(CONFIG_NETFILTER_TPROXY_MODULE)
1614 + if (unlikely(skb->sk)) {
1615 + /* steal reference */
1617 + skb->destructor = NULL;
1621 sk = __inet_lookup(dev_net(skb->dev), &tcp_hashinfo, iph->saddr,
1622 th->source, iph->daddr, th->dest, inet_iif(skb));
1630 From 8b291305fd4891a92118cf358666f25a0e42ca00 Mon Sep 17 00:00:00 2001
1631 From: KOVACS Krisztian <hidden@sch.bme.hu>
1632 Date: Mon, 28 Apr 2008 14:46:53 +0200
1633 Subject: [PATCH] Don't lookup the socket if there's a socket attached to the skb
1635 Use the socket cached in the TPROXY target if it's present.
1637 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
1639 net/ipv4/udp.c | 16 ++++++++++++++++
1640 1 files changed, 16 insertions(+), 0 deletions(-)
1642 diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c
1643 index 672d0d4..c29597c 100644
1644 --- a/net/ipv4/udp.c
1645 +++ b/net/ipv4/udp.c
1646 @@ -364,6 +364,14 @@ void __udp4_lib_err(struct sk_buff *skb, u32 info, struct hlist_head udptable[])
1650 +#if defined(CONFIG_NETFILTER_TPROXY) || defined(CONFIG_NETFILTER_TPROXY_MODULE)
1651 + if (unlikely(skb->sk)) {
1652 + /* steal reference */
1654 + skb->destructor = NULL;
1658 sk = __udp4_lib_lookup(dev_net(skb->dev), iph->daddr, uh->dest,
1659 iph->saddr, uh->source, skb->dev->ifindex, udptable);
1661 @@ -1188,6 +1196,14 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],
1662 if (rt->rt_flags & (RTCF_BROADCAST|RTCF_MULTICAST))
1663 return __udp4_lib_mcast_deliver(skb, uh, saddr, daddr, udptable);
1665 +#if defined(CONFIG_NETFILTER_TPROXY) || defined(CONFIG_NETFILTER_TPROXY_MODULE)
1666 + if (unlikely(skb->sk)) {
1667 + /* steal reference */
1669 + skb->destructor = NULL;
1673 sk = __udp4_lib_lookup(dev_net(skb->dev), saddr, uh->source, daddr,
1674 uh->dest, inet_iif(skb), udptable);
1679 From 6e33de49987ecc73930148c88f07f61527929dcc Mon Sep 17 00:00:00 2001
1680 From: KOVACS Krisztian <hidden@sch.bme.hu>
1681 Date: Mon, 28 Apr 2008 14:46:53 +0200
1682 Subject: [PATCH] Add documentation
1684 Add basic usage instructions to Documentation/networking.
1686 Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
1688 Documentation/networking/tproxy.txt | 62 +++++++++++++++++++++++++++++++++++
1689 1 files changed, 62 insertions(+), 0 deletions(-)
1691 diff --git a/Documentation/networking/tproxy.txt b/Documentation/networking/tproxy.txt
1692 new file mode 100644
1693 index 0000000..dfcb613
1695 +++ b/Documentation/networking/tproxy.txt
1697 +Transparent proxy support
1698 +=========================
1700 +This feature adds Linux 2.2-like transparent proxy support to current kernels.
1701 +To use it, enable NETFILTER_TPROXY, the socket match and the TPROXY target in
1702 +your kernel config. You will need policy routing too, so be sure to enable that
1705 +1. Making non-local sockets work
1706 +================================
1708 +The idea is that you identify packets with destination address matching a local
1709 +socket your box, set the packet mark to a certain value, and then match on that
1710 +value using policy routing to have those packets delivered locally:
1712 +# iptables -t mangle -N DIVERT
1713 +# iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
1714 +# iptables -t mangle -A DIVERT -j MARK --set-mark 1
1715 +# iptables -t mangle -A DIVERT -j ACCEPT
1717 +# ip rule add fwmark 1 lookup 100
1718 +# ip route add local 0.0.0.0/0 dev lo table 100
1720 +Because of certain restrictions in the IPv4 routing output code you'll have to
1721 +modify your application to allow it sending datagrams _from_ non-local IP
1722 +addresses. All you have to do is to enable the (SOL_IP, IP_TRANSPARENT) socket
1723 +option before calling bind:
1725 +fd = socket(AF_INET, SOCK_STREAM, 0);
1728 +setsockopt(fd, SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
1730 +name.sin_family = AF_INET;
1731 +name.sin_port = htons(0xCAFE);
1732 +name.sin_addr.s_addr = htonl(0xDEADBEEF);
1733 +bind(fd, &name, sizeof(name));
1735 +A trivial patch for netcat is available here:
1736 +http://people.netfilter.org/hidden/tproxy/netcat-ip_transparent-support.patch
1739 +2. Redirecting traffic
1740 +======================
1742 +Transparent proxying often involves "intercepting" traffic on a router. This is
1743 +usually done with the iptables REDIRECT target, however, there are serious
1744 +limitations of that method. One of the major issues is that it actually
1745 +modifies the packets to change the destination address -- which might not be
1746 +acceptable in certain situations. (Think of proxying UDP for example: you won't
1747 +be able to find out the original destination address. Even in case of TCP
1748 +getting the original destination address is racy.)
1750 +The 'TPROXY' target provides similar functionality without relying on NAT. Simply
1751 +add rules like this to the iptables ruleset above:
1753 +# iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY \
1754 + --tproxy-mark 0x1/0x1 --on-port 50080
1756 +Note that for this to work you'll have to modify the proxy to enable (SOL_IP,
1757 +IP_TRANSPARENT) for the listening socket.