Commit 93742cf8af9dd3b053242b273040aa35fcbf93b3

Authored by Florian Westphal
Committed by Pablo Neira Ayuso
1 parent fd158d79d3

netfilter: tproxy: remove nf_tproxy_core.h

We've removed nf_tproxy_core.ko, so also remove its header.
The lookup helpers are split and then moved to tproxy target/socket match.

Signed-off-by: Florian Westphal <fw@strlen.de>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>

Showing 3 changed files with 220 additions and 212 deletions Side-by-side Diff

include/net/netfilter/nf_tproxy_core.h
1   -#ifndef _NF_TPROXY_CORE_H
2   -#define _NF_TPROXY_CORE_H
3   -
4   -#include <linux/types.h>
5   -#include <linux/in.h>
6   -#include <linux/skbuff.h>
7   -#include <net/sock.h>
8   -#include <net/inet_hashtables.h>
9   -#include <net/inet6_hashtables.h>
10   -#include <net/tcp.h>
11   -
12   -#define NFT_LOOKUP_ANY 0
13   -#define NFT_LOOKUP_LISTENER 1
14   -#define NFT_LOOKUP_ESTABLISHED 2
15   -
16   -/* look up and get a reference to a matching socket */
17   -
18   -
19   -/* This function is used by the 'TPROXY' target and the 'socket'
20   - * match. The following lookups are supported:
21   - *
22   - * Explicit TProxy target rule
23   - * ===========================
24   - *
25   - * This is used when the user wants to intercept a connection matching
26   - * an explicit iptables rule. In this case the sockets are assumed
27   - * matching in preference order:
28   - *
29   - * - match: if there's a fully established connection matching the
30   - * _packet_ tuple, it is returned, assuming the redirection
31   - * already took place and we process a packet belonging to an
32   - * established connection
33   - *
34   - * - match: if there's a listening socket matching the redirection
35   - * (e.g. on-port & on-ip of the connection), it is returned,
36   - * regardless if it was bound to 0.0.0.0 or an explicit
37   - * address. The reasoning is that if there's an explicit rule, it
38   - * does not really matter if the listener is bound to an interface
39   - * or to 0. The user already stated that he wants redirection
40   - * (since he added the rule).
41   - *
42   - * "socket" match based redirection (no specific rule)
43   - * ===================================================
44   - *
45   - * There are connections with dynamic endpoints (e.g. FTP data
46   - * connection) that the user is unable to add explicit rules
47   - * for. These are taken care of by a generic "socket" rule. It is
48   - * assumed that the proxy application is trusted to open such
49   - * connections without explicit iptables rule (except of course the
50   - * generic 'socket' rule). In this case the following sockets are
51   - * matched in preference order:
52   - *
53   - * - match: if there's a fully established connection matching the
54   - * _packet_ tuple
55   - *
56   - * - match: if there's a non-zero bound listener (possibly with a
57   - * non-local address) We don't accept zero-bound listeners, since
58   - * then local services could intercept traffic going through the
59   - * box.
60   - *
61   - * Please note that there's an overlap between what a TPROXY target
62   - * and a socket match will match. Normally if you have both rules the
63   - * "socket" match will be the first one, effectively all packets
64   - * belonging to established connections going through that one.
65   - */
66   -static inline struct sock *
67   -nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
68   - const __be32 saddr, const __be32 daddr,
69   - const __be16 sport, const __be16 dport,
70   - const struct net_device *in, int lookup_type)
71   -{
72   - struct sock *sk;
73   -
74   - /* look up socket */
75   - switch (protocol) {
76   - case IPPROTO_TCP:
77   - switch (lookup_type) {
78   - case NFT_LOOKUP_ANY:
79   - sk = __inet_lookup(net, &tcp_hashinfo,
80   - saddr, sport, daddr, dport,
81   - in->ifindex);
82   - break;
83   - case NFT_LOOKUP_LISTENER:
84   - sk = inet_lookup_listener(net, &tcp_hashinfo,
85   - saddr, sport,
86   - daddr, dport,
87   - in->ifindex);
88   -
89   - /* NOTE: we return listeners even if bound to
90   - * 0.0.0.0, those are filtered out in
91   - * xt_socket, since xt_TPROXY needs 0 bound
92   - * listeners too */
93   -
94   - break;
95   - case NFT_LOOKUP_ESTABLISHED:
96   - sk = inet_lookup_established(net, &tcp_hashinfo,
97   - saddr, sport, daddr, dport,
98   - in->ifindex);
99   - break;
100   - default:
101   - WARN_ON(1);
102   - sk = NULL;
103   - break;
104   - }
105   - break;
106   - case IPPROTO_UDP:
107   - sk = udp4_lib_lookup(net, saddr, sport, daddr, dport,
108   - in->ifindex);
109   - if (sk && lookup_type != NFT_LOOKUP_ANY) {
110   - int connected = (sk->sk_state == TCP_ESTABLISHED);
111   - int wildcard = (inet_sk(sk)->inet_rcv_saddr == 0);
112   -
113   - /* NOTE: we return listeners even if bound to
114   - * 0.0.0.0, those are filtered out in
115   - * xt_socket, since xt_TPROXY needs 0 bound
116   - * listeners too */
117   - if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) ||
118   - (lookup_type == NFT_LOOKUP_LISTENER && connected)) {
119   - sock_put(sk);
120   - sk = NULL;
121   - }
122   - }
123   - break;
124   - default:
125   - WARN_ON(1);
126   - sk = NULL;
127   - }
128   -
129   - pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u, lookup type: %d, sock %p\n",
130   - protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), lookup_type, sk);
131   -
132   - return sk;
133   -}
134   -
135   -#if IS_ENABLED(CONFIG_IPV6)
136   -static inline struct sock *
137   -nf_tproxy_get_sock_v6(struct net *net, const u8 protocol,
138   - const struct in6_addr *saddr, const struct in6_addr *daddr,
139   - const __be16 sport, const __be16 dport,
140   - const struct net_device *in, int lookup_type)
141   -{
142   - struct sock *sk;
143   -
144   - /* look up socket */
145   - switch (protocol) {
146   - case IPPROTO_TCP:
147   - switch (lookup_type) {
148   - case NFT_LOOKUP_ANY:
149   - sk = inet6_lookup(net, &tcp_hashinfo,
150   - saddr, sport, daddr, dport,
151   - in->ifindex);
152   - break;
153   - case NFT_LOOKUP_LISTENER:
154   - sk = inet6_lookup_listener(net, &tcp_hashinfo,
155   - saddr, sport,
156   - daddr, ntohs(dport),
157   - in->ifindex);
158   -
159   - /* NOTE: we return listeners even if bound to
160   - * 0.0.0.0, those are filtered out in
161   - * xt_socket, since xt_TPROXY needs 0 bound
162   - * listeners too */
163   -
164   - break;
165   - case NFT_LOOKUP_ESTABLISHED:
166   - sk = __inet6_lookup_established(net, &tcp_hashinfo,
167   - saddr, sport, daddr, ntohs(dport),
168   - in->ifindex);
169   - break;
170   - default:
171   - WARN_ON(1);
172   - sk = NULL;
173   - break;
174   - }
175   - break;
176   - case IPPROTO_UDP:
177   - sk = udp6_lib_lookup(net, saddr, sport, daddr, dport,
178   - in->ifindex);
179   - if (sk && lookup_type != NFT_LOOKUP_ANY) {
180   - int connected = (sk->sk_state == TCP_ESTABLISHED);
181   - int wildcard = ipv6_addr_any(&inet6_sk(sk)->rcv_saddr);
182   -
183   - /* NOTE: we return listeners even if bound to
184   - * 0.0.0.0, those are filtered out in
185   - * xt_socket, since xt_TPROXY needs 0 bound
186   - * listeners too */
187   - if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) ||
188   - (lookup_type == NFT_LOOKUP_LISTENER && connected)) {
189   - sock_put(sk);
190   - sk = NULL;
191   - }
192   - }
193   - break;
194   - default:
195   - WARN_ON(1);
196   - sk = NULL;
197   - }
198   -
199   - pr_debug("tproxy socket lookup: proto %u %pI6:%u -> %pI6:%u, lookup type: %d, sock %p\n",
200   - protocol, saddr, ntohs(sport), daddr, ntohs(dport), lookup_type, sk);
201   -
202   - return sk;
203   -}
204   -#endif
205   -
206   -#endif
net/netfilter/xt_TPROXY.c
... ... @@ -15,7 +15,9 @@
15 15 #include <linux/ip.h>
16 16 #include <net/checksum.h>
17 17 #include <net/udp.h>
  18 +#include <net/tcp.h>
