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