Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 364ae953 authored by David S. Miller's avatar David S. Miller
Browse files
parents 075f6646 f39a9410
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -250,6 +250,9 @@ What (Why):
	- xt_mark match revision 0
	  (superseded by xt_mark match revision 1)

	- xt_recent: the old ipt_recent proc dir
	  (superseded by /proc/net/xt_recent)

When:	January 2009 or Linux 2.7.0, whichever comes first
Why:	Superseded by newer revisions or modules
Who:	Jan Engelhardt <jengelh@computergmbh.de>
+85 −0
Original line number Diff line number Diff line
Transparent proxy support
=========================

This feature adds Linux 2.2-like transparent proxy support to current kernels.
To use it, enable NETFILTER_TPROXY, the socket match and the TPROXY target in
your kernel config. You will need policy routing too, so be sure to enable that
as well.


1. Making non-local sockets work
================================

The idea is that you identify packets with destination address matching a local
socket on your box, set the packet mark to a certain value, and then match on that
value using policy routing to have those packets delivered locally:

# iptables -t mangle -N DIVERT
# iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT
# iptables -t mangle -A DIVERT -j MARK --set-mark 1
# iptables -t mangle -A DIVERT -j ACCEPT

# ip rule add fwmark 1 lookup 100
# ip route add local 0.0.0.0/0 dev lo table 100

Because of certain restrictions in the IPv4 routing output code you'll have to
modify your application to allow it to send datagrams _from_ non-local IP
addresses. All you have to do is enable the (SOL_IP, IP_TRANSPARENT) socket
option before calling bind:

fd = socket(AF_INET, SOCK_STREAM, 0);
/* - 8< -*/
int value = 1;
setsockopt(fd, SOL_IP, IP_TRANSPARENT, &value, sizeof(value));
/* - 8< -*/
name.sin_family = AF_INET;
name.sin_port = htons(0xCAFE);
name.sin_addr.s_addr = htonl(0xDEADBEEF);
bind(fd, &name, sizeof(name));

A trivial patch for netcat is available here:
http://people.netfilter.org/hidden/tproxy/netcat-ip_transparent-support.patch


2. Redirecting traffic
======================

Transparent proxying often involves "intercepting" traffic on a router. This is
usually done with the iptables REDIRECT target; however, there are serious
limitations of that method. One of the major issues is that it actually
modifies the packets to change the destination address -- which might not be
acceptable in certain situations. (Think of proxying UDP for example: you won't
be able to find out the original destination address. Even in case of TCP
getting the original destination address is racy.)

The 'TPROXY' target provides similar functionality without relying on NAT. Simply
add rules like this to the iptables ruleset above:

# iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY \
  --tproxy-mark 0x1/0x1 --on-port 50080

Note that for this to work you'll have to modify the proxy to enable (SOL_IP,
IP_TRANSPARENT) for the listening socket.


3. Iptables extensions
======================

To use tproxy you'll need to have the 'socket' and 'TPROXY' modules
compiled for iptables. A patched version of iptables is available
here: http://git.balabit.hu/?p=bazsi/iptables-tproxy.git


4. Application support
======================

4.1. Squid
----------

Squid 3.HEAD has support built-in. To use it, pass
'--enable-linux-netfilter' to configure and set the 'tproxy' option on
the HTTP listener you redirect traffic to with the TPROXY iptables
target.

For more information please consult the following page on the Squid
wiki: http://wiki.squid-cache.org/Features/Tproxy4
+28 −69
Original line number Diff line number Diff line
@@ -5,13 +5,11 @@
#include <linux/init.h>
#include <linux/skbuff.h>
#include <linux/net.h>
#include <linux/netdevice.h>
#include <linux/if.h>
#include <linux/in.h>
#include <linux/in6.h>
#include <linux/wait.h>
#include <linux/list.h>
#include <net/net_namespace.h>
#endif
#include <linux/types.h>
#include <linux/compiler.h>
@@ -52,6 +50,16 @@ enum nf_inet_hooks {
	NF_INET_NUMHOOKS
};

enum {
	NFPROTO_UNSPEC =  0,
	NFPROTO_IPV4   =  2,
	NFPROTO_ARP    =  3,
	NFPROTO_BRIDGE =  7,
	NFPROTO_IPV6   = 10,
	NFPROTO_DECNET = 12,
	NFPROTO_NUMPROTO,
};

union nf_inet_addr {
	__u32		all[4];
	__be32		ip;
@@ -92,8 +100,8 @@ struct nf_hook_ops
	/* User fills in from here down. */
	nf_hookfn *hook;
	struct module *owner;
	int pf;
	int hooknum;
	u_int8_t pf;
	unsigned int hooknum;
	/* Hooks are ordered in ascending priority. */
	int priority;
};
@@ -102,7 +110,7 @@ struct nf_sockopt_ops
{
	struct list_head list;

	int pf;
	u_int8_t pf;

	/* Non-inclusive ranges: use 0/0/NULL to never get called. */
	int set_optmin;
@@ -138,9 +146,9 @@ extern struct ctl_path nf_net_netfilter_sysctl_path[];
extern struct ctl_path nf_net_ipv4_netfilter_sysctl_path[];
#endif /* CONFIG_SYSCTL */

extern struct list_head nf_hooks[NPROTO][NF_MAX_HOOKS];
extern struct list_head nf_hooks[NFPROTO_NUMPROTO][NF_MAX_HOOKS];

int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
int nf_hook_slow(u_int8_t pf, unsigned int hook, struct sk_buff *skb,
		 struct net_device *indev, struct net_device *outdev,
		 int (*okfn)(struct sk_buff *), int thresh);

@@ -151,7 +159,7 @@ int nf_hook_slow(int pf, unsigned int hook, struct sk_buff *skb,
 *	okfn must be invoked by the caller in this case.  Any other return
 *	value indicates the packet has been consumed by the hook.
 */
static inline int nf_hook_thresh(int pf, unsigned int hook,
static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,
				 struct sk_buff *skb,
				 struct net_device *indev,
				 struct net_device *outdev,
@@ -167,7 +175,7 @@ static inline int nf_hook_thresh(int pf, unsigned int hook,
	return nf_hook_slow(pf, hook, skb, indev, outdev, okfn, thresh);
}

static inline int nf_hook(int pf, unsigned int hook, struct sk_buff *skb,
static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sk_buff *skb,
			  struct net_device *indev, struct net_device *outdev,
			  int (*okfn)(struct sk_buff *))
{
@@ -212,14 +220,14 @@ __ret;})
	NF_HOOK_THRESH(pf, hook, skb, indev, outdev, okfn, INT_MIN)

/* Call setsockopt() */
int nf_setsockopt(struct sock *sk, int pf, int optval, char __user *opt, 
int nf_setsockopt(struct sock *sk, u_int8_t pf, int optval, char __user *opt,
		  int len);
int nf_getsockopt(struct sock *sk, int pf, int optval, char __user *opt,
int nf_getsockopt(struct sock *sk, u_int8_t pf, int optval, char __user *opt,
		  int *len);

int compat_nf_setsockopt(struct sock *sk, int pf, int optval,
int compat_nf_setsockopt(struct sock *sk, u_int8_t pf, int optval,
		char __user *opt, int len);
int compat_nf_getsockopt(struct sock *sk, int pf, int optval,
int compat_nf_getsockopt(struct sock *sk, u_int8_t pf, int optval,
		char __user *opt, int *len);

/* Call this before modifying an existing packet: ensures it is
@@ -247,7 +255,7 @@ struct nf_afinfo {
	int		route_key_size;
};

extern const struct nf_afinfo *nf_afinfo[NPROTO];
extern const struct nf_afinfo *nf_afinfo[NFPROTO_NUMPROTO];
static inline const struct nf_afinfo *nf_get_afinfo(unsigned short family)
{
	return rcu_dereference(nf_afinfo[family]);
@@ -292,7 +300,7 @@ extern void nf_unregister_afinfo(const struct nf_afinfo *afinfo);
extern void (*ip_nat_decode_session)(struct sk_buff *, struct flowi *);

static inline void
nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family)
nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
{
#ifdef CONFIG_NF_NAT_NEEDED
	void (*decodefn)(struct sk_buff *, struct flowi *);
@@ -315,7 +323,7 @@ extern struct proc_dir_entry *proc_net_netfilter;
#else /* !CONFIG_NETFILTER */
#define NF_HOOK(pf, hook, skb, indev, outdev, okfn) (okfn)(skb)
#define NF_HOOK_COND(pf, hook, skb, indev, outdev, okfn, cond) (okfn)(skb)
static inline int nf_hook_thresh(int pf, unsigned int hook,
static inline int nf_hook_thresh(u_int8_t pf, unsigned int hook,
				 struct sk_buff *skb,
				 struct net_device *indev,
				 struct net_device *outdev,
@@ -324,7 +332,7 @@ static inline int nf_hook_thresh(int pf, unsigned int hook,
{
	return okfn(skb);
}
static inline int nf_hook(int pf, unsigned int hook, struct sk_buff *skb,
static inline int nf_hook(u_int8_t pf, unsigned int hook, struct sk_buff *skb,
			  struct net_device *indev, struct net_device *outdev,
			  int (*okfn)(struct sk_buff *))
{
@@ -332,7 +340,9 @@ static inline int nf_hook(int pf, unsigned int hook, struct sk_buff *skb,
}
struct flowi;
static inline void
nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, int family) {}
nf_nat_decode_session(struct sk_buff *skb, struct flowi *fl, u_int8_t family)
{
}
#endif /*CONFIG_NETFILTER*/

#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
@@ -343,56 +353,5 @@ extern void (*nf_ct_destroy)(struct nf_conntrack *);
static inline void nf_ct_attach(struct sk_buff *new, struct sk_buff *skb) {}
#endif

static inline struct net *nf_pre_routing_net(const struct net_device *in,
					     const struct net_device *out)
{
#ifdef CONFIG_NET_NS
	return in->nd_net;
#else
	return &init_net;
#endif
}

static inline struct net *nf_local_in_net(const struct net_device *in,
					  const struct net_device *out)
{
#ifdef CONFIG_NET_NS
	return in->nd_net;
#else
	return &init_net;
#endif
}

static inline struct net *nf_forward_net(const struct net_device *in,
					 const struct net_device *out)
{
#ifdef CONFIG_NET_NS
	BUG_ON(in->nd_net != out->nd_net);
	return in->nd_net;
#else
	return &init_net;
#endif
}

static inline struct net *nf_local_out_net(const struct net_device *in,
					   const struct net_device *out)
{
#ifdef CONFIG_NET_NS
	return out->nd_net;
#else
	return &init_net;
#endif
}

static inline struct net *nf_post_routing_net(const struct net_device *in,
					      const struct net_device *out)
{
#ifdef CONFIG_NET_NS
	return out->nd_net;
#else
	return &init_net;
#endif
}

#endif /*__KERNEL__*/
#endif /*__LINUX_NETFILTER_H*/
+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ header-y += xt_owner.h
header-y += xt_pkttype.h
header-y += xt_rateest.h
header-y += xt_realm.h
header-y += xt_recent.h
header-y += xt_sctp.h
header-y += xt_state.h
header-y += xt_statistic.h
+1 −1
Original line number Diff line number Diff line
@@ -87,7 +87,7 @@ int nf_ct_gre_keymap_add(struct nf_conn *ct, enum ip_conntrack_dir dir,
/* delete keymap entries */
void nf_ct_gre_keymap_destroy(struct nf_conn *ct);

extern void nf_ct_gre_keymap_flush(void);
extern void nf_ct_gre_keymap_flush(struct net *net);
extern void nf_nat_need_gre(void);

#endif /* __KERNEL__ */
Loading