diff options
author | KOVACS Krisztian <hidden@sch.bme.hu> | 2008-10-08 11:35:12 +0200 |
---|---|---|
committer | Patrick McHardy <kaber@trash.net> | 2008-10-08 11:35:12 +0200 |
commit | e84392707e10301b93121e1b74e2823db50cdf9e (patch) | |
tree | d58858f585f9cc266928d3ec2be103922258fa97 /net | |
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>
Diffstat (limited to 'net')
-rw-r--r-- | net/netfilter/Kconfig | 15 | ||||
-rw-r--r-- | net/netfilter/Makefile | 1 | ||||
-rw-r--r-- | net/netfilter/xt_TPROXY.c | 112 |
3 files changed, 128 insertions, 0 deletions
diff --git a/net/netfilter/Kconfig b/net/netfilter/Kconfig index f6c80729948..de18bba619f 100644 --- a/net/netfilter/Kconfig +++ b/net/netfilter/Kconfig @@ -421,6 +421,21 @@ config NETFILTER_XT_TARGET_RATEEST To compile it as a module, choose M here. If unsure, say N. +config NETFILTER_XT_TARGET_TPROXY + tristate '"TPROXY" target support (EXPERIMENTAL)' + depends on EXPERIMENTAL + depends on NETFILTER_TPROXY + depends on NETFILTER_XTABLES + depends on NETFILTER_ADVANCED + select NF_DEFRAG_IPV4 + help + This option adds a `TPROXY' target, which is somewhat similar to + REDIRECT. It can only be used in the mangle table and is useful + to redirect traffic to a transparent proxy. It does _not_ depend + on Netfilter connection tracking and NAT, unlike REDIRECT. + + To compile it as a module, choose M here. If unsure, say N. + config NETFILTER_XT_TARGET_TRACE tristate '"TRACE" target support' depends on NETFILTER_XTABLES diff --git a/net/netfilter/Makefile b/net/netfilter/Makefile index 1cdc3a13d01..8ce67665882 100644 --- a/net/netfilter/Makefile +++ b/net/netfilter/Makefile @@ -51,6 +51,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_NFQUEUE) += xt_NFQUEUE.o obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o obj-$(CONFIG_NETFILTER_XT_TARGET_RATEEST) += xt_RATEEST.o obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o +obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o obj-$(CONFIG_NETFILTER_XT_TARGET_TCPOPTSTRIP) += xt_TCPOPTSTRIP.o 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 00000000000..183f251d2f0 --- /dev/null +++ b/net/netfilter/xt_TPROXY.c @@ -0,0 +1,112 @@ +/* + * Transparent proxy support for Linux/iptables + * + * Copyright (c) 2006-2007 BalaBit IT Ltd. + * Author: Balazs Scheidler, Krisztian Kovacs + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + */ + +#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/ip.h> +#include <net/checksum.h> +#include <net/udp.h> +#include <net/inet_sock.h> + +#include <linux/netfilter/x_tables.h> +#include <linux/netfilter_ipv4/ip_tables.h> +#include <linux/netfilter/xt_TPROXY.h> + +#include <net/netfilter/ipv4/nf_defrag_ipv4.h> +#include <net/netfilter/nf_tproxy_core.h> + +static unsigned int +tproxy_tg(struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + unsigned int hooknum, + const struct xt_target *target, + const void *targinfo) +{ + const struct iphdr *iph = ip_hdr(skb); + const struct xt_tproxy_target_info *tgi = targinfo; + struct udphdr _hdr, *hp; + struct sock *sk; + + hp = skb_header_pointer(skb, ip_hdrlen(skb), sizeof(_hdr), &_hdr); + if (hp == NULL) + return NF_DROP; + + sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), iph->protocol, + iph->saddr, tgi->laddr ? tgi->laddr : iph->daddr, + hp->source, tgi->lport ? tgi->lport : hp->dest, + in, true); + + /* NOTE: assign_sock consumes our sk reference */ + if (sk && nf_tproxy_assign_sock(skb, sk)) { + /* This should be in a separate target, but we don't do multiple + targets on the same rule yet */ + skb->mark = (skb->mark & ~tgi->mark_mask) ^ tgi->mark_value; + + pr_debug("redirecting: proto %u %08x:%u -> %08x:%u, mark: %x\n", + iph->protocol, ntohl(iph->daddr), ntohs(hp->dest), + ntohl(tgi->laddr), ntohs(tgi->lport), skb->mark); + return NF_ACCEPT; + } + + pr_debug("no socket, dropping: proto %u %08x:%u -> %08x:%u, mark: %x\n", + iph->protocol, ntohl(iph->daddr), ntohs(hp->dest), + ntohl(tgi->laddr), ntohs(tgi->lport), skb->mark); + return NF_DROP; +} + +static bool +tproxy_tg_check(const char *tablename, + const void *entry, + const struct xt_target *target, + void *targetinfo, + unsigned int hook_mask) +{ + const struct ipt_ip *i = entry; + + if ((i->proto == IPPROTO_TCP || i->proto == IPPROTO_UDP) + && !(i->invflags & IPT_INV_PROTO)) + return true; + + pr_info("xt_TPROXY: Can be used only in combination with " + "either -p tcp or -p udp\n"); + return false; +} + +static struct xt_target tproxy_tg_reg __read_mostly = { + .name = "TPROXY", + .family = AF_INET, + .table = "mangle", + .target = tproxy_tg, + .targetsize = sizeof(struct xt_tproxy_target_info), + .checkentry = tproxy_tg_check, + .hooks = 1 << NF_INET_PRE_ROUTING, + .me = THIS_MODULE, +}; + +static int __init tproxy_tg_init(void) +{ + nf_defrag_ipv4_enable(); + return xt_register_target(&tproxy_tg_reg); +} + +static void __exit tproxy_tg_exit(void) +{ + xt_unregister_target(&tproxy_tg_reg); +} + +module_init(tproxy_tg_init); +module_exit(tproxy_tg_exit); +MODULE_LICENSE("GPL"); +MODULE_AUTHOR("Krisztian Kovacs"); +MODULE_DESCRIPTION("Netfilter transparent proxy (TPROXY) target module."); +MODULE_ALIAS("ipt_TPROXY"); |