18 19 #include <net/inet_sock.h>
  20 +#include <net/inet_hashtables.h>
19 21 #include <linux/inetdevice.h>
20 22 #include <linux/netfilter/x_tables.h>
21 23 #include <linux/netfilter_ipv4/ip_tables.h>
22 24  
23 25  
... ... @@ -26,13 +28,18 @@
26 28 #define XT_TPROXY_HAVE_IPV6 1
27 29 #include <net/if_inet6.h>
28 30 #include <net/addrconf.h>
  31 +#include <net/inet6_hashtables.h>
29 32 #include <linux/netfilter_ipv6/ip6_tables.h>
30 33 #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
31 34 #endif
32 35  
33   -#include <net/netfilter/nf_tproxy_core.h>
34 36 #include <linux/netfilter/xt_TPROXY.h>
35 37  
  38 +enum nf_tproxy_lookup_t {
  39 + NFT_LOOKUP_LISTENER,
  40 + NFT_LOOKUP_ESTABLISHED,
  41 +};
  42 +
36 43 static bool tproxy_sk_is_transparent(struct sock *sk)
37 44 {
38 45 if (sk->sk_state != TCP_TIME_WAIT) {
... ... @@ -67,6 +74,157 @@
67 74  
68 75 return laddr ? laddr : daddr;
69 76 }
  77 +
  78 +/*
  79 + * This is used when the user wants to intercept a connection matching
  80 + * an explicit iptables rule. In this case the sockets are assumed
  81 + * matching in preference order:
  82 + *
  83 + * - match: if there's a fully established connection matching the
  84 + * _packet_ tuple, it is returned, assuming the redirection
  85 + * already took place and we process a packet belonging to an
  86 + * established connection
  87 + *
  88 + * - match: if there's a listening socket matching the redirection
  89 + * (e.g. on-port & on-ip of the connection), it is returned,
  90 + * regardless if it was bound to 0.0.0.0 or an explicit
  91 + * address. The reasoning is that if there's an explicit rule, it
  92 + * does not really matter if the listener is bound to an interface
  93 + * or to 0. The user already stated that he wants redirection
  94 + * (since he added the rule).
  95 + *
  96 + * Please note that there's an overlap between what a TPROXY target
  97 + * and a socket match will match. Normally if you have both rules the
  98 + * "socket" match will be the first one, effectively all packets
  99 + * belonging to established connections going through that one.
  100 + */
  101 +static inline struct sock *
  102 +nf_tproxy_get_sock_v4(struct net *net, const u8 protocol,
  103 + const __be32 saddr, const __be32 daddr,
  104 + const __be16 sport, const __be16 dport,
  105 + const struct net_device *in,
  106 + const enum nf_tproxy_lookup_t lookup_type)
  107 +{
  108 + struct sock *sk;
  109 +
  110 + switch (protocol) {
  111 + case IPPROTO_TCP:
  112 + switch (lookup_type) {
  113 + case NFT_LOOKUP_LISTENER:
  114 + sk = inet_lookup_listener(net, &tcp_hashinfo,
  115 + saddr, sport,
  116 + daddr, dport,
  117 + in->ifindex);
  118 +
  119 + /* NOTE: we return listeners even if bound to
  120 + * 0.0.0.0, those are filtered out in
  121 + * xt_socket, since xt_TPROXY needs 0 bound
  122 + * listeners too
  123 + */
  124 + break;
  125 + case NFT_LOOKUP_ESTABLISHED:
  126 + sk = inet_lookup_established(net, &tcp_hashinfo,
  127 + saddr, sport, daddr, dport,
  128 + in->ifindex);
  129 + break;
  130 + default:
  131 + BUG();
  132 + }
  133 + break;
  134 + case IPPROTO_UDP:
  135 + sk = udp4_lib_lookup(net, saddr, sport, daddr, dport,
  136 + in->ifindex);
  137 + if (sk) {
  138 + int connected = (sk->sk_state == TCP_ESTABLISHED);
  139 + int wildcard = (inet_sk(sk)->inet_rcv_saddr == 0);
  140 +
  141 + /* NOTE: we return listeners even if bound to
  142 + * 0.0.0.0, those are filtered out in
  143 + * xt_socket, since xt_TPROXY needs 0 bound
  144 + * listeners too
  145 + */
  146 + if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) ||
  147 + (lookup_type == NFT_LOOKUP_LISTENER && connected)) {
  148 + sock_put(sk);
  149 + sk = NULL;
  150 + }
  151 + }
  152 + break;
  153 + default:
  154 + WARN_ON(1);
  155 + sk = NULL;
  156 + }
  157 +
  158 + pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u, lookup type: %d, sock %p\n",
  159 + protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), lookup_type, sk);
  160 +
  161 + return sk;
  162 +}
  163 +
  164 +#if IS_ENABLED(CONFIG_IPV6)
  165 +static inline struct sock *
  166 +nf_tproxy_get_sock_v6(struct net *net, const u8 protocol,
  167 + const struct in6_addr *saddr, const struct in6_addr *daddr,
  168 + const __be16 sport, const __be16 dport,
  169 + const struct net_device *in,
  170 + const enum nf_tproxy_lookup_t lookup_type)
  171 +{
  172 + struct sock *sk;
  173 +
  174 + switch (protocol) {
  175 + case IPPROTO_TCP:
  176 + switch (lookup_type) {
  177 + case NFT_LOOKUP_LISTENER:
  178 + sk = inet6_lookup_listener(net, &tcp_hashinfo,
  179 + saddr, sport,
  180 + daddr, ntohs(dport),
  181 + in->ifindex);
  182 +
  183 + /* NOTE: we return listeners even if bound to
  184 + * 0.0.0.0, those are filtered out in
  185 + * xt_socket, since xt_TPROXY needs 0 bound
  186 + * listeners too
  187 + */
  188 + break;
  189 + case NFT_LOOKUP_ESTABLISHED:
  190 + sk = __inet6_lookup_established(net, &tcp_hashinfo,
  191 + saddr, sport, daddr, ntohs(dport),
  192 + in->ifindex);
  193 + break;
  194 + default:
  195 + BUG();
  196 + }
  197 + break;
  198 + case IPPROTO_UDP:
  199 + sk = udp6_lib_lookup(net, saddr, sport, daddr, dport,
  200 + in->ifindex);
  201 + if (sk) {
  202 + int connected = (sk->sk_state == TCP_ESTABLISHED);
  203 + int wildcard = ipv6_addr_any(&inet6_sk(sk)->rcv_saddr);
  204 +
  205 + /* NOTE: we return listeners even if bound to
  206 + * 0.0.0.0, those are filtered out in
  207 + * xt_socket, since xt_TPROXY needs 0 bound
  208 + * listeners too
  209 + */
  210 + if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) ||
  211 + (lookup_type == NFT_LOOKUP_LISTENER && connected)) {
  212 + sock_put(sk);
  213 + sk = NULL;
  214 + }
  215 + }
  216 + break;
  217 + default:
  218 + WARN_ON(1);
  219 + sk = NULL;
  220 + }
  221 +
  222 + pr_debug("tproxy socket lookup: proto %u %pI6:%u -> %pI6:%u, lookup type: %d, sock %p\n",
  223 + protocol, saddr, ntohs(sport), daddr, ntohs(dport), lookup_type, sk);
  224 +
  225 + return sk;
  226 +}
  227 +#endif
