diff options
author | KOVACS Krisztian <hidden@sch.bme.hu> | 2008-10-08 05:35:12 -0400 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2008-10-08 05:35:12 -0400 |
commit | e84392707e10301b93121e1b74e2823db50cdf9e (patch) | |
tree | d58858f585f9cc266928d3ec2be103922258fa97 | |
parent | 136cdc71fd54e77463e570643ac76e2b696e48a0 (diff) |
netfilter: iptables TPROXY target
The TPROXY target implements redirection of non-local TCP/UDP traffic to local
sockets. Additionally, it's possible to manipulate the packet mark if and only
if a socket has been found. (We need this because we cannot use multiple
targets in the same iptables rule.)
Signed-off-by: KOVACS Krisztian <hidden@sch.bme.hu>
Signed-off-by: Patrick McHardy <kaber@trash.net>
-rw-r--r-- | include/linux/netfilter/xt_TPROXY.h | 14 | ||||
-rw-r--r-- | net/netfilter/Kconfig | 15 | ||||
-rw-r--r-- | net/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/netfilter/xt_TPROXY.c | 112 |
4 files changed, 142 insertions, 0 deletions
diff --git a/include/linux/netfilter/xt_TPROXY.h b/include/linux/netfilter/xt_TPROXY.h new file mode 100644 index 000000000000..152e8f97132b --- /dev/null +++ b/include/linux/netfilter/xt_TPROXY.h | |||
@@ -0,0 +1,14 @@ | |||
1 | #ifndef _XT_TPROXY_H_target | ||
2 | #define _XT_TPROXY_H_target | ||
3 | |||
4 | /* TPROXY target is capable of marking the packet to perform | ||
5 | * redirection. We can get rid of that whenever we get support for | ||
6 | * mutliple targets in the same rule. */ | ||
7 | struct xt_tproxy_target_info { | ||
8 | u_int32_t mark_mask; | ||
9 | u_int32_t mark_value; | ||
10 | __be32 laddr; | ||
11 | __be16 lport; | ||
12 | }; | ||
13 | |||
14 | #endif /* _XT_TPROXY_H_target */ | ||
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index f6c807299487..de18bba619f2 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig | |||
@@ -421,6 +421,21 @@ config NETFILTER_XT_TARGET_RATEEST | |||
421 | 421 | ||
422 | To compile it as a module, choose M here. If unsure, say N. | 422 | To compile it as a module, choose M here. If unsure, say N. |
423 | 423 | ||
424 | config NETFILTER_XT_TARGET_TPROXY | ||
425 | tristate '"TPROXY" target support (EXPERIMENTAL)' | ||
426 | depends on EXPERIMENTAL | ||
427 | depends on NETFILTER_TPROXY | ||
428 | depends on NETFILTER_XTABLES | ||
429 | depends on NETFILTER_ADVANCED | ||
430 | select NF_DEFRAG_IPV4 | ||
431 | help | ||
432 | This option adds a `TPROXY' target, which is somewhat similar to | ||
433 | REDIRECT. It can only be used in the mangle table and is useful | ||
434 | to redirect traffic to a transparent proxy. It does _not_ depend | ||
435 | on Netfilter connection tracking and NAT, unlike REDIRECT. | ||
436 | |||
437 | To compile it as a module, choose M here. If unsure, say N. | ||
438 | |||
424 | config NETFILTER_XT_TARGET_TRACE | 439 | config NETFILTER_XT_TARGET_TRACE |
425 | tristate '"TRACE" target support' | 440 | tristate '"TRACE" target support' |
426 | depends on NETFILTER_XTABLES | 441 | depends on NETFILTER_XTABLES |
diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 1cdc3a13d01f..8ce67665882d 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile | |||
@@ -51,6 +51,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o | |||
51 | obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o | 51 | obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o |
52 | obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o | 52 | obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o |
53 | obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o | 53 | obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o |
54 | obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o | ||
54 | obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o | 55 | obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o |
55 | obj-$(CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP) += xt_TCPOPTSTRIP.o | 56 | obj-$(CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP) += xt_TCPOPTSTRIP.o |
56 | obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o | 57 | obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.o |
diff --git a/net/netfilter/xt_TPROXY.c b/net/netfilter/xt_TPROXY.c new file mode 100644 index 000000000000..183f251d2f06 --- /dev/null +++ b/net/netfilter/xt_TPROXY.c | |||
@@ -0,0 +1,112 @@ | |||
1 | /* | ||
2 | * Transparent proxy support for Linux/iptables | ||
3 | * | ||
4 | * Copyright (c) 2006-2007 BalaBit IT Ltd. | ||
5 | * Author: Balazs Scheidler, Krisztian Kovacs | ||
6 | * | ||
7 | * This program is free software; you can redistribute it and/or modify | ||
8 | * it under the terms of the GNU General Public License version 2 as | ||
9 | * published by the Free Software Foundation. | ||
10 | * | ||
11 | */ | ||
12 | |||
13 | #include <linux/module.h> | ||
14 | #include <linux/skbuff.h> | ||
15 | #include <linux/ip.h> | ||
16 | #include <net/checksum.h> | ||
17 | #include <net/udp.h> | ||
18 | #include <net/inet_sock.h> | ||
19 | |||
20 | #include <linux/netfilter/x_tables.h> | ||
21 | #include <linux/netfilter_ipv4/ip_tables.h> | ||
22 | #include <linux/netfilter/xt_TPROXY.h> | ||
23 | |||
24 | #include <net/netfilter/ipv4/nf_defrag_ipv4.h> | ||
25 | #include <net/netfilter/nf_tproxy_core.h> | ||
26 | |||
27 | static unsigned int | ||
28 | tproxy_tg(struct sk_buff *skb, | ||
29 | const struct net_device *in, | ||
30 | const struct net_device *out, | ||
31 | unsigned int hooknum, | ||
32 | const struct xt_target *target, | ||
33 | const void *targinfo) | ||
34 | { | ||
35 | const struct iphdr *iph = ip_hdr(skb); | ||
36 | const struct xt_tproxy_target_info *tgi = targinfo; | ||
37 | struct udphdr _hdr, *hp; | ||
38 | struct sock *sk; | ||
39 | |||
40 | hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr); | ||
41 | if (hp == NULL) | ||
42 | return NF_DROP; | ||
43 | |||
44 | sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol, | ||
45 | iph->saddr, tgi->laddr ? tgi->laddr : iph->daddr, | ||
46 | hp->source, tgi->lport ? tgi->lport : hp->dest, | ||
47 | in, true); | ||
48 | |||
49 | /* NOTE: assign_sock consumes our sk reference */ | ||
50 | if (sk && nf_tproxy_assign_sock(skb, sk)) { | ||
51 | /* This should be in a separate target, but we don't do multiple | ||
52 | targets on the same rule yet */ | ||
53 | skb->mark = (skb->mark & ~tgi->mark_mask) ^ tgi->mark_value; | ||
54 | |||
55 | pr_debug("redirecting: proto %u %08x:%u -> %08x:%u, mark: %x\n", | ||
56 | iph->protocol, ntohl(iph->daddr), ntohs(hp->dest), | ||
57 | ntohl(tgi->laddr), ntohs(tgi->lport), skb->mark); | ||
58 | return NF_ACCEPT; | ||
59 | } | ||
60 | |||
61 | pr_debug("no socket, dropping: proto %u %08x:%u -> %08x:%u, mark: %x\n", | ||
62 | iph->protocol, ntohl(iph->daddr), ntohs(hp->dest), | ||
63 | ntohl(tgi->laddr), ntohs(tgi->lport), skb->mark); | ||
64 | return NF_DROP; | ||
65 | } | ||
66 | |||
67 | static bool | ||
68 | tproxy_tg_check(const char *tablename, | ||
69 | const void *entry, | ||
70 | const struct xt_target *target, | ||
71 | void *targetinfo, | ||
72 | unsigned int hook_mask) | ||
73 | { | ||
74 | const struct ipt_ip *i = entry; | ||
75 | |||
76 | if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP) | ||
77 | && !(i->invflags & IPT_INV_PROTO)) | ||
78 | return true; | ||
79 | |||
80 | pr_info("xt_TPROXY: Can be used only in combination with " | ||
81 | "either -p tcp or -p udp\n"); | ||
82 | return false; | ||
83 | } | ||
84 | |||
85 | static struct xt_target tproxy_tg_reg __read_mostly = { | ||
86 | .name = "TPROXY", | ||
87 | .family = AF_INET, | ||
88 | .table = "mangle", | ||
89 | .target = tproxy_tg, | ||
90 | .targetsize = sizeof(struct xt_tproxy_target_info), | ||
91 | .checkentry = tproxy_tg_check, | ||
92 | .hooks = 1 << NF_INET_PRE_ROUTING, | ||
93 | .me = THIS_MODULE, | ||
94 | }; | ||
95 | |||
96 | static int __init tproxy_tg_init(void) | ||
97 | { | ||
98 | nf_defrag_ipv4_enable(); | ||
99 | return xt_register_target(&tproxy_tg_reg); | ||
100 | } | ||
101 | |||
102 | static void __exit tproxy_tg_exit(void) | ||
103 | { | ||
104 | xt_unregister_target(&tproxy_tg_reg); | ||
105 | } | ||
106 | |||
107 | module_init(tproxy_tg_init); | ||
108 | module_exit(tproxy_tg_exit); | ||
109 | MODULE_LICENSE("GPL"); | ||
110 | MODULE_AUTHOR("Krisztian Kovacs"); | ||
111 | MODULE_DESCRIPTION("Netfilter transparent proxy (TPROXY) target module."); | ||
112 | MODULE_ALIAS("ipt_TPROXY"); | ||