Transparent Proxying Patches, Take 4
Subsystems (5)
cover Transparent Proxying Patches, Take 4
Hi Patrick,
Here's the next round of tproxy patches, hopefully fixing problems which came up last time I've posted these patches[1].
I'd like to thank you and Jan Engelhardt the huge help you've provided. (Jan himself did a lot of fixes/cleanups!)
The most important changes relative to the previous versions[1] are:
* the patch implementing the propagation of IP_TRANSPARENT to routing output now does not change the signature of request_sock_opt.send_ack but uses a flag in inet_request_sock itself
* TCP port redirection support patch
adds loc_port to struct inet_request_sock unconditionally
* TPROXY target is an xt_* target now and has proper 32 bit mark values in the target info structure
Additionally there are code cleanups all over the place (thanks Jan).
References:
[1] http://marc.info/?l=netfilter-devel&m=119118672703285&w=2
Signature · 1 line
KOVACS Krisztian
PATCH 1/13 Loosen source address check on IPv4 output
ip_route_output() contains a check to make sure that no flows with non-local source IP addresses are routed. This obviously makes using such addresses impossible.
This patch introduces a flowi flag which makes omitting this check possible. The new flag provides a way of handling transparent and non-transparent connections differently.
---
include/net/flow.h | 1 + net/ipv4/route.c | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 7 deletions(-)
include/net/flow.h +1 -0
@@ -49,6 +49,7 @@ struct flowi {__u8 proto;__u8 flags;#define FLOWI_FLAG_MULTIPATHOLDROUTE 0x01 +#define FLOWI_FLAG_ANYSRC 0x02 union { struct { __be16 sport;
net/ipv4/route.c +13 -7
@@ -2172,11 +2172,6 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp) ZERONET(oldflp->fl4_src)) goto out; -/* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ - dev_out =ip_dev_find (oldflp->fl4_src); -if (dev_out ==NULL ) - goto out; -/* I removed check for oif == dev_out->oif here. It was wrong for two reasons: 1. ip_dev_find(saddr) can return wrong iface, if saddr is
@@ -2187,6 +2182,11 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp)if (oldflp->oif ==0 && (MULTICAST (oldflp->fl4_dst) || oldflp->fl4_dst ==htonl (0xFFFFFFFF ))) { +/* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ + dev_out =ip_dev_find (oldflp->fl4_src); +if (dev_out ==NULL ) + goto out; +/* Special hack: user can direct multicasts and limited broadcast via necessary interface without fiddling with IP_MULTICAST_IF or IP_PKTINFO.
@@ -2205,9 +2205,15 @@ static int ip_route_output_slow(struct rtable **rp, const struct flowi *oldflp) fl.oif = dev_out->ifindex; goto make_route; } -if (dev_out) + +if (!(oldflp->flags &FLOWI_FLAG_ANYSRC )) { +/* It is equivalent to inet_addr_type(saddr) == RTN_LOCAL */ + dev_out =ip_dev_find (oldflp->fl4_src); +if (dev_out ==NULL ) + goto out;dev_put (dev_out); - dev_out =NULL ; + dev_out =NULL ; + } }
PATCH 2/13 Implement IP_TRANSPARENT socket option
In reply to KOVACS KrisztianThis patch introduces the IP_TRANSPARENT socket option: enabling that will make the IPv4 routing omit the non-local source address check on output. Setting IP_TRANSPARENT requires NET_ADMIN capability.
---
include/linux/in.h | 1 + include/net/inet_sock.h | 3 ++- include/net/inet_timewait_sock.h | 3 ++- include/net/route.h | 1 + net/ipv4/inet_timewait_sock.c | 1 + net/ipv4/ip_sockglue.c | 12 +++++++++++- 6 files changed, 18 insertions(+), 3 deletions(-)
include/linux/in.h +1 -0
@@ -75,6 +75,7 @@ struct in_addr {#define IP_IPSEC_POLICY 16#define IP_XFRM_POLICY 17#define IP_PASSSEC 18 +#define IP_TRANSPARENT 19/* BSD compatibility */ #define IP_RECVRETOPTS IP_RETOPTS
include/net/inet_sock.h +2 -1
@@ -128,7 +128,8 @@ struct inet_sock { is_icsk:1, freebind:1, hdrincl:1, - mc_loop:1; + mc_loop:1, + transparent:1;int mc_index;__be32 mc_addr;struct ip_mc_socklist *mc_list;
include/net/inet_timewait_sock.h +2 -1
@@ -126,7 +126,8 @@ struct inet_timewait_sock {__be16 tw_dport;__u16 tw_num;/* And these are ours. */ - __u8 tw_ipv6only:1; + __u8 tw_ipv6only:1, + tw_transparent:1;/* 15 bits hole, try to pack */ __u16 tw_ipv6_offset;int tw_timeout;
include/net/route.h +1 -0
@@ -27,6 +27,7 @@#include <net/dst.h> #include <net/inetpeer.h> #include <net/flow.h> +#include <net/inet_sock.h> #include <linux/in_route.h> #include <linux/rtnetlink.h> #include <linux/route.h>
net/ipv4/inet_timewait_sock.c +1 -0
@@ -107,6 +107,7 @@ struct inet_timewait_sock *inet_twsk_alloc(const struct sock *sk, const int stat tw->tw_reuse = sk->sk_reuse; tw->tw_hash = sk->sk_hash; tw->tw_ipv6only =0 ; + tw->tw_transparent = inet->transparent; tw->tw_prot = sk->sk_prot_creator;atomic_set (&tw->tw_refcnt,1 );inet_twsk_dead_node_init (tw);
net/ipv4/ip_sockglue.c +11 -1
@@ -420,7 +420,7 @@ static int do_ip_setsockopt(struct sock *sk, int level, (1 <<IP_TTL ) | (1 <<IP_HDRINCL ) | (1 <<IP_MTU_DISCOVER ) | (1 <<IP_RECVERR ) | (1 <<IP_ROUTER_ALERT ) | (1 <<IP_FREEBIND ) | - (1<<IP_PASSSEC))) || + (1<<IP_PASSSEC) | (1<<IP_TRANSPARENT))) || optname ==IP_MULTICAST_TTL || optname == IP_MULTICAST_LOOP) { if (optlen >= sizeof(int)) {
@@ -885,6 +885,16 @@ static int do_ip_setsockopt(struct sock *sk, int level, err =xfrm_user_policy (sk, optname, optval, optlen);break ; +case IP_TRANSPARENT : +if (!capable (CAP_NET_ADMIN )) { + err = -EPERM ; +break ; + } +if (optlen <1 ) + goto e_inval; + inet->transparent = !!val; +break ; +default : err = -ENOPROTOOPT ;break ;
PATCH 3/13 Allow binding to non-local addresses if IP_TRANSPARENT is set
In reply to KOVACS KrisztianSetting IP_TRANSPARENT is not really useful without allowing non-local binds for the socket. To make user-space code simpler we allow these binds even if IP_TRANSPARENT is set but IP_FREEBIND is not.
---
net/ipv4/af_inet.c | 2 +- 1 files changed, 1 insertions(+), 1 deletions(-)
net/ipv4/af_inet.c +1 -1
@@ -448,7 +448,7 @@ int inet_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)*/ err = -EADDRNOTAVAIL ; if (!sysctl_ip_nonlocal_bind && - !inet->freebind && + !(inet->freebind || inet->transparent) && addr->sin_addr.s_addr != INADDR_ANY && chk_addr_ret != RTN_LOCAL && chk_addr_ret != RTN_MULTICAST &&
-
To unsubscribe from this list: send the line "unsubscribe netfilter-devel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
PATCH 4/13 Conditionally enable transparent flow flag when connecting
In reply to KOVACS KrisztianSet FLOWI_FLAG_ANYSRC in flowi->flags if the socket has the transparent socket option set. This way we selectively enable certain connections with non-local source addresses to be routed.
---
include/net/route.h | 4 ++++ 1 files changed, 4 insertions(+), 0 deletions(-)
include/net/route.h +4 -0
@@ -158,6 +158,10 @@ static inline int ip_route_connect(struct rtable **rp, __be32 dst, .dport = dport } } };int err; + +if (inet_sk (sk)->transparent) + fl.flags |=FLOWI_FLAG_ANYSRC ; +if (!dst || !src) { err =__ip_route_output_key (rp, &fl);if (err)
PATCH 5/13 Handle TCP SYN+ACK/ACK/RST transparency
In reply to KOVACS KrisztianThe TCP stack sends out SYN+ACK/ACK/RST reply packets in response to incoming packets. The non-local source address check on output bites us again, as replies for transparently redirected traffic won't have a chance to leave the node.
This patch selectively sets the FLOWI_FLAG_ANYSRC flag when doing the route lookup for those replies. Transparent replies are enabled if the listening socket has the transparent socket flag set.
---
include/net/inet_sock.h | 8 +++++++- include/net/ip.h | 9 +++++++++ net/ipv4/inet_connection_sock.c | 1 + net/ipv4/ip_output.c | 4 +++- net/ipv4/syncookies.c | 1 + net/ipv4/tcp_ipv4.c | 11 ++++++++--- 6 files changed, 29 insertions(+), 5 deletions(-)
include/net/inet_sock.h +7 -1
@@ -72,7 +72,8 @@ struct inet_request_sock { sack_ok : 1, wscale_ok : 1, ecn_ok : 1, - acked : 1; + acked : 1, + no_srccheck: 1;struct ip_options *opt; };
@@ -191,4 +192,9 @@ static inline int inet_sk_ehashfn(const struct sock *sk) return inet_ehashfn(laddr, lport, faddr, fport); } +static inline __u8 inet_sk_flowi_flags (const struct sock *sk) +{ +return inet_sk (sk)->transparent ?FLOWI_FLAG_ANYSRC :0 ; +} +#endif /* _INET_SOCK_H */
include/net/ip.h +9 -0
@@ -29,6 +29,7 @@#include <net/inet_sock.h> #include <net/snmp.h> +#include <net/flow.h> struct sock ;
@@ -140,12 +141,20 @@ static inline void ip_tr_mc_map(__be32 addr, char *buf)struct ip_reply_arg {struct kvec iov[1 ]; +int flags;__wsum csum;int csumoffset;/* u16 offset of csum in iov[0].iov_base */ /* -1 if not needed */ int bound_dev_if; }; +#define IP_REPLY_ARG_NOSRCCHECK 1 + +static inline __u8 ip_reply_arg_flowi_flags (const struct ip_reply_arg *arg) +{ +return (arg->flags &IP_REPLY_ARG_NOSRCCHECK ) ?FLOWI_FLAG_ANYSRC :0 ; +} +void ip_send_reply (struct sock *sk,struct sk_buff *skb,struct ip_reply_arg *arg,unsigned int len);
net/ipv4/inet_connection_sock.c +1 -0
@@ -321,6 +321,7 @@ struct dst_entry* inet_csk_route_req(struct sock *sk, .saddr = ireq->loc_addr, .tos = RT_CONN_FLAGS(sk) } }, .proto = sk->sk_protocol, + .flags = inet_sk_flowi_flags(sk), .uli_u = { .ports = { .sport = inet_sk(sk)->sport, .dport = ireq->rmt_port } } };
net/ipv4/ip_output.c +3 -1
@@ -322,6 +322,7 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok) .saddr = inet->saddr, .tos = RT_CONN_FLAGS(sk) } }, .proto = sk->sk_protocol, + .flags = inet_sk_flowi_flags(sk), .uli_u = { .ports = { .sport = inet->sport, .dport = inet->dport } } };
@@ -1364,7 +1365,8 @@ void ip_send_reply(struct sock *sk, struct sk_buff *skb, struct ip_reply_arg *ar .uli_u = { .ports = { .sport = tcp_hdr(skb)->dest, .dport = tcp_hdr(skb)->source } }, - .proto = sk->sk_protocol }; + .proto = sk->sk_protocol, + .flags = ip_reply_arg_flowi_flags(arg) };security_skb_classify_flow (skb, &fl);if (ip_route_output_key (&rt, &fl))return ;
net/ipv4/syncookies.c +1 -0
@@ -260,6 +260,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, .saddr = ireq->loc_addr, .tos = RT_CONN_FLAGS(sk) } }, .proto = IPPROTO_TCP, + .flags = inet_sk_flowi_flags(sk), .uli_u = { .ports = { .sport = th->dest, .dport = th->source } } };
net/ipv4/tcp_ipv4.c +8 -3
@@ -612,6 +612,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)ip_hdr (skb)->saddr,/* XXX */ sizeof(struct tcphdr), IPPROTO_TCP, 0); arg.csumoffset = offsetof(struct tcphdr , check) /2 ; + arg.flags = (sk &&inet_sk (sk)->transparent) ?IP_REPLY_ARG_NOSRCCHECK :0 ;ip_send_reply (tcp_socket->sk, skb, &arg, arg.iov[0 ].iov_len);
@@ -625,7 +626,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)static void tcp_v4_send_ack (struct tcp_timewait_sock *twsk,struct sk_buff *skb,u32 seq,u32 ack, -u32 win,u32 ts) +u32 win,u32 ts,int reply_flags) {struct tcphdr *th =tcp_hdr (skb);struct {
@@ -701,6 +702,7 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, arg.iov[0].iov_len); }#endif + arg.flags = reply_flags; arg.csum =csum_tcpudp_nofold (ip_hdr (skb)->daddr,ip_hdr (skb)->saddr,/* XXX */ arg.iov[0 ].iov_len,IPPROTO_TCP ,0 );
@@ -720,7 +722,8 @@ static void tcp_v4_timewait_ack(struct sock *sk, struct sk_buff *skb)tcp_v4_send_ack (tcptw, skb, tcptw->tw_snd_nxt, tcptw->tw_rcv_nxt, tcptw->tw_rcv_wnd >> tw->tw_rcv_wscale, - tcptw->tw_ts_recent); + tcptw->tw_ts_recent, + tw->tw_transparent ?IP_REPLY_ARG_NOSRCCHECK :0 );inet_twsk_put (tw); }
@@ -730,7 +733,8 @@ static void tcp_v4_reqsk_send_ack(struct sk_buff *skb, {tcp_v4_send_ack (NULL , skb,tcp_rsk (req)->snt_isn +1 ,tcp_rsk (req)->rcv_isn +1 , req->rcv_wnd, - req->ts_recent); + req->ts_recent, +inet_rsk (req)->no_srccheck ?IP_REPLY_ARG_NOSRCCHECK :0 ); }/*
@@ -1332,6 +1336,7 @@ int tcp_v4_conn_request(struct sock *sk, struct sk_buff *skb) ireq =inet_rsk (req); ireq->loc_addr = daddr; ireq->rmt_addr = saddr; + ireq->no_srccheck =inet_sk (sk)->transparent; ireq->opt =tcp_v4_save_options (sk, skb);if (!want_cookie)TCP_ECN_create_request (req,tcp_hdr (skb));
PATCH 6/13 Port redirection support for TCP
In reply to KOVACS KrisztianCurrent TCP code relies on the local port of the listening socket being the same as the destination address of the incoming connection. Port redirection used by many transparent proxying techniques obviously breaks this, so we have to store the original destination port address.
This patch extends struct inet_request_sock and stores the incoming destination port value there. It also modifies the handshake code to use that value as the source port when sending reply packets.
---
include/net/inet_sock.h | 2 +- include/net/tcp.h | 1 + net/ipv4/inet_connection_sock.c | 2 ++ net/ipv4/syncookies.c | 1 + net/ipv4/tcp_output.c | 2 +- 5 files changed, 6 insertions(+), 2 deletions(-)
include/net/inet_sock.h +1 -1
@@ -61,8 +61,8 @@ struct inet_request_sock {struct request_sock req;#if defined(CONFIG_IPV6 ) || defined(CONFIG_IPV6_MODULE )u16 inet6_rsk_offset; -/* 2 bytes hole, try to pack */ #endif +__be16 loc_port;__be32 loc_addr;__be32 rmt_addr;__be16 rmt_port;
include/net/tcp.h +1 -0
@@ -980,6 +980,7 @@ static inline void tcp_openreq_init(struct request_sock *req, ireq->acked =0 ; ireq->ecn_ok =0 ; ireq->rmt_port =tcp_hdr (skb)->source; + ireq->loc_port =tcp_hdr (skb)->dest; }extern void tcp_enter_memory_pressure (void );
net/ipv4/inet_connection_sock.c +2 -0
@@ -501,6 +501,8 @@ struct sock *inet_csk_clone(struct sock *sk, const struct request_sock *req, newicsk->icsk_bind_hash =NULL ;inet_sk (newsk)->dport =inet_rsk (req)->rmt_port; +inet_sk (newsk)->num =ntohs (inet_rsk (req)->loc_port); +inet_sk (newsk)->sport =inet_rsk (req)->loc_port; newsk->sk_write_space = sk_stream_write_space; newicsk->icsk_retransmits =0 ;
net/ipv4/syncookies.c +1 -0
@@ -223,6 +223,7 @@ struct sock *cookie_v4_check(struct sock *sk, struct sk_buff *skb, treq->rcv_isn =ntohl (th->seq) -1 ; treq->snt_isn = cookie; req->mss = mss; + ireq->loc_port = th->dest; ireq->rmt_port = th->source; ireq->loc_addr =ip_hdr (skb)->daddr; ireq->rmt_addr =ip_hdr (skb)->saddr;
net/ipv4/tcp_output.c +1 -1
@@ -2153,7 +2153,7 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, th->syn =1 ; th->ack =1 ;TCP_ECN_make_synack (req, th); - th->source =inet_sk (sk)->sport; + th->source = ireq->loc_port; th->dest = ireq->rmt_port;TCP_SKB_CB (skb)->seq =tcp_rsk (req)->snt_isn;TCP_SKB_CB (skb)->end_seq =TCP_SKB_CB (skb)->seq +1 ;
PATCH 7/13 Export UDP socket lookup function
In reply to KOVACS KrisztianThe iptables tproxy code has to be able to do UDP socket hash lookups, so we have to provide an exported lookup function for this purpose.
---
include/net/udp.h | 4 ++++ net/ipv4/udp.c | 8 ++++++++ 2 files changed, 12 insertions(+), 0 deletions(-)
include/net/udp.h +4 -0
@@ -138,6 +138,10 @@ extern int udp_lib_setsockopt(struct sock *sk, int level, int optname, char __user *optval, int optlen, int (*push_pending_frames)(struct sock *)); +extern struct sock *udp4_lib_lookup (__be32 saddr,__be16 sport, +__be32 daddr,__be16 dport, +int dif); + DECLARE_SNMP_STAT(struct udp_mib, udp_statistics);/* * SNMP statistics for UDP and UDP-Lite
net/ipv4/udp.c +8 -0
@@ -287,6 +287,14 @@ static struct sock *__udp4_lib_lookup(__be32 saddr, __be16 sport,return result; } +struct sock *udp4_lib_lookup (__be32 saddr,__be16 sport, +__be32 daddr,__be16 dport, +int dif) +{ +return __udp4_lib_lookup (saddr, sport, daddr, dport, dif, udp_hash); +} +EXPORT_SYMBOL_GPL (udp4_lib_lookup); + static inline struct sock *udp_v4_mcast_next(struct sock *sk, __be16 loc_port, __be32 loc_addr, __be16 rmt_port, __be32 rmt_addr,
PATCH 8/13 Split Netfilter IPv4 defragmentation into a separate module
In reply to KOVACS KrisztianNetfilter connection tracking requires all IPv4 packets to be defragmented. Both the socket match and the TPROXY target depend on this functionality, so this patch separates the Netfilter IPv4 defrag hooks into a separate module.
---
include/net/netfilter/ipv4/nf_defrag_ipv4.h | 6 ++ net/ipv4/netfilter/Kconfig | 5 + net/ipv4/netfilter/Makefile | 3 + net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c | 55 +------------- net/ipv4/netfilter/nf_defrag_ipv4.c | 94 ++++++++++++++++++++++++ 5 files changed, 110 insertions(+), 53 deletions(-)
include/net/netfilter/ipv4/nf_defrag_ipv4.h new file +6 -0
@@ -0,0 +1,6 @@ +#ifndef _NF_DEFRAG_IPV4_H +#define _NF_DEFRAG_IPV4_H + +extern void nf_defrag_ipv4_enable (void ); + +#endif /* _NF_DEFRAG_IPV4_H */
net/ipv4/netfilter/Kconfig +5 -0
@@ -5,9 +5,14 @@ menu "IP: Netfilter Configuration" depends on INET && NETFILTER +config NF_DEFRAG_IPV4 + tristate + default n + config NF_CONNTRACK_IPV4 tristate "IPv4 connection tracking support (required for NAT)" depends on NF_CONNTRACK + select NF_DEFRAG_IPV4 ---help--- Connection tracking keeps a record of what packets have passed through your machine, in order to figure out how they are related
net/ipv4/netfilter/Makefile +3 -0
@@ -18,6 +18,9 @@ obj-$(CONFIG_NF_CONNTRACK_IPV4) += nf_conntrack_ipv4.o obj-$(CONFIG_NF_NAT) += nf_nat.o +# defrag +obj-$(CONFIG_NF_DEFRAG_IPV4) += nf_defrag_ipv4.o + # NAT helpers (nf_conntrack) obj-$(CONFIG_NF_NAT_AMANDA) += nf_nat_amanda.o obj-$(CONFIG_NF_NAT_FTP) += nf_nat_ftp.o
net/ipv4/netfilter/nf_conntrack_l3proto_ipv4.c +2 -53
91 lines not on this page · raw message
net/ipv4/netfilter/nf_defrag_ipv4.c new file +94 -0
94 lines not on this page · raw message
Re: [PATCH 08/13] Split Netfilter IPv4 defragmentation into a separate module
net/ipv4/netfilter/nf_defrag_ipv4.c line 89
Quoted 4 lines · KOVACS Krisztian
net/ipv4/netfilter/nf_defrag_ipv4.c new file +4
-0+void nf_defrag_ipv4_enable (void ) +{ +} +EXPORT_SYMBOL (nf_defrag_ipv4_enable);
A bit pointless for this function, but I'd preferEXPORT_SYMBOL_GPL for consistenty :)
Re: [PATCH 08/13] Split Netfilter IPv4 defragmentation into a separate module
In reply to KOVACS KrisztianHello,
Quoted 3 lines · KOVACS Krisztian
Netfilter connection tracking requires all IPv4 packets to be defragmented. Both the socket match and the TPROXY target depend on this functionality, so this patch separates the Netfilter IPv4 defrag hooks into a separate module.
With this patch taken from:
http://people.netfilter.org/hidden/tproxy/tproxy4-2.6.23-200710090922.tar.bz2
with:
# CONFIG_NF_CONNTRACK_ENABLED is not set
# CONFIG_NF_CONNTRACK is not set
I get:
net/ipv4/netfilter/nf_defrag_ipv4.c: In function 'ipv4_conntrack_defrag':net/ipv4/netfilter/nf_defrag_ipv4.c:44: error: 'struct sk_buff' has no member named 'nfct' make[3]: *** [net/ipv4/netfilter/nf_defrag_ipv4.o] Error 1
make[2]: *** [net/ipv4/netfilter] Error 2
make[1]: *** [net/ipv4] Error 2
This is not a surprise since:
--- cut here ---
#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE)
struct nf_conntrack *nfct;
struct sk_buff *nfct_reasm;#endif
--- cut here ---
Best regards,
Krzysztof Olędzki
Re: [PATCH 08/13] Split Netfilter IPv4 defragmentation into a separate module
Hi Krzysztof,
Quoted 22 lines · Krzysztof Oledzki
Quoted 4 lines · KOVACS Krisztian
Netfilter connection tracking requires all IPv4 packets to be defragmented. Both the socket match and the TPROXY target depend on this functionality, so this patch separates the Netfilter IPv4 defrag hooks into a separate module.
With this patch taken from:
http://people.netfilter.org/hidden/tproxy/tproxy4-2.6.23-200710090922.t
ar.bz2 with:
#CONFIG_NF_CONNTRACK_ENABLEDis not set
#CONFIG_NF_CONNTRACKis not setI get:
net/ipv4/netfilter/nf_defrag_ipv4.c: In function 'ipv4_conntrack_defrag':net/ipv4/netfilter/nf_defrag_ipv4.c:44: error:
'structsk_buff' has no member named 'nfct' make[3]: *** [net/ipv4/netfilter/nf_defrag_ipv4.o] Error 1
make[2]: *** [net/ipv4/netfilter] Error 2
make[1]: *** [net/ipv4] Error 2
Quoted 7 lines
This is not a surprise since:
--- cut here ---#if defined(CONFIG_NF_CONNTRACK) || defined(CONFIG_NF_CONNTRACK_MODULE) struct nf_conntrack *nfct; struct sk_buff *nfct_reasm;#endif
--- cut here ---
Thanks for spotting this, indeed, this was an oversight from my part... The latest tree at http://people.netfilter.org/hidden/tproxy/ should fix this compilation problem.
Signature · 1 line
KOVACS Krisztian
PATCH 9/13 iptables tproxy core
In reply to KOVACS KrisztianThe iptables tproxy core is a module that contains the common routines used by various tproxy related modules (TPROXY target and socket match)
---
include/net/netfilter/nf_tproxy_core.h | 32 +++++++++++ net/netfilter/Kconfig | 10 +++ net/netfilter/Makefile | 3 + net/netfilter/nf_tproxy_core.c | 96 ++++++++++++++++++++++++++++++++ 4 files changed, 141 insertions(+), 0 deletions(-)
include/net/netfilter/nf_tproxy_core.h new file +32 -0
@@ -0,0 +1,32 @@ +#ifndef _NF_TPROXY_CORE_H +#define _NF_TPROXY_CORE_H + +#include <linux/types.h> +#include <linux/in.h> +#include <linux/skbuff.h> +#include <net/sock.h> +#include <net/inet_sock.h> +#include <net/tcp.h> + +/* look up and get a reference to a matching socket */ +extern struct sock * +nf_tproxy_get_sock_v4 (const u8 protocol, +const __be32 saddr,const __be32 daddr, +const __be16 sport,const __be16 dport, +const struct net_device *in,bool listening); + +static inline void +nf_tproxy_put_sock (struct sock *sk) +{ +/* TIME_WAIT inet sockets have to be handled differently */ +if ((sk->sk_protocol ==IPPROTO_TCP ) && (sk->sk_state ==TCP_TIME_WAIT )) +inet_twsk_put (inet_twsk (sk)); +else +sock_put (sk); +} + +/* assign a socket to the skb -- consumes sk */ +int +nf_tproxy_assign_sock (struct sk_buff *skb,struct sock *sk); + +#endif
net/netfilter/Kconfig +10 -0
@@ -257,6 +257,16 @@ config NF_CT_NETLINK help This option enables support for a netlink-based userspace interface +# transparent proxy support +config NETFILTER_TPROXY + tristate "Transparent proxying support" + depends on IP_NF_MANGLE + help + Transparent proxying. For more information see + http://www.balabit.com/downloads/tproxy. + + To compile it as a module, choose M here. If unsure, say N. + config NETFILTER_XTABLES tristate "Netfilter Xtables support (required for ip_tables)" help
net/netfilter/Makefile +3 -0
@@ -34,6 +34,9 @@ obj-$(CONFIG_NF_CONNTRACK_SANE) += nf_conntrack_sane.o obj-$(CONFIG_NF_CONNTRACK_SIP) += nf_conntrack_sip.o obj-$(CONFIG_NF_CONNTRACK_TFTP) += nf_conntrack_tftp.o +# transparent proxy support +obj-$(CONFIG_NETFILTER_TPROXY) += nf_tproxy_core.o + # generic X tables obj-$(CONFIG_NETFILTER_XTABLES) += x_tables.o xt_tcpudp.o
net/netfilter/nf_tproxy_core.c new file +96 -0
96 lines not on this page · raw message
PATCH 10/13 iptables socket match
In reply to KOVACS KrisztianAdd iptables 'socket' match, which matches packets for which a TCP/UDP socket lookup succeeds.
---
net/netfilter/Kconfig | 12 +++++++ net/netfilter/Makefile | 1 + net/netfilter/xt_socket.c | 83 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 96 insertions(+), 0 deletions(-)
net/netfilter/Kconfig +12 -0
@@ -632,6 +632,18 @@ config NETFILTER_XT_MATCH_SCTP If you want to compile it as a module, say M here and read <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. +config NETFILTER_XT_MATCH_SOCKET + tristate '"socket" match support' + depends on NETFILTER_TPROXY + depends on NETFILTER_XTABLES + select NF_DEFRAG_IPV4 + help + This option adds a `socket' match, which can be used to match + packets for which a TCP or UDP socket lookup finds a valid socket. + It can only be used in the tproxy table. + + To compile it as a module, choose M here. If unsure, say N. + config NETFILTER_XT_MATCH_STATE tristate '"state" match support' depends on NETFILTER_XTABLES
net/netfilter/Makefile +1 -0
@@ -73,6 +73,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) += xt_pkttype.o obj-$(CONFIG_NETFILTER_XT_MATCH_QUOTA) += xt_quota.o obj-$(CONFIG_NETFILTER_XT_MATCH_REALM) += xt_realm.o obj-$(CONFIG_NETFILTER_XT_MATCH_SCTP) += xt_sctp.o +obj-$(CONFIG_NETFILTER_XT_MATCH_SOCKET) += xt_socket.o obj-$(CONFIG_NETFILTER_XT_MATCH_STATE) += xt_state.o obj-$(CONFIG_NETFILTER_XT_MATCH_STATISTIC) += xt_statistic.o obj-$(CONFIG_NETFILTER_XT_MATCH_STRING) += xt_string.o
net/netfilter/xt_socket.c new file +83 -0
83 lines not on this page · raw message
Re: [PATCH 10/13] iptables socket match
net/netfilter/Kconfig config NETFILTER_XT_MATCH_SCTP · line 638
Quoted 4 lines · KOVACS Krisztian
net/netfilter/Kconfig +4
-0+config NETFILTER_XT_MATCH_SOCKET + tristate '"socket" match support' + depends on NETFILTER_TPROXY + depends on NETFILTER_XTABLES
EXPERIMENTAL please.
Quoted 7 lines
net/netfilter/xt_socket.c new file +7
-0+static bool +socket_match(const struct sk_buff *skb, + const struct net_device *in, + const struct net_device *out, + const struct xt_match *match, + const void *matchinfo, + int offset,
net/netfilter/xt_socket.c line 39
Quoted 10 lines
net/netfilter/xt_socket.c new file +10
-0+unsigned int protoff, + bool *hotdrop) +{ + const struct iphdr *iph = ip_hdr(skb); +struct udphdr _hdr, *hp; +struct sock *sk; + +/* TCP/UDP only */ +if (iph->protocol !=IPPROTO_TCP && iph->protocol !=IPPROTO_UDP ) +return false;
How about making sure that its only used in a -p udp or -p tcp rule in ->checkentry() instead?
PATCH 11/13 iptables TPROXY target
In reply to KOVACS KrisztianThe 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.)
---
include/linux/netfilter/xt_TPROXY.h | 14 +++++ net/netfilter/Kconfig | 13 +++++ net/netfilter/Makefile | 1 net/netfilter/xt_TPROXY.c | 97 +++++++++++++++++++++++++++++++++++ 4 files changed, 125 insertions(+), 0 deletions(-)
include/linux/netfilter/xt_TPROXY.h new file +14 -0
@@ -0,0 +1,14 @@ +#ifndef _XT_TPROXY_H_target +#define _XT_TPROXY_H_target + +/* TPROXY target is capable of marking the packet to perform +* redirection. We can get rid of that whenever we get support for +* mutliple targets in the same rule. */ +struct xt_tproxy_target_info { +u_int32_t mark_mask; +u_int32_t mark_value; +__be32 laddr; +__be16 lport; +}; + +#endif /* _XT_TPROXY_H_target */
net/netfilter/Kconfig +13 -0
@@ -363,6 +363,19 @@ config NETFILTER_XT_TARGET_NOTRACK If you want to compile it as a module, say M here and read <file:Documentation/kbuild/modules.txt>. If unsure, say `N'. +config NETFILTER_XT_TARGET_TPROXY + tristate '"TPROXY" target support' + depends on NETFILTER_TPROXY + depends on NETFILTER_XTABLES + 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
net/netfilter/Makefile +1 -0
@@ -50,6 +50,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) += xt_NFLOG.o obj-$(CONFIG_NETFILTER_XT_TARGET_NOTRACK) += xt_NOTRACK.o obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) += xt_TRACE.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_CONNSECMARK) += xt_CONNSECMARK.o
net/netfilter/xt_TPROXY.c new file +97 -0
97 lines not on this page · raw message
Re: [PATCH 11/13] iptables TPROXY target
Quoted 4 lines · KOVACS Krisztian
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.)
Same suggestions as for the socket match (EXPERIMENTAL and TCP/UDP check in ->checkentry).
PATCH 12/13 Don't lookup the socket if there's a socket attached to the skb
In reply to KOVACS KrisztianUse the socket cached in the TPROXY target if it's present.
---
net/ipv4/tcp_ipv4.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-)
net/ipv4/tcp_ipv4.c +8 -0
@@ -1661,6 +1661,14 @@ int tcp_v4_rcv(struct sk_buff *skb)TCP_SKB_CB (skb)->flags = iph->tos;TCP_SKB_CB (skb)->sacked =0 ; +#if defined(CONFIG_NETFILTER_TPROXY ) || defined (CONFIG_NETFILTER_TPROXY_MODULE ) +if (unlikely (skb->sk)) { +/* steal reference */ + sk = skb->sk; + skb->destructor =NULL ; + skb->sk =NULL ; + } else +#endif sk =__inet_lookup (&tcp_hashinfo, iph->saddr, th->source, iph->daddr, th->dest,inet_iif (skb));if (!sk)
PATCH 13/13 Don't lookup the socket if there's a socket attached to the skb
In reply to KOVACS KrisztianUse the socket cached in the TPROXY target if it's present.
---
net/ipv4/udp.c | 8 ++++++++ 1 files changed, 8 insertions(+), 0 deletions(-)
net/ipv4/udp.c +8 -0
@@ -1151,6 +1151,14 @@ int __udp4_lib_rcv(struct sk_buff *skb, struct hlist_head udptable[],if (rt->rt_flags & (RTCF_BROADCAST |RTCF_MULTICAST ))return __udp4_lib_mcast_deliver (skb, uh, saddr, daddr, udptable); +#if defined(CONFIG_NETFILTER_TPROXY ) || defined (CONFIG_NETFILTER_TPROXY_MODULE ) +if (unlikely (skb->sk)) { +/* steal reference */ + sk = skb->sk; + skb->destructor =NULL ; + skb->sk =NULL ; + } else +#endif sk =__udp4_lib_lookup (saddr, uh->source, daddr, uh->dest, skb->dev->ifindex, udptable );