70 228  
71 229 /**
72 230 * tproxy_handle_time_wait4 - handle IPv4 TCP TIME_WAIT reopen redirections
net/netfilter/xt_socket.c
... ... @@ -19,12 +19,12 @@
19 19 #include <net/icmp.h>
20 20 #include <net/sock.h>
21 21 #include <net/inet_sock.h>
22   -#include <net/netfilter/nf_tproxy_core.h>
23 22 #include <net/netfilter/ipv4/nf_defrag_ipv4.h>
24 23  
25 24 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
26 25 #define XT_SOCKET_HAVE_IPV6 1
27 26 #include <linux/netfilter_ipv6/ip6_tables.h>
  27 +#include <net/inet6_hashtables.h>
28 28 #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
29 29 #endif
30 30  
... ... @@ -101,6 +101,43 @@
101 101 return 0;
102 102 }
103 103  
  104 +/* "socket" match based redirection (no specific rule)
  105 + * ===================================================
  106 + *
  107 + * There are connections with dynamic endpoints (e.g. FTP data
  108 + * connection) that the user is unable to add explicit rules
  109 + * for. These are taken care of by a generic "socket" rule. It is
  110 + * assumed that the proxy application is trusted to open such
  111 + * connections without explicit iptables rule (except of course the
  112 + * generic 'socket' rule). In this case the following sockets are
  113 + * matched in preference order:
  114 + *
  115 + * - match: if there's a fully established connection matching the
  116 + * _packet_ tuple
  117 + *
  118 + * - match: if there's a non-zero bound listener (possibly with a
  119 + * non-local address) We don't accept zero-bound listeners, since
  120 + * then local services could intercept traffic going through the
  121 + * box.
  122 + */
  123 +static struct sock *
  124 +xt_socket_get_sock_v4(struct net *net, const u8 protocol,
  125 + const __be32 saddr, const __be32 daddr,
  126 + const __be16 sport, const __be16 dport,
  127 + const struct net_device *in)
  128 +{
  129 + switch (protocol) {
  130 + case IPPROTO_TCP:
  131 + return __inet_lookup(net, &tcp_hashinfo,
  132 + saddr, sport, daddr, dport,
  133 + in->ifindex);
  134 + case IPPROTO_UDP:
  135 + return udp4_lib_lookup(net, saddr, sport, daddr, dport,
  136 + in->ifindex);
  137 + }
  138 + return NULL;
  139 +}
  140 +
104 141 static bool
105 142 socket_match(const struct sk_buff *skb, struct xt_action_param *par,
106 143 const struct xt_socket_mtinfo1 *info)
107 144  
... ... @@ -156,9 +193,9 @@
156 193 #endif
157 194  
158 195 if (!sk)
159   - sk = nf_tproxy_get_sock_v4(dev_net(skb->dev), protocol,
  196 + sk = xt_socket_get_sock_v4(dev_net(skb->dev), protocol,
160 197 saddr, daddr, sport, dport,
161   - par->in, NFT_LOOKUP_ANY);
  198 + par->in);
162 199 if (sk) {
163 200 bool wildcard;
164 201 bool transparent = true;
... ... @@ -261,6 +298,25 @@
261 298 return 0;
262 299 }
263 300  
  301 +static struct sock *
  302 +xt_socket_get_sock_v6(struct net *net, const u8 protocol,
  303 + const struct in6_addr *saddr, const struct in6_addr *daddr,
  304 + const __be16 sport, const __be16 dport,
  305 + const struct net_device *in)
  306 +{
  307 + switch (protocol) {
  308 + case IPPROTO_TCP:
  309 + return inet6_lookup(net, &tcp_hashinfo,
  310 + saddr, sport, daddr, dport,
  311 + in->ifindex);
  312 + case IPPROTO_UDP:
  313 + return udp6_lib_lookup(net, saddr, sport, daddr, dport,
  314 + in->ifindex);
  315 + }
  316 +
  317 + return NULL;
  318 +}
  319 +
264 320 static bool
265 321 socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par)
266 322 {
267 323  
... ... @@ -298,9 +354,9 @@
298 354 }
299 355  
300 356 if (!sk)
301   - sk = nf_tproxy_get_sock_v6(dev_net(skb->dev), tproto,
  357 + sk = xt_socket_get_sock_v6(dev_net(skb->dev), tproto,
302 358 saddr, daddr, sport, dport,
303   - par->in, NFT_LOOKUP_ANY);
  359 + par->in);
304 360 if (sk) {
305 361 bool wildcard;
306 362 bool transparent = true;