Loading Documentation/feature-removal-schedule.txt +3 −0 Original line number Diff line number Diff line Loading @@ -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> Loading Documentation/networking/tproxy.txt 0 → 100644 +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 include/linux/netfilter.h +28 −69 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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; Loading Loading @@ -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; }; Loading @@ -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; Loading Loading @@ -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); Loading @@ -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, Loading @@ -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 *)) { Loading Loading @@ -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 Loading Loading @@ -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]); Loading Loading @@ -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 *); Loading @@ -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, Loading @@ -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 *)) { Loading @@ -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) Loading @@ -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*/ include/linux/netfilter/Kbuild +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading include/linux/netfilter/nf_conntrack_proto_gre.h +1 −1 Original line number Diff line number Diff line Loading @@ -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 Loading
Documentation/feature-removal-schedule.txt +3 −0 Original line number Diff line number Diff line Loading @@ -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> Loading
Documentation/networking/tproxy.txt 0 → 100644 +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
include/linux/netfilter.h +28 −69 Original line number Diff line number Diff line Loading @@ -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> Loading Loading @@ -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; Loading Loading @@ -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; }; Loading @@ -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; Loading Loading @@ -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); Loading @@ -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, Loading @@ -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 *)) { Loading Loading @@ -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 Loading Loading @@ -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]); Loading Loading @@ -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 *); Loading @@ -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, Loading @@ -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 *)) { Loading @@ -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) Loading @@ -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*/
include/linux/netfilter/Kbuild +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
include/linux/netfilter/nf_conntrack_proto_gre.h +1 −1 Original line number Diff line number Diff line Loading @@ -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