Transparent Proxying Patches, Take 3
Subsystems (5)
cover Transparent Proxying Patches, Take 3
Hi Patrick,
These patches are our (Balazs, Attila and me) third try at providing Linux 2.2-like transparent proxying support for Linux 2.6. During the 5th Netfilter Workshop in Karlsruhe, Germany we tried to come up with an even more lightweight approach not requiring the modification of the IPv4 routing code at all.
The most important changes relative to the previous versions[1,2] are:
* the tproxy table is gone, TPROXY targets need to be added to the mangle table instead
* the tproxy match is gone, a new "socket" match is introduced
* instead of using a separate routing trick to divert packets to the local IP stack inside the TProxy target, we are now using stock routing decisions, and need a bit in the packet MARK field, and perform diversion by using an advanced routing rule (this hopefully makes it possible to implement IPv6 support in the future
* instead of IP_FREEBIND we are using a setsockopt named IP_TRANSPARENT which requires CAP_NET_ADMIN privilege
* in previous patches the output routing decision was commented out, it is now correctly decided whether a packet belongs to a tproxied connection or not.
Usage is a bit more complicated compared to the previous approach, but it's certainly not rocket science:
# iptables rules necessary: # create a chain named DIVERT iptables -t mangle -N DIVERT # everything that matches "-m socket" should go to the local stack iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT # connections to be redirected should use the TPROXY target, which sets # up redirection, and marks the packet according to its 'tproxy-mark' # argument iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY \ --tproxy-mark 0x1/0x1 --on-port 50080 # DIVERT chain: mark packets and accept iptables -t mangle -A DIVERT -j MARK --set-mark 1 iptables -t mangle -A DIVERT -j ACCEPT
# set up advanced routing rules to deliver our marked packets locally ip rule add fwmark 1 lookup 100 ip route add local 0.0.0.0/0 dev lo table 100
The proxy code needs to be modified as well, but these are really lightweight:
before binding, the IP_TRANSPARENT sockopt needs to be enabled on the socket. This implies IP_FREEBIND, so after enabling this socket option non-local binds will work and if you got your iptables/iproute setup right non-local traffic will be delivered to/from the socket. A netcat patch demonstrating this is available[4] as an example.
Some word about the patches:
* output path (patches 1-5): these modifications make it possible to output IPv4 datagrams with non-local IP addresses by:
- introducing a new flowi flag (FLOWI_FLAG_ANYSRC) which disables the source address check in ip_route_output_slow() [3]
- adding the IP_TRANSPARENT socket option (setting this requires CAP_NET_ADMIN)
- setting FLOWI_FLAG_ANYSRC if IP_TRANSPARENT is enabled for the originating socket
- set FLOWI_FLAG_ANYSRC where appropriate for sending reply packets generated by the kernel; this requires extending the ip_reply_arg structure with a flags field and adding an IP_REPLY_ARG_NOSRCCHECK flag
* input patch (patches 6-13): these changes implement redirection support for TCP plus the iptables socket match and TPROXY target -- these provide the actual user interface:
- split IPv4 defragmentation into a separate module, as this is needed by both our target and match
- add a 'socket' match which does a socket lookup based on the destination tuple in the packet and matches is a socket has been found
- add a 'TPROXY' target which looks up a socket based on a modified IP/port tuple and stores the socket reference in the skb
- modifying the TCP/UDP input paths to use the stored socket reference if present
All kinds of comments welcome. Patrick, I'd like to ask you to review these patches and if no issues are found by you or by anyone on the list, please consider merging them.
I'll send the necessary iptables changes in a separate mail.
References:
[1] http://marc.info/?l=linux-netdev&m=117310979603009&w=2
[2] http://www.balabit.com/downloads/files/tproxy/
[3] http://marc.info/?l=linux-netdev&m=118065358510836&w=2
[4] http://people.netfilter.org/hidden/tproxy/netcat-ip_transparent-support.patch
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 ; + } }
Re: [PATCH 01/13] Loosen source address check on IPv4 output
Quoted 10 lines · KOVACS Krisztian
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.
Signed-off-by Julian Anastasov <[email protected]>Signed-off-by KOVACS Krisztian <[email protected]>
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 ;
Re: [PATCH 02/13] Implement IP_TRANSPARENT socket option
Quoted 5 lines · KOVACS Krisztian
This patch introduces the
IP_TRANSPARENTsocket option: enabling that will make the IPv4 routing omit the non-local source address check on output. SettingIP_TRANSPARENTrequiresNET_ADMINcapability.Signed-off-by KOVACS Krisztian <[email protected]>
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
Re: [PATCH 03/13] Allow binding to non-local addresses if IP_TRANSPARENT is set
Quoted 6 lines · KOVACS Krisztian
Setting
IP_TRANSPARENTis not really useful without allowing non-local binds for the socket. To make user-space code simpler we allow these binds even ifIP_TRANSPARENTis set butIP_FREEBINDis not.Signed-off-by Tóth László Attila <[email protected]>
-
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/ip.h | 3 +++ include/net/request_sock.h | 3 ++- net/ipv4/inet_connection_sock.c | 2 ++ net/ipv4/ip_output.c | 6 +++++- net/ipv4/syncookies.c | 2 ++ net/ipv4/tcp_ipv4.c | 17 ++++++++++------- net/ipv4/tcp_minisocks.c | 3 ++- net/ipv6/tcp_ipv6.c | 5 +++-- 8 files changed, 29 insertions(+), 12 deletions(-)
include/net/ip.h +3 -0
@@ -138,8 +138,11 @@ static inline void ip_tr_mc_map(__be32 addr, char *buf) buf[5 ]=0x00 ; } +#define IP_REPLY_ARG_NOSRCCHECK 1 +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 */
include/net/request_sock.h +2 -1
@@ -34,7 +34,8 @@ struct request_sock_ops {struct request_sock *req, struct dst_entry *dst);void (*send_ack)(struct sk_buff *skb, -struct request_sock *req); +struct request_sock *req, +int reply_flags);void (*send_reset)(struct sock *sk,struct sk_buff *skb);void (*destructor)(struct request_sock *req);
net/ipv4/inet_connection_sock.c +2 -0
@@ -321,6 +321,8 @@ 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 (sk)->transparent ? + FLOWI_FLAG_ANYSRC : 0, .uli_u = { .ports = { .sport = inet_sk(sk)->sport, .dport = ireq->rmt_port } } };
net/ipv4/ip_output.c +5 -1
@@ -322,6 +322,8 @@ int ip_queue_xmit(struct sk_buff *skb, int ipfragok) .saddr = inet->saddr, .tos = RT_CONN_FLAGS(sk) } }, .proto = sk->sk_protocol, + .flags = inet->transparent ? + FLOWI_FLAG_ANYSRC : 0, .uli_u = { .ports = { .sport = inet->sport, .dport = inet->dport } } };
@@ -1364,7 +1366,9 @@ 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 = (arg->flags &IP_REPLY_ARG_NOSRCCHECK ) ? + FLOWI_FLAG_ANYSRC : 0 };security_skb_classify_flow (skb, &fl);if (ip_route_output_key (&rt, &fl))return ;
net/ipv4/syncookies.c +2 -0
@@ -260,6 +260,8 @@ 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 (sk)->transparent ? + FLOWI_FLAG_ANYSRC : 0, .uli_u = { .ports = { .sport = th->dest, .dport = th->source } } };
net/ipv4/tcp_ipv4.c +10 -7
@@ -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,36 +702,37 @@ 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 ); arg.csumoffset = offsetof(struct tcphdr , check) /2 ;if (twsk) arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if; -ip_send_reply (tcp_socket->sk, skb, &arg, arg.iov[0 ].iov_len);TCP_INC_STATS_BH (TCP_MIB_OUTSEGS ); } -static void tcp_v4_timewait_ack (struct sock *sk,struct sk_buff *skb) +static void tcp_v4_timewait_ack (struct sock *sk,struct sk_buff *skb,int reply_flags) {struct inet_timewait_sock *tw =inet_twsk (sk);struct tcp_timewait_sock *tcptw =tcp_twsk (sk);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, reply_flags);inet_twsk_put (tw); }static void tcp_v4_reqsk_send_ack (struct sk_buff *skb, -struct request_sock *req) +struct request_sock *req, +int reply_flags) {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, reply_flags); }/*
@@ -1742,7 +1744,8 @@ do_time_wait:/* Fall through to ACK */ }case TCP_TW_ACK : -tcp_v4_timewait_ack (sk, skb); +tcp_v4_timewait_ack (sk, skb,inet_twsk (sk)->tw_transparent ? +IP_REPLY_ARG_NOSRCCHECK :0 );break ;case TCP_TW_RST : goto no_tcp_socket;
net/ipv4/tcp_minisocks.c +2 -1
@@ -604,7 +604,8 @@ struct sock *tcp_check_req(struct sock *sk,struct sk_buff *skb, tcp_rsk(req)->rcv_isn + 1, tcp_rsk(req)->rcv_isn + 1 + req->rcv_wnd)) {/* Out of window: send ACK and drop. */ if (!(flg &TCP_FLAG_RST )) - req->rsk_ops->send_ack (skb, req); + req->rsk_ops->send_ack (skb, req,inet_sk (sk)->transparent ? +IP_REPLY_ARG_NOSRCCHECK :0 );if (paws_reject)NET_INC_STATS_BH (LINUX_MIB_PAWSESTABREJECTED );return NULL ;
net/ipv6/tcp_ipv6.c +3 -2
@@ -72,7 +72,7 @@static struct socket *tcp6_socket;static void tcp_v6_send_reset (struct sock *sk,struct sk_buff *skb); -static void tcp_v6_reqsk_send_ack (struct sk_buff *skb,struct request_sock *req); +static void tcp_v6_reqsk_send_ack (struct sk_buff *skb,struct request_sock *req,int reply_flags);static void tcp_v6_send_check (struct sock *sk,int len,struct sk_buff *skb);
@@ -1183,7 +1183,8 @@ static void tcp_v6_timewait_ack(struct sock *sk, struct sk_buff *skb)inet_twsk_put (tw); } -static void tcp_v6_reqsk_send_ack (struct sk_buff *skb,struct request_sock *req) +static void tcp_v6_reqsk_send_ack (struct sk_buff *skb,struct request_sock *req, +int reply_flags) {tcp_v6_send_ack (NULL , skb,tcp_rsk (req)->snt_isn +1 ,tcp_rsk (req)->rcv_isn +1 , req->rcv_wnd, req->ts_recent); }
Re: [PATCH 05/13] Handle TCP SYN+ACK/ACK/RST transparency
Quoted 9 lines · KOVACS Krisztian
The 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_ANYSRCflag when doing the route lookup for those replies. Transparent replies are enabled if the listening socket has the transparent socket flag set.
I needed to add extra patches to actually compile it cleanly....
Quoted 10 lines
include/net/ip.h | 3 +++ include/net/request_sock.h | 3 ++- net/ipv4/inet_connection_sock.c | 2 ++ net/ipv4/ip_output.c | 6 +++++- net/ipv4/syncookies.c | 2 ++ net/ipv4/tcp_ipv4.c | 17 ++++++++++------- net/ipv4/tcp_minisocks.c | 3 ++- net/ipv6/tcp_ipv6.c | 5 +++-- 8 files changed, 29 insertions(+), 12 deletions(-)
--- net/dccp/dccp.h | 3 ++- net/dccp/minisocks.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)
net/dccp/dccp.h +2 -1
@@ -209,7 +209,8 @@ extern int dccp_retransmit_skb(struct sextern void dccp_send_ack (struct sock *sk);extern void dccp_send_delayed_ack (struct sock *sk); -extern void dccp_reqsk_send_ack (struct sk_buff *sk,struct request_sock *rsk); +extern void dccp_reqsk_send_ack (struct sk_buff *sk,struct request_sock *rsk, +int reply_flags);extern void dccp_send_sync (struct sock *sk,const u64 seq,const enum dccp_pkt_type pkt_type);
net/dccp/minisocks.c +2 -1
@@ -285,7 +285,8 @@ int dccp_child_process(struct sock *pareEXPORT_SYMBOL_GPL (dccp_child_process); -void dccp_reqsk_send_ack (struct sk_buff *skb,struct request_sock *rsk) +void dccp_reqsk_send_ack (struct sk_buff *skb,struct request_sock *rsk, +int reply_flags) {DCCP_BUG ("DCCP-ACK packets are never sent in LISTEN/RESPOND state" ); }
Re: [PATCH 05/13] Handle TCP SYN+ACK/ACK/RST transparency
Quoted 8 lines · KOVACS Krisztian
Quoted 6 lines
The 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.
Quoted 16 lines
Quoted 3 lines
This patch selectively sets the
FLOWI_FLAG_ANYSRCflag when doing the route lookup for those replies. Transparent replies are enabled if the listening socket has the transparent socket flag set.I needed to add extra patches to actually compile it cleanly....
Quoted 10 lines
include/net/ip.h | 3 +++ include/net/request_sock.h | 3 ++- net/ipv4/inet_connection_sock.c | 2 ++ net/ipv4/ip_output.c | 6 +++++- net/ipv4/syncookies.c | 2 ++ net/ipv4/tcp_ipv4.c | 17 ++++++++++------- net/ipv4/tcp_minisocks.c | 3 ++- net/ipv6/tcp_ipv6.c | 5 +++-- 8 files changed, 29 insertions(+), 12 deletions(-)
part 2/2.
Quoted 3 lines
Signed-off-by Jan Engelhardt <[email protected]>
--- net/ipv6/tcp_ipv6.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
net/ipv6/tcp_ipv6.c +2 -2
@@ -73,7 +73,7 @@static struct socket *tcp6_socket;static void tcp_v6_send_reset (struct sock *sk,struct sk_buff *skb); -static void tcp_v6_reqsk_send_ack (struct sk_buff *skb,struct request_sock *req); +static void tcp_v6_reqsk_send_ack (struct sk_buff *skb,struct request_sock *req,int );static void tcp_v6_send_check (struct sock *sk,int len,struct sk_buff *skb);
@@ -1195,7 +1195,7 @@ static void tcp_v6_timewait_ack(struct sinet_twsk_put (tw); } -static void tcp_v6_reqsk_send_ack (struct sk_buff *skb,struct request_sock *req) +static void tcp_v6_reqsk_send_ack (struct sk_buff *skb,struct request_sock *req,int reply_flags) {tcp_v6_send_ack (NULL , skb,tcp_rsk (req)->snt_isn +1 ,tcp_rsk (req)->rcv_isn +1 , req->rcv_wnd, req->ts_recent); }
Re: [PATCH 05/13] Handle TCP SYN+ACK/ACK/RST transparency
Hi Jan,
Quoted 27 lines · Jan Engelhardt
part 2/2.
Quoted 1 line
Signed-off-by Jan Engelhardt <[email protected]>--- net/ipv6/tcp_ipv6.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)Index:
linux-2.6.22.3/net/ipv6/tcp_ipv6.c
===================================================================net/ipv6/tcp_ipv6.c +0
-1@@ -73,7 +73,7 @@static struct socket *tcp6_socket;static void tcp_v6_send_reset (struct sock *sk,struct sk_buff *skb); -static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct
request_sock*req); +static void tcp_v6_reqsk_send_ack(structsk_buff
*skb, structrequest_sock*req, int); static
void tcp_v6_send_check(struct sock *sk, int len,net/ipv6/tcp_ipv6.c +0
-1struct sk_buff *skb);@@ -1195,7 +1195,7 @@ static void tcp_v6_timewait_ack(struct sinet_twsk_put (tw); } -static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct
Quoted 8 lines
request_sock*req) +static voidtcp_v6_reqsk_send_ack(struct sk_buff *skb, struct request_sock *req, int reply_flags){
tcp_v6_send_ack(NULL, skb, tcp_rsk(req)->snt_isn + 1,
tcp_rsk(req)->rcv_isn + 1,req->rcv_wnd,req->ts_recent); } -
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
This is already _in_ the patch I've sent.
Signature · 1 line
KOVACS Krisztian
Re: [PATCH 05/13] Handle TCP SYN+ACK/ACK/RST transparency
Quoted 11 lines · KOVACS Krisztian
Quoted 11 lines
--- net/ipv6/tcp_ipv6.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)Index:
linux-2.6.22.3/net/ipv6/tcp_ipv6.c
===================================================================net/ipv6/tcp_ipv6.c +0
-0@@ -73,7 +73,7 @@static struct socket *tcp6_socket;
Quoted 8 lines
Quoted 6 lines
net/ipv6/tcp_ipv6.c +0
-1static void tcp_v6_send_reset (struct sock *sk,struct sk_buff *skb); -static void tcp_v6_reqsk_send_ack(struct sk_buff *skb, struct
request_sock*req); +static void tcp_v6_reqsk_send_ack(structsk_buff
*skb, structrequest_sock*req, int); static
void tcp_v6_send_check(struct sock *sk, int len,
structsk_buff*skb);This is already _in_ the patch I've sent.
Hm, my bad, did not look to far. (Also these were the 2.6.22 ones - I should probably update)
Re: [PATCH 05/13] Handle TCP SYN+ACK/ACK/RST transparency
In reply to Jan EngelhardtHi Jan,
Quoted 26 lines · Jan Engelhardt
Signed-off-by Jan Engelhardt <[email protected]>--- net/dccp/dccp.h | 3 ++- net/dccp/minisocks.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-)Index:
linux-2.6.22.1/net/dccp/dccp.h
===================================================================net/dccp/dccp.h +0
-1@@ -209,7 +209,8 @@ extern int dccp_retransmit_skb(struct sextern void dccp_send_ack (struct sock *sk);extern void dccp_send_delayed_ack (struct sock *sk); -extern void dccp_reqsk_send_ack(struct sk_buff *sk, struct
request_sock*rsk); +extern void dccp_reqsk_send_ack(structsk_buff
*sk, structrequest_sock*rsk, + intreply_flags);extern void dccp_send_sync(struct sock *sk, const u64 seq,
const enumdccp_pkt_typepkt_type);
Index:linux-2.6.22.1/net/dccp/minisocks.c
===================================================================
net/dccp/minisocks.c int dccp_child_process(struct sock *pare · line 292
Quoted 9 lines
net/dccp/minisocks.c +0
-1@@ -285,7 +285,8 @@ int dccp_child_process(struct sock *pareEXPORT_SYMBOL_GPL (dccp_child_process); -void dccp_reqsk_send_ack (struct sk_buff *skb,struct request_sock *rsk) +void dccp_reqsk_send_ack(struct sk_buff *skb, struct request_sock *rsk, + int reply_flags) { DCCP_BUG("DCCP-ACK packets are never sent in LISTEN/RESPOND state"); }
Yes, this was missing. Thanks.
Signature · 1 line
KOVACS Krisztian
Re: [PATCH 05/13] Handle TCP SYN+ACK/ACK/RST transparency
In reply to KOVACS KrisztianQuoted 17 lines · KOVACS Krisztian
The 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_ANYSRCflag when doing the route lookup for those replies. Transparent replies are enabled if the listening socket has the transparent socket flag set.Signed-off-by KOVACS Krisztian <[email protected]>---
include/net/request_sock.h +0
-0
include/net/request_sock.h struct request_sock_ops { · line 39
Quoted 7 lines
include/net/request_sock.h +2
-1@@ -34,7 +34,8 @@ struct request_sock_ops {struct request_sock *req, struct dst_entry *dst);void (*send_ack)(struct sk_buff *skb, -struct request_sock *req); +struct request_sock *req, +int reply_flags);
How about putting the flags in the request_sock?
net/ipv4/inet_connection_sock.c struct dst_entry* inet_csk_route_req(struct sock *sk, · line 326
Quoted 11 lines
net/ipv4/inet_connection_sock.c +2
-0@@ -321,6 +321,8 @@ 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 (sk)->transparent ? + FLOWI_FLAG_ANYSRC : 0,
Introducing a function (sk_flowi_flags(sk) or something) might make it a bit nicer to look at.
Quoted 14 lines
net/ipv4/tcp_ipv4.c +1
-1@@ -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 {
net/ipv4/tcp_ipv4.c static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, · line 706
Quoted 5 lines
net/ipv4/tcp_ipv4.c +1
-0@@ -701,36 +702,37 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, arg.iov[0].iov_len); }#endif + arg.flags = reply_flags;
Shouldn't this use twsk->transparent?
net/ipv4/tcp_ipv4.c static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, · line 712
Quoted 8 lines
net/ipv4/tcp_ipv4.c +0
-1arg.csum =csum_tcpudp_nofold (ip_hdr (skb)->daddr,ip_hdr (skb)->saddr,/* XXX */ arg.iov[0 ].iov_len,IPPROTO_TCP ,0 ); arg.csumoffset = offsetof(struct tcphdr , check) /2 ;if (twsk) arg.bound_dev_if = twsk->tw_sk.tw_bound_dev_if; -ip_send_reply (tcp_socket->sk, skb, &arg, arg.iov[0 ].iov_len);
Unrelated whitespace change
Re: [PATCH 05/13] Handle TCP SYN+ACK/ACK/RST transparency
Hi Patrick,
Quoted 13 lines · Patrick McHardy
Quoted 12 lines · KOVACS Krisztian
The 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_ANYSRCflag when doing the route lookup for those replies. Transparent replies are enabled if the listening socket has the transparent socket flag set.Signed-off-by KOVACS Krisztian <[email protected]>---
Quoted 13 lines
include/net/request_sock.h struct request_sock_ops { · line 38
Quoted 11 lines
include/net/request_sock.h +2
-1@@ -34,7 +34,8 @@ struct request_sock_ops {struct request_sock *req, struct dst_entry *dst);void (*send_ack)(struct sk_buff *skb, -struct request_sock *req); +struct request_sock *req, +int reply_flags);How about putting the flags in the
request_sock?
Nice idea, I'll give it a try.
Quoted 5 lines
Quoted 5 lines
(quoted diff) +0
-0
b/net/ipv4/inet_connection_sock.cindex fbe7714..26b9dbe 100644net/ipv4/inet_connection_sock.c +0
-0@@ -321,6 +321,8 @@ struct dst_entry* inet_csk_route_req(struct sock
Quoted 8 lines
net/ipv4/inet_connection_sock.c struct dst_entry* inet_csk_route_req(struct sock *sk, · line 325
Quoted 5 lines
net/ipv4/inet_connection_sock.c +2
-0*sk, .saddr = ireq->loc_addr, .tos = RT_CONN_FLAGS(sk) } }, .proto = sk->sk_protocol, + .flags =inet_sk (sk)->transparent ? + FLOWI_FLAG_ANYSRC : 0,Introducing a function (
sk_flowi_flags(sk)or something) might make it a bit nicer to look at.
Ok, done for the next round of patches.
Quoted 7 lines
Quoted 7 lines
net/ipv4/tcp_ipv4.c +0
-0@@ -625,7 +626,7 @@ static void tcp_v4_send_reset(struct sock *sk, struct sk_buff *skb)
Quoted 14 lines
net/ipv4/tcp_ipv4.c static void tcp_v4_send_ack(struct · line 705
Quoted 12 lines
net/ipv4/tcp_ipv4.c +1
-1static 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);net/ipv4/tcp_ipv4.c +1
-0struct {@@ -701,36 +702,37 @@ static void tcp_v4_send_ack(struct tcp_timewait_sock *twsk, arg.iov[0].iov_len); }#endif + arg.flags = reply_flags;Shouldn't this use
twsk->transparent?
We can't, as tcp_v4_send_ack() is called with twsk == NULL from tcp_v4_reqsk_send_ack().
Signature · 1 line
KOVACS Krisztian
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 | 3 +++ include/net/tcp.h | 3 +++ net/ipv4/inet_connection_sock.c | 4 ++++ net/ipv4/syncookies.c | 3 +++ net/ipv4/tcp_output.c | 4 ++++ 5 files changed, 17 insertions(+), 0 deletions(-)
include/net/inet_sock.h +3 -0
@@ -65,6 +65,9 @@ struct inet_request_sock {#endif __be32 loc_addr;__be32 rmt_addr; +#if defined(CONFIG_NETFILTER_TPROXY ) || defined(CONFIG_NETFILTER_TPROXY_MODULE ) +__be16 loc_port; +#endif __be16 rmt_port; u16 snd_wscale : 4, rcv_wscale : 4,
include/net/tcp.h +3 -0
@@ -980,6 +980,9 @@ static inline void tcp_openreq_init(struct request_sock *req, ireq->acked =0 ; ireq->ecn_ok =0 ; ireq->rmt_port =tcp_hdr (skb)->source; +#if defined(CONFIG_NETFILTER_TPROXY ) || defined(CONFIG_NETFILTER_TPROXY_MODULE ) + ireq->loc_port =tcp_hdr (skb)->dest; +#endif }extern void tcp_enter_memory_pressure (void );
net/ipv4/inet_connection_sock.c +4 -0
@@ -502,6 +502,10 @@ 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; +#if defined(CONFIG_IP_NF_TPROXY ) || defined(CONFIG_IP_NF_TPROXY_MODULE ) +inet_sk (newsk)->num =ntohs (inet_rsk (req)->loc_port); +inet_sk (newsk)->sport =inet_rsk (req)->loc_port; +#endif newsk->sk_write_space = sk_stream_write_space; newicsk->icsk_retransmits =0 ;
net/ipv4/syncookies.c +3 -0
@@ -223,6 +223,9 @@ 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; +#if defined(CONFIG_IP_NF_TPROXY ) || defined(CONFIG_IP_NF_TPROXY_MODULE ) + ireq->loc_port = th->dest; +#endif ireq->rmt_port = th->source; ireq->loc_addr =ip_hdr (skb)->daddr; ireq->rmt_addr =ip_hdr (skb)->saddr;
net/ipv4/tcp_output.c +4 -0
@@ -2153,7 +2153,11 @@ 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); +#if defined(CONFIG_IP_NF_TPROXY ) || defined(CONFIG_IP_NF_TPROXY_MODULE ) + th->source = ireq->loc_port; +#else th->source =inet_sk (sk)->sport; +#endif 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 ;
Re: [PATCH 06/13] Port redirection support for TCP
Quoted 46 lines · KOVACS Krisztian
Current 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_sockand 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.Signed-off-by KOVACS Krisztian <[email protected]>---
include/net/inet_sock.h +3
-0@@ -65,6 +65,9 @@ struct inet_request_sock {#endif __be32 loc_addr;__be32 rmt_addr; +#if defined(CONFIG_NETFILTER_TPROXY ) || defined(CONFIG_NETFILTER_TPROXY_MODULE ) +__be16 loc_port; +#endif __be16 rmt_port; u16 snd_wscale : 4, rcv_wscale : 4,include/net/tcp.h +3
-0@@ -980,6 +980,9 @@ static inline void tcp_openreq_init(struct request_sock *req, ireq->acked =0 ; ireq->ecn_ok =0 ; ireq->rmt_port =tcp_hdr (skb)->source; +#if defined(CONFIG_NETFILTER_TPROXY ) || defined(CONFIG_NETFILTER_TPROXY_MODULE ) + ireq->loc_port =tcp_hdr (skb)->dest; +#endif }extern void tcp_enter_memory_pressure (void );net/ipv4/inet_connection_sock.c +0
-0
net/ipv4/inet_connection_sock.c struct sock *inet_csk_clone(struct sock *sk, const struct request_sock *req, · line 509
Quoted 8 lines
net/ipv4/inet_connection_sock.c +3
-0@@ -502,6 +502,10 @@ 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; +#if defined(CONFIG_IP_NF_TPROXY ) || defined(CONFIG_IP_NF_TPROXY_MODULE ) +inet_sk (newsk)->num =ntohs (inet_rsk (req)->loc_port); +inet_sk (newsk)->sport =inet_rsk (req)->loc_port;
Why do you store the port twice here?
Quoted 5 lines
ipv4/tcp_output.c
index 666d8a5..69dd230 100644
net/ipv4/tcp_output.c struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, · line 2161
Quoted 9 lines
net/ipv4/tcp_output.c +4
-0@@ -2153,7 +2153,11 @@ 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); +#if defined(CONFIG_IP_NF_TPROXY ) || defined(CONFIG_IP_NF_TPROXY_MODULE ) + th->source = ireq->loc_port; +#else th->source =inet_sk (sk)->sport; +#endif
I think this should simply use loc_port unconditionally.
Re: [PATCH 06/13] Port redirection support for TCP
Hi Patrick,
Quoted 50 lines · Patrick McHardy
Quoted 49 lines · KOVACS Krisztian
Current 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_sockand 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.Signed-off-by KOVACS Krisztian <[email protected]>---
include/net/inet_sock.h +2
-0@@ -65,6 +65,9 @@ struct inet_request_sock {#endif __be32 loc_addr;__be32 rmt_addr; +#if defined(CONFIG_NETFILTER_TPROXY) || defined(CONFIG_NETFILTER_TPROXY_MODULE) + __be16 loc_port; +#endif __be16 rmt_port; u16 snd_wscale : 4, rcv_wscale : 4,include/net/tcp.h +1
-0@@ -980,6 +980,9 @@ static inline void tcp_openreq_init(struct request_sock *req, ireq->acked =0 ; ireq->ecn_ok =0 ; ireq->rmt_port =tcp_hdr (skb)->source; +#if defined(CONFIG_NETFILTER_TPROXY) ||
defined(CONFIG_NETFILTER_TPROXY_MODULE)+ireq->loc_port=
tcp_hdr(skb)->dest;include/net/tcp.h +1
-0+#endif }extern void tcp_enter_memory_pressure (void );(quoted diff) +0
-0
b/net/ipv4/inet_connection_sock.cindex 26b9dbe..f47d966 100644net/ipv4/inet_connection_sock.c +0
-0@@ -502,6 +502,10 @@ struct sock *inet_csk_clone(struct sock *sk, const struct request_sock *req, newicsk->icsk_bind_hash = NULL;
Quoted 8 lines
net/ipv4/inet_connection_sock.c struct sock *inet_csk_clone(struct sock *sk, const struct request_sock *req, · line 507
Quoted 6 lines
net/ipv4/inet_connection_sock.c +1
-0inet_sk (newsk)->dport =inet_rsk (req)->rmt_port; +#if defined(CONFIG_IP_NF_TPROXY) ||
defined(CONFIG_IP_NF_TPROXY_MODULE)+ inet_sk(newsk)->num =
ntohs(inet_rsk(req)->loc_port);net/ipv4/inet_connection_sock.c +1
-0+inet_sk (newsk)->sport =inet_rsk (req)->loc_port;Why do you store the port twice here?
Because ->num is in host byte order while sport is host byte order.
Quoted 7 lines
Quoted 7 lines
ipv4/tcp_output.c
index 666d8a5..69dd230 100644net/ipv4/tcp_output.c +0
-0@@ -2153,7 +2153,11 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, th->syn = 1; th->ack =1 ;
Quoted 8 lines
net/ipv4/tcp_output.c struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, · line 2160
Quoted 6 lines
net/ipv4/tcp_output.c +3
-0TCP_ECN_make_synack (req, th); +#if defined(CONFIG_IP_NF_TPROXY) || defined(CONFIG_IP_NF_TPROXY_MODULE) + th->source = ireq->loc_port; +#else th->source = inet_sk(sk)->sport; +#endif I think this should simply use
loc_portunconditionally.
Unfortunately ireq->loc_port does not exist unless tproxy is enabled in the config. (We could remove all these #ifdefs but that would mean extending inet_request_sock with 2 bytes even if tproxy is not enabled.)
Signature · 1 line
KOVACS Krisztian
Re: [PATCH 06/13] Port redirection support for TCP
Quoted 17 lines · KOVACS Krisztian
Quoted 7 lines
Quoted 7 lines
ipv4/tcp_output.c
index 666d8a5..69dd230 100644net/ipv4/tcp_output.c +0
-0@@ -2153,7 +2153,11 @@ struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, th->syn = 1; th->ack =1 ;Quoted 8 lines
net/ipv4/tcp_output.c struct sk_buff * tcp_make_synack(struct sock *sk, struct dst_entry *dst, · line 2160
Quoted 6 lines
net/ipv4/tcp_output.c +3
-0TCP_ECN_make_synack (req, th); +#if defined(CONFIG_IP_NF_TPROXY) || defined(CONFIG_IP_NF_TPROXY_MODULE) + th->source = ireq->loc_port; +#else th->source = inet_sk(sk)->sport; +#endif I think this should simply use
loc_portunconditionally.
Quoted 3 lines
Unfortunately
ireq->loc_portdoes not exist unless tproxy is enabled in the config. (We could remove all these #ifdefs but that would mean extendinginet_request_sockwith 2 bytes even if tproxy is not enabled.)
There's a 2 byte hole with IPv6 where you could put this in. I think even without IPv6 the small waste is not worth the increased testing complexity.
Re: [PATCH 06/13] Port redirection support for TCP
Hi Patrick,
Quoted 18 lines · Patrick McHardy
Quoted 17 lines · KOVACS Krisztian
Quoted 15 lines
net/ipv4/tcp_output.c struct sk_buff * tcp_make_synack(struct sock · line 2160
Quoted 13 lines
ipv4/tcp_output.c
index 666d8a5..69dd230 100644net/ipv4/tcp_output.c +3
-0@@ -2153,7 +2153,11 @@ 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); +#if defined(CONFIG_IP_NF_TPROXY) || defined(CONFIG_IP_NF_TPROXY_MODULE) + th->source = ireq->loc_port; +#else th->source = inet_sk(sk)->sport; +#endif I think this should simply use
loc_portunconditionally.
Quoted 8 lines
Quoted 3 lines
Unfortunately
ireq->loc_portdoes not exist unless tproxy is enabled in the config. (We could remove all these #ifdefs but that would mean extendinginet_request_sockwith 2 bytes even if tproxy is not enabled.)There's a 2 byte hole with IPv6 where you could put this in. I think even without IPv6 the small waste is not worth the increased testing complexity.
Ok, I'll remove the ifdefs then and add loc_port in that hole. Thanks for your feedback.
Signature · 1 line
KOVACS Krisztian
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
Quoted 6 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.
Signed-off-by KOVACS Krisztian <[email protected]>
Mhh .. I don't like this too much, but I don't see a much better way myself, especially for the socket match since it can't do defragmentation itself.
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
Re: [PATCH 09/13] iptables tproxy core
Quoted 4 lines · KOVACS Krisztian
The iptables tproxy core is a module that contains the common routines used by various tproxy related modules (TPROXY target and socket match)
Signed-off-by KOVACS Krisztian <[email protected]>
Looks fine.
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 | 87 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 100 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 +87 -0
87 lines not on this page · raw message
Re: [PATCH 10/13] iptables socket match
Quoted 5 lines · KOVACS Krisztian
Add iptables 'socket' match, which matches packets for which a TCP/UDP socket lookup succeeds.
---
And here is the xt_socket that I had..
===
iptables socket match
From: KOVACS Krisztian <[email protected]>
Add iptables 'socket' match, which matches packets for which a TCP/UDP socket lookup succeeds.
---
net/ipv4/netfilter/Kconfig | 10 +++++ net/netfilter/Makefile | 1 net/netfilter/xt_socket.c | 80 +++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 91 insertions(+)
net/ipv4/netfilter/Kconfig +10 -0
@@ -414,6 +414,16 @@ config NETFILTER_XT_TARGET_TPROXY To compile it as a module, choose M here. If unsure, say N. +config NETFILTER_XT_MATCH_SOCKET + tristate "socket match support" + depends on IP_NF_TPROXY_TABLE + 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. + # ARP tables config IP_NF_ARPTABLES tristate "ARP tables support"
net/netfilter/Makefile +1 -0
@@ -76,6 +76,7 @@ obj-$(CONFIG_NETFILTER_XT_MATCH_PKTTYPE) 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 +80 -0
80 lines not on this page · raw message
Re: [PATCH 10/13] xt_socket
In reply to KOVACS KrisztianReview
Quoted 4 lines · KOVACS Krisztian
(quoted diff) +4
-0+ + hp = skb_header_pointer(skb, iph->ihl * 4, sizeof(_hdr), &_hdr); + if (hp == NULL) + return false;
ip_hdrlen(skb) for 2nd arg.
Review
Quoted 3 lines
(quoted diff) +3
-0+ pr_debug("socket match: proto %d %08x:%d -> %08x:%d sock %p\n", + iph->protocol, ntohl(iph->saddr), ntohs(hp->source), + ntohl(iph->daddr), ntohs(hp->dest), sk);
Should be %u.
Quoted 1 line
+static struct
xt_matchsocket_matches[] = {
A single struct suffices.
Review
Quoted 3 lines
(quoted diff) +3
-0+ .name = "socket", + .family = AF_INET, + .match = match,
This goes against debugging. If everyone names their match function "match" (and it's done too often in netfilter and iptables-userspace already), it is hard to find out which is meant (e.g. in an oops). It also makes debugging quite impossible because setting a breakpoint will be ambiguous.
Find below a patch that makes me happy, and compiles. :)
===
Add the xt_socket match, which matches packets for which a TCP/UDP socket lookup succeeds.
(originally from: KOVACS Krisztian <[email protected]>)
A few cleanups.
---
net/netfilter/Kconfig | 12 +++++++ net/netfilter/Makefile | 1 net/netfilter/xt_socket.c | 76 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+)
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) 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 +76 -0
76 lines not on this page · raw message
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_ipv4/ipt_TPROXY.h | 14 +++ net/netfilter/Kconfig | 12 +++ net/netfilter/Makefile | 1 net/netfilter/xt_TPROXY.c | 139 +++++++++++++++++++++++++++++ 4 files changed, 166 insertions(+), 0 deletions(-)
include/linux/netfilter_ipv4/ipt_TPROXY.h new file +14 -0
@@ -0,0 +1,14 @@ +#ifndef _IPT_TPROXY_H_target +#define _IPT_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 ipt_tproxy_target_info { +__be32 laddr; +__be16 lport; +unsigned long mark_mask; +unsigned long mark_value; +}; + +#endif
net/netfilter/Kconfig +12 -0
@@ -363,6 +363,18 @@ 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 + help + This option adds a `TPROXY' target, which is somewhat similar to + REDIRECT. It can only be used in the tproxy table and is useful + to redirect traffic to a transparent proxy. It does _not_ depend + on Netfilter connection tracking. + + 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 +139 -0
139 lines not on this page · raw message
Re: [PATCH 11/13] xtables 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.)
This provides xt_TPROXY.
===
iptables TPROXY target
From: KOVACS Krisztian <[email protected]>
The TPROXY target implements redirection of non-local TCP/UDP traffic to local sockets. It is simply a wrapper around functionality exported from iptable_tproxy.
---
include/linux/netfilter/xt_TPROXY.h | 9 ++++ net/ipv4/netfilter/Kconfig | 11 +++++ net/netfilter/Makefile | 1 net/netfilter/xt_TPROXY.c | 76 ++++++++++++++++++++++++++++++++++++ 4 files changed, 97 insertions(+)
include/linux/netfilter/xt_TPROXY.h new file +9 -0
@@ -0,0 +1,9 @@ +#ifndef _XT_TPROXY_H +#define _XT_TPROXY_H + +struct xt_tproxy_info { +u_int32_t laddr; +u_int16_t lport; +}; + +#endif /* _XT_TPROXY_H */
net/ipv4/netfilter/Kconfig +11 -0
@@ -403,6 +403,17 @@ config IP_NF_TPROXY_TABLE To compile it as a module, choose M here. If unsure, say `N'. +config NETFILTER_XT_TARGET_TPROXY + tristate "TPROXY target support" + depends on IP_NF_TPROXY_TABLE + help + This option adds a `TPROXY' target, which is somewhat similar to + REDIRECT. It can only be used in the tproxy table and is useful + to redirect traffic to a transparent proxy. It does _not_ depend + on Netfilter connection tracking. + + To compile it as a module, choose M here. If unsure, say N. + # ARP tables config IP_NF_ARPTABLES tristate "ARP tables support"
net/netfilter/Makefile +1 -0
@@ -50,6 +50,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_TRACE) obj-$(CONFIG_NETFILTER_XT_TARGET_SECMARK) += xt_SECMARK.o obj-$(CONFIG_NETFILTER_XT_TARGET_TARPIT) += xt_TARPIT.o obj-$(CONFIG_NETFILTER_XT_TARGET_TCPMSS) += xt_TCPMSS.o +obj-$(CONFIG_NETFILTER_XT_TARGET_TPROXY) += xt_TPROXY.o obj-$(CONFIG_NETFILTER_XT_TARGET_CONNSECMARK) += xt_CONNSECMARK.o # matches
net/netfilter/xt_TPROXY.c new file +76 -0
76 lines not on this page · raw message
Re: [PATCH 11/13] xtables TPROXY target
Hi Jan,
Quoted 18 lines · Jan Engelhardt
net/netfilter/xt_TPROXY.c new file +18
-0+static unsigned int +tproxy_target (struct sk_buff **pskb,const struct net_device *in, +const struct net_device *out,unsigned int hooknum, +const struct xt_target *target,const void *targinfo) +{ +const struct xt_tproxy_info *tgi = targinfo; +const struct iphdr *iph =ip_hdr (*pskb); +struct sk_buff *skb = *pskb; +struct udphdr _hdr, *hp; + +/* TCP/UDP only */ +if (iph->protocol !=IPPROTO_TCP && iph->protocol !=IPPROTO_UDP ) +return NF_ACCEPT ; + + hp =skb_header_pointer (*pskb, iph->ihl *4 ,sizeof (_hdr), &_hdr); +if (hp ==NULL ) +return NF_DROP ; +
net/netfilter/xt_TPROXY.c line 50
Quoted 10 lines
net/netfilter/xt_TPROXY.c new file +10
-0+ skb->nf_tproxy.redirect_address = tgi->laddr ? : iph->daddr; + skb->nf_tproxy.redirect_port = tgi->lport ? : hp->dest; + +pr_debug (KERN_DEBUG "redirecting: proto %d %08x:%d -> %08x:%d\n" , + iph->protocol,ntohl (iph->daddr),ntohs (hp->dest), +ntohl (skb->nf_tproxy.redirect_address), +ntohs (skb->nf_tproxy.redirect_port)); + +return NF_ACCEPT ; +}
I guess this is also an old version, the current one does not look like this. Are you sure this is really up-to-date?
Signature · 1 line
KOVACS Krisztian
Re: [PATCH 11/13] xt_TPROXY
In reply to KOVACS KrisztianReview
Quoted 6 lines · KOVACS Krisztian
(quoted diff) +6
-0+struct ipt_tproxy_target_info { + __be32 laddr; + __be16 lport; + unsigned long mark_mask; + unsigned long mark_value; +};
Cannot use unsigned long, as its size is not fixed.
(other nitpicks that were already in xt_socket)
Review
Quoted 5 lines
(quoted diff) +5
-0+ /* 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;
I guess you mean | instead of ^ here.
Review
Quoted 8 lines
(quoted diff) +8
-0+#ifdef CONFIG_COMPAT +struct compat_ipt_tproxy_target_info { + __be32 laddr; + __be16 lport; + __be16 __pad1; + compat_ulong_t mark_mask; + compat_ulong_t mark_value; +};
Uhm, that's a bit cumbersome. By reordering, we can get all the alignment done without any premature compat code.
Find below a patch that makes me happy, and compiles. :)
[ xtification comes at no cost, even if it's ipv4-only.
Although it is just a guess, I suppose xt_ is going to replace ipt_ and ip6t_ even if some matches/targets are not all-protocol ]
===
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.)
(originally from: KOVACS Krisztian <[email protected]>)
A few cleanups and fixes.
---
include/linux/netfilter/xt_TPROXY.h | 16 ++++++ net/netfilter/Kconfig | 12 ++++ net/netfilter/Makefile | 1 net/netfilter/xt_TPROXY.c | 92 ++++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+)
include/linux/netfilter/xt_TPROXY.h new file +16 -0
@@ -0,0 +1,16 @@ +#ifndef _XT_TPROXY_H +#define _XT_TPROXY_H + +/* +* 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_info { +u_int32_t mark_mask; +u_int32_t mark_value; +__be32 laddr; +__be16 lport; +}; + +#endif /* _XT_TPROXY_H */
net/netfilter/Kconfig +12 -0
@@ -363,6 +363,18 @@ 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 + help + This option adds a "TPROXY" target, which is somewhat similar to + REDIRECT. It can only be used in the tproxy table and is useful + to redirect traffic to a transparent proxy. It does _not_ depend + on Netfilter connection tracking. + + 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) 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 +92 -0
92 lines not on this page · raw message
Re: [PATCH 11/13] xt_TPROXY
Quoted 13 lines · Jan Engelhardt
include/linux/netfilter/xt_TPROXY.h line 14
Quoted 6 lines · KOVACS Krisztian
include/linux/netfilter/xt_TPROXY.h new file +6
-0+struct ipt_tproxy_target_info { +__be32 laddr; +__be16 lport; +unsigned long mark_mask; +unsigned long mark_value; +};Cannot use unsigned long, as its size is not fixed.
(other nitpicks that were already in
xt_socket)
Quoted 7 lines
Review
Quoted 5 lines
(quoted diff) +5
-0+ /* 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;I guess you mean | instead of ^ here.
No, ^ is intentional. The idea is that in addition to being able to _set_ the masked part of the mark to a given value, you can also flip other bits of the mark with the unmasked parts of the value. So it has slightly more expressive power, and does the right thing if you use it in a 'conventional' way.
Quoted 12 lines
Review
Quoted 9 lines
(quoted diff) +8
-0+#ifdef CONFIG_COMPAT +struct compat_ipt_tproxy_target_info { + __be32 laddr; + __be16 lport; + __be16 __pad1; + compat_ulong_t mark_mask; + compat_ulong_t mark_value; +};Uhm, that's a bit cumbersome. By reordering, we can get all the alignment done without any premature compat code.
Yes, given that we can go back to using 32 bit marks.
Quoted 185 lines
Find below a patch that makes me happy, and compiles. :)
[ xtification comes at no cost, even if it's ipv4-only.
Although it is just a guess, I supposext_is going to replaceipt_andip6t_even if some matches/targets are not all-protocol ]===
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.)
(originally from: KOVACS Krisztian <[email protected]>)
A few cleanups and fixes.
Signed-off-by Jan Engelhardt <[email protected]>---
include/linux/netfilter/xt_TPROXY.h | 16 ++++++ net/netfilter/Kconfig | 12 ++++ net/netfilter/Makefile | 1 net/netfilter/xt_TPROXY.c | 92++++++++++++++++++++++++++++++++++++ 4 files changed, 121 insertions(+)
Index:
linux-2.6.23/include/linux/netfilter/xt_TPROXY.h
===================================================================include/linux/netfilter/xt_TPROXY.h new file +16
-0@@ -0,0 +1,16 @@ +#ifndef _XT_TPROXY_H +#define _XT_TPROXY_H + +/* +* 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_info { +u_int32_t mark_mask; +u_int32_t mark_value; +__be32 laddr; +__be16 lport; +}; + +#endif /* _XT_TPROXY_H */ Index: linux-2.6.23/net/netfilter/Kconfig
===================================================================net/netfilter/Kconfig +12
-0@@ -363,6 +363,18 @@ 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 + help + This option adds a "TPROXY" target, which is somewhat similar to + REDIRECT. It can only be used in the tproxy table and is useful + to redirect traffic to a transparent proxy. It does _not_ depend + on Netfilter connection tracking. + + 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_XTABLESIndex: linux-2.6.23/net/netfilter/Makefile
===================================================================net/netfilter/Makefile +1
-0@@ -50,6 +50,7 @@ obj-$(CONFIG_NETFILTER_XT_TARGET_NFLOG) 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.oIndex:
linux-2.6.23/net/netfilter/xt_TPROXY.c
===================================================================net/netfilter/xt_TPROXY.c new file +7
-0@@ -0,0 +1,92 @@ +/* +* 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.
+ *
+ */net/netfilter/xt_TPROXY.c new file +49
-0+#include <linux/module.h> +#include <linux/skbuff.h> +#include <linux/ip.h> +#include <net/checksum.h> +#include <net/inet_sock.h> +#include <net/udp.h> +#include <linux/netfilter/x_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_target (struct sk_buff **pskb,const struct net_device *in, +const struct net_device *out,unsigned int hooknum, +const struct xt_target *target,const void *targinfo) +{ +const struct xt_tproxy_info *tgi = targinfo; +const struct iphdr *iph =ip_hdr (*pskb); +struct sk_buff *skb = *pskb; +struct udphdr _hdr, *hp; +struct sock *sk; + +/* TCP/UDP only */ +if (iph->protocol !=IPPROTO_TCP && iph->protocol !=IPPROTO_UDP ) +return NF_ACCEPT ; + + hp =skb_header_pointer (*pskb,ip_hdrlen (skb),sizeof (_hdr), &_hdr); +if (hp ==NULL ) +return NF_DROP ; + + sk =nf_tproxy_get_sock_v4 (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 !=NULL &&nf_tproxy_assign_sock (skb, sk) !=0 ) { +/* +* This should be in a separate target, but we do not 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),net/netfilter/xt_TPROXY.c new file +29
-0+ ntohl(tgi->laddr), ntohs(tgi->lport), skb->mark); +return NF_DROP ; +} + +static struct xt_target xt_tproxy_reg = { + .name ="TPROXY" , + .family =AF_INET , + .table ="mangle" , + .target = tproxy_target, + .targetsize =sizeof (struct xt_tproxy_info ), + .hooks =1 <<NF_IP_PRE_ROUTING , + .me =THIS_MODULE , +}; + +static int __init xt_tproxy_init (void ) +{ +nf_defrag_ipv4_enable (); +return xt_register_target (&xt_tproxy_reg); +} + +static void __exit xt_tproxy_exit(void) +{ +xt_unregister_target (&xt_tproxy_reg); +} + +module_init (xt_tproxy_init); +module_exit (xt_tproxy_exit); +MODULE_AUTHOR ("Krisztian Kovacs" ); +MODULE_DESCRIPTION("Netfilter transparent proxy (TPROXY) targetmodule"); +MODULE_LICENSE("GPL");
net/netfilter/xt_TPROXY.c new file +1
-1+MODULE_ALIAS ("ipt_TPROXY" ); -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
Signature · 1 line
KOVACS Krisztian
Re: [PATCH 11/13] iptables TPROXY target
In reply to KOVACS KrisztianQuoted 11 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.)
Signed-off-by KOVACS Krisztian <[email protected]>---
+++b/include/linux/netfilter_ipv4/ipt_TPROXY.hinclude/linux/netfilter_ipv4/ipt_TPROXY.h new file +1
-0@@ -0,0 +1,14 @@ +#ifndef _IPT_TPROXY_H_target
include/linux/netfilter_ipv4/ipt_TPROXY.h line 11
Quoted 10 lines
include/linux/netfilter_ipv4/ipt_TPROXY.h new file +10
-0+#define _IPT_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 ipt_tproxy_target_info { +__be32 laddr; +__be16 lport; +unsigned long mark_mask; +unsigned long mark_value;
This should use fixed size types.
Quoted 71 lines
net/netfilter/xt_TPROXY.c new file +64
-0@@ -0,0 +1,139 @@ +/* +* 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/ipt_TPROXY.h> + +#include <net/netfilter/ipv4/nf_defrag_ipv4.h> +#include <net/netfilter/nf_tproxy_core.h> + +static unsigned int +target (struct sk_buff **pskb, +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 (*pskb); +const struct ipt_tproxy_target_info *tgi = + (const struct ipt_tproxy_target_info *) targinfo; +struct sk_buff *skb = *pskb; +struct udphdr _hdr, *hp; +struct sock *sk; + +/* TCP/UDP only */ +if ((iph->protocol !=IPPROTO_TCP ) && + (iph->protocol !=IPPROTO_UDP )) +return NF_ACCEPT ; + + hp =skb_header_pointer (*pskb, iph->ihl *4 ,sizeof (_hdr), &_hdr); +if (hp ==NULL ) +return NF_DROP ; + + sk =nf_tproxy_get_sock_v4 (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 %d %08x:%d -> %08x:%d, mark: %x\n" , + iph->protocol,ntohl (iph->daddr),ntohs (hp->dest), +ntohl (tgi->laddr),ntohs (tgi->lport), skb->mark); +return NF_ACCEPT ;
net/netfilter/xt_TPROXY.c line 74
Quoted 10 lines
net/netfilter/xt_TPROXY.c new file +10
-0+ } +else { +pr_debug ("no socket, dropping: proto %d %08x:%d -> %08x:%d, mark: %x\n" , + iph->protocol,ntohl (iph->daddr),ntohs (hp->dest), +ntohl (tgi->laddr),ntohs (tgi->lport), skb->mark); +return NF_DROP ; + } +} + +#ifdef CONFIG_COMPAT
All this compat stuff becomes unnecessary with fixed size types.
Re: [PATCH 11/13] iptables TPROXY target
Quoted 2 lines · Patrick McHardy
All this compat stuff becomes unnecessary with fixed size types.
Fixed size types alone won't do it. Think 64-bit. You would have {32, 16, 32, 32}, and I would be pretty sure they pad it up to {32, 16, [16], 32, 32}. Well, see my version, which avoids that :)
Re: [PATCH 11/13] iptables TPROXY target
In reply to Patrick McHardyHi Patrick,
Quoted 15 lines · Patrick McHardy
Quoted 14 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.)
Signed-off-by KOVACS Krisztian <[email protected]>---
+++b/include/linux/netfilter_ipv4/ipt_TPROXY.hinclude/linux/netfilter_ipv4/ipt_TPROXY.h new file +5
-0@@ -0,0 +1,14 @@ +#ifndef _IPT_TPROXY_H_target +#define _IPT_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
Quoted 8 lines
include/linux/netfilter_ipv4/ipt_TPROXY.h line 11
Quoted 6 lines
include/linux/netfilter_ipv4/ipt_TPROXY.h new file +6
-0+* mutliple targets in the same rule. */ +struct ipt_tproxy_target_info { +__be32 laddr; +__be16 lport; +unsigned long mark_mask; +unsigned long mark_value;This should use fixed size types.
Yes, but marks are unsigned longs, aren't they? So if we restrict this to say 32bit then we lose the ability to use the upper half of the mark...
Quoted 83 lines
Quoted 75 lines
net/netfilter/xt_TPROXY.c new file +7
-0@@ -0,0 +1,139 @@ +/* +* 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.
+ *
+ */net/netfilter/xt_TPROXY.c new file +56
-0+ +#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/ipt_TPROXY.h> + +#include <net/netfilter/ipv4/nf_defrag_ipv4.h> +#include <net/netfilter/nf_tproxy_core.h> + +static unsigned int +target (struct sk_buff **pskb, +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 (*pskb); +const struct ipt_tproxy_target_info *tgi = + (const struct ipt_tproxy_target_info *) targinfo; +struct sk_buff *skb = *pskb; +struct udphdr _hdr, *hp; +struct sock *sk; + +/* TCP/UDP only */ +if ((iph->protocol !=IPPROTO_TCP ) && + (iph->protocol !=IPPROTO_UDP )) +return NF_ACCEPT ; + + hp =skb_header_pointer (*pskb, iph->ihl *4 ,sizeof (_hdr), &_hdr); +if (hp ==NULL ) +return NF_DROP ; + + sk =nf_tproxy_get_sock_v4 (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 %d %08x:%d -> %08x:%d, mark: %x\n" , + iph->protocol,ntohl (iph->daddr),ntohs (hp->dest), +ntohl (tgi->laddr),ntohs (tgi->lport), skb->mark); +return NF_ACCEPT ; + } +else { + pr_debug("no socket, dropping: proto %d %08x:%d -> %08x:%d, mark:%x\n", +
iph->protocol,ntohl(iph->daddr),ntohs(hp->dest),net/netfilter/xt_TPROXY.c line 74
Quoted 6 lines
net/netfilter/xt_TPROXY.c new file +6
-0+ ntohl(tgi->laddr), ntohs(tgi->lport), skb->mark); +return NF_DROP ; + } +} + +#ifdef CONFIG_COMPAT All this compat stuff becomes unnecessary with fixed size types.
Signature · 1 line
KOVACS Krisztian
Re: [PATCH 11/13] iptables TPROXY target
Quoted 11 lines · KOVACS Krisztian
Quoted 10 lines
include/linux/netfilter_ipv4/ipt_TPROXY.h line 11
Quoted 8 lines
include/linux/netfilter_ipv4/ipt_TPROXY.h new file +8
-0+/* 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 ipt_tproxy_target_info { +__be32 laddr; +__be16 lport; +unsigned long mark_mask; +unsigned long mark_value;This should use fixed size types.
Quoted 2 lines
Yes, but marks are unsigned longs, aren't they? So if we restrict this to say 32bit then we lose the ability to use the upper half of the mark...
longs are 32 and 64 bits, resp. A 64-bit kernel with a 32-bit userland, well it speaks for itself.
The more I am puzzled as to why xt_MARK.h, xt_mark.h, xt_CONNMARK.h, xt_connmark.h use longs, and not uint32_t! Only xt_SECMARK.h does it right...
Patrick, is this a longstanding 'bug'?
Re: [PATCH 11/13] iptables TPROXY target
Quoted 17 lines · Jan Engelhardt
Quoted 11 lines · KOVACS Krisztian
Quoted 10 lines
include/linux/netfilter_ipv4/ipt_TPROXY.h line 11
Quoted 8 lines
include/linux/netfilter_ipv4/ipt_TPROXY.h new file +8
-0+/* 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 ipt_tproxy_target_info { +__be32 laddr; +__be16 lport; +unsigned long mark_mask; +unsigned long mark_value;This should use fixed size types.
Quoted 2 lines
Yes, but marks are unsigned longs, aren't they? So if we restrict this to say 32bit then we lose the ability to use the upper half of the mark...
Quoted 7 lines
longs are 32 and 64 bits, resp. A 64-bit kernel with a 32-bit userland, well it speaks for itself.
The more I am puzzled as to why
xt_MARK.h,xt_mark.h,xt_CONNMARK.h,xt_connmark.huse longs, and notuint32_t! Onlyxt_SECMARK.hdoes it right...Patrick, is this a longstanding 'bug'?
Not a bug, compatiblity crap. skb->nfmark used to be unsigned long, but since a) it sucks to have userspace-visible stuff like this depend on the architecture and b) routing, classifiers etc. all only supported 32 bits, we've changed it.
Re: [PATCH 11/13] iptables TPROXY target
In reply to KOVACS KrisztianQuoted 30 lines · KOVACS Krisztian
Hi Patrick,
Quoted 16 lines · Patrick McHardy
Quoted 14 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.)
Signed-off-by KOVACS Krisztian <[email protected]>---
+++b/include/linux/netfilter_ipv4/ipt_TPROXY.hinclude/linux/netfilter_ipv4/ipt_TPROXY.h new file +5
-0@@ -0,0 +1,14 @@ +#ifndef _IPT_TPROXY_H_target +#define _IPT_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 Quoted 9 lines
include/linux/netfilter_ipv4/ipt_TPROXY.h line 11
Quoted 7 lines
include/linux/netfilter_ipv4/ipt_TPROXY.h new file +6
-0+* mutliple targets in the same rule. */ +struct ipt_tproxy_target_info { +__be32 laddr; +__be16 lport; +unsigned long mark_mask; +unsigned long mark_value;This should use fixed size types.
Quoted 2 lines
Yes, but marks are unsigned longs, aren't they? So if we restrict this to say 32bit then we lose the ability to use the upper half of the mark...
No, marks are 32 bit for a long time now. The unsigned longs in the mark target and matches are just there for compatiblity.
(BTW, going to sleep now, will continue tommorrow)
Re: [PATCH 11/13] iptables TPROXY target
Hi Patrick,
Quoted 29 lines · Patrick McHardy
Quoted 28 lines · KOVACS Krisztian
Hi Patrick,
Quoted 24 lines · Patrick McHardy
Quoted 11 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.)
Signed-off-by KOVACS Krisztian <[email protected]>---
+++b/include/linux/netfilter_ipv4/ipt_TPROXY.hinclude/linux/netfilter_ipv4/ipt_TPROXY.h new file +1
-0@@ -0,0 +1,14 @@ +#ifndef _IPT_TPROXY_H_targetinclude/linux/netfilter_ipv4/ipt_TPROXY.h line 11
Quoted 10 lines
include/linux/netfilter_ipv4/ipt_TPROXY.h new file +10
-0+#define _IPT_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 ipt_tproxy_target_info { +__be32 laddr; +__be16 lport; +unsigned long mark_mask; +unsigned long mark_value;This should use fixed size types.
Quoted 6 lines
Quoted 3 lines
Yes, but marks are unsigned longs, aren't they? So if we restrict this to say 32bit then we lose the ability to use the upper half of the mark...
No, marks are 32 bit for a long time now. The unsigned longs in the mark target and matches are just there for compatiblity.
Indeed, I must have missed this. Obviously if this is the case then we don't need all this cruft and can simply use 32 bit mark fields (and the reordered info structure Jan suggested.)
Quoted 1 line
(BTW, going to sleep now, will continue tommorrow)
OK, me too. :)
Signature · 1 line
KOVACS Krisztian
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
@@ -1658,6 +1658,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_IP_NF_TPROXY ) || defined (CONFIG_IP_NF_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_IP_NF_TPROXY ) || defined (CONFIG_IP_NF_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 );
Quoted 74 lines · KOVACS Krisztian
Hi Patrick,
These patches are our (Balazs, Attila and me) third try at providing Linux 2.2-like transparent proxying support for Linux 2.6. During the 5th Netfilter Workshop in Karlsruhe, Germany we tried to come up with an even more lightweight approach not requiring the modification of the IPv4 routing code at all.
The most important changes relative to the previous versions[1,2] are:
* the tproxy table is gone, TPROXY targets need to be added to the mangle table instead
* the tproxy match is gone, a new "socket" match is introduced
* instead of using a separate routing trick to divert packets to the local IP stack inside the TProxy target, we are now using stock routing decisions, and need a bit in the packet MARK field, and perform diversion by using an advanced routing rule (this hopefully makes it possible to implement IPv6 support in the future
* instead ofIP_FREEBINDwe are using a setsockopt namedIP_TRANSPARENTwhich requiresCAP_NET_ADMINprivilege
* in previous patches the output routing decision was commented out, it is now correctly decided whether a packet belongs to a tproxied connection or not.Usage is a bit more complicated compared to the previous approach, but it's certainly not rocket science:
# iptables rules necessary: # create a chain named DIVERT iptables -t mangle -N DIVERT # everything that matches "-m socket" should go to the local stack iptables -t mangle -A PREROUTING -p tcp -m socket -j DIVERT # connections to be redirected should use the TPROXY target, which sets # up redirection, and marks the packet according to its 'tproxy-mark' # argument iptables -t mangle -A PREROUTING -p tcp --dport 80 -j TPROXY \ --tproxy-mark 0x1/0x1 --on-port 50080 # DIVERT chain: mark packets and accept iptables -t mangle -A DIVERT -j MARK --set-mark 1 iptables -t mangle -A DIVERT -j ACCEPT# set up advanced routing rules to deliver our marked packets locally ip rule add fwmark 1 lookup 100 ip route add local 0.0.0.0/0 dev lo table 100The proxy code needs to be modified as well, but these are really lightweight:
before binding, theIP_TRANSPARENTsockopt needs to be enabled on the socket. This impliesIP_FREEBIND, so after enabling this socket option non-local binds will work and if you got your iptables/iproute setup right non-local traffic will be delivered to/from the socket. A netcat patch demonstrating this is available[4] as an example.Some word about the patches:
* output path (patches 1-5): these modifications make it possible to output IPv4 datagrams with non-local IP addresses by:
- introducing a new flowi flag (FLOWI_FLAG_ANYSRC) which disables the source address check inip_route_output_slow()[3]
- adding theIP_TRANSPARENTsocket option (setting this requiresCAP_NET_ADMIN)
- settingFLOWI_FLAG_ANYSRCifIP_TRANSPARENTis enabled for the originating socket
- setFLOWI_FLAG_ANYSRCwhere appropriate for sending reply packets generated by the kernel; this requires extending theip_reply_argstructure with a flags field and adding anIP_REPLY_ARG_NOSRCCHECKflag* input patch (patches 6-13): these changes implement redirection support for TCP plus the iptables socket match and TPROXY target -- these provide the actual user interface:
- split IPv4 defragmentation into a separate module, as this is needed by both our target and match
- add a 'socket' match which does a socket lookup based on the destination tuple in the packet and matches is a socket has been found
- add a 'TPROXY' target which looks up a socket based on a modified IP/port tuple and stores the socket reference in the skb
- modifying the TCP/UDP input paths to use the stored socket reference if present
Quoted 4 lines
All kinds of comments welcome. Patrick, I'd like to ask you to review these patches and if no issues are found by you or by anyone on the list, please consider merging them.
Thanks for posting these patches. I'll gladly review them, but the patches touching things outside of netfilter need to go through netdev and Dave for merging.
Hi Patrick,
Quoted 3 lines · Patrick McHardy
Thanks for posting these patches. I'll gladly review them, but the patches touching things outside of netfilter need to go through netdev and Dave for merging.
Thanks a lot. I guess getting feedback from you and the list is very important -- we absolutely would like to hammer out as many problems as possible before posting to netdev/Dave. Not to mention the Netfilter specific parts... :)
Signature · 1 line
KOVACS Krisztian