diff options
Diffstat (limited to 'include')
| -rw-r--r-- | include/linux/in6.h | 4 | ||||
| -rw-r--r-- | include/linux/ipv6.h | 4 | ||||
| -rw-r--r-- | include/linux/netfilter/xt_TPROXY.h | 13 | ||||
| -rw-r--r-- | include/net/inet_hashtables.h | 2 | ||||
| -rw-r--r-- | include/net/netfilter/ipv6/nf_defrag_ipv6.h | 6 | ||||
| -rw-r--r-- | include/net/netfilter/nf_tproxy_core.h | 192 | ||||
| -rw-r--r-- | include/net/udp.h | 3 |
7 files changed, 216 insertions, 8 deletions
diff --git a/include/linux/in6.h b/include/linux/in6.h index c4bf46f764bf..097a34b55560 100644 --- a/include/linux/in6.h +++ b/include/linux/in6.h | |||
| @@ -268,6 +268,10 @@ struct in6_flowlabel_req { | |||
| 268 | /* RFC5082: Generalized Ttl Security Mechanism */ | 268 | /* RFC5082: Generalized Ttl Security Mechanism */ |
| 269 | #define IPV6_MINHOPCOUNT 73 | 269 | #define IPV6_MINHOPCOUNT 73 |
| 270 | 270 | ||
| 271 | #define IPV6_ORIGDSTADDR 74 | ||
| 272 | #define IPV6_RECVORIGDSTADDR IPV6_ORIGDSTADDR | ||
| 273 | #define IPV6_TRANSPARENT 75 | ||
| 274 | |||
| 271 | /* | 275 | /* |
| 272 | * Multicast Routing: | 276 | * Multicast Routing: |
| 273 | * see include/linux/mroute6.h. | 277 | * see include/linux/mroute6.h. |
diff --git a/include/linux/ipv6.h b/include/linux/ipv6.h index e62683ba88e6..8e429d0e0405 100644 --- a/include/linux/ipv6.h +++ b/include/linux/ipv6.h | |||
| @@ -341,7 +341,9 @@ struct ipv6_pinfo { | |||
| 341 | odstopts:1, | 341 | odstopts:1, |
| 342 | rxflow:1, | 342 | rxflow:1, |
| 343 | rxtclass:1, | 343 | rxtclass:1, |
| 344 | rxpmtu:1; | 344 | rxpmtu:1, |
| 345 | rxorigdstaddr:1; | ||
| 346 | /* 2 bits hole */ | ||
| 345 | } bits; | 347 | } bits; |
| 346 | __u16 all; | 348 | __u16 all; |
| 347 | } rxopt; | 349 | } rxopt; |
diff --git a/include/linux/netfilter/xt_TPROXY.h b/include/linux/netfilter/xt_TPROXY.h index 152e8f97132b..3f3d69361289 100644 --- a/include/linux/netfilter/xt_TPROXY.h +++ b/include/linux/netfilter/xt_TPROXY.h | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | #ifndef _XT_TPROXY_H_target | 1 | #ifndef _XT_TPROXY_H |
| 2 | #define _XT_TPROXY_H_target | 2 | #define _XT_TPROXY_H |
| 3 | 3 | ||
| 4 | /* TPROXY target is capable of marking the packet to perform | 4 | /* TPROXY target is capable of marking the packet to perform |
| 5 | * redirection. We can get rid of that whenever we get support for | 5 | * redirection. We can get rid of that whenever we get support for |
| @@ -11,4 +11,11 @@ struct xt_tproxy_target_info { | |||
| 11 | __be16 lport; | 11 | __be16 lport; |
| 12 | }; | 12 | }; |
| 13 | 13 | ||
| 14 | #endif /* _XT_TPROXY_H_target */ | 14 | struct xt_tproxy_target_info_v1 { |
| 15 | u_int32_t mark_mask; | ||
| 16 | u_int32_t mark_value; | ||
| 17 | union nf_inet_addr laddr; | ||
| 18 | __be16 lport; | ||
| 19 | }; | ||
| 20 | |||
| 21 | #endif /* _XT_TPROXY_H */ | ||
diff --git a/include/net/inet_hashtables.h b/include/net/inet_hashtables.h index 74358d1b3f43..e9c2ed8af864 100644 --- a/include/net/inet_hashtables.h +++ b/include/net/inet_hashtables.h | |||
| @@ -245,7 +245,7 @@ static inline int inet_sk_listen_hashfn(const struct sock *sk) | |||
| 245 | } | 245 | } |
| 246 | 246 | ||
| 247 | /* Caller must disable local BH processing. */ | 247 | /* Caller must disable local BH processing. */ |
| 248 | extern void __inet_inherit_port(struct sock *sk, struct sock *child); | 248 | extern int __inet_inherit_port(struct sock *sk, struct sock *child); |
| 249 | 249 | ||
| 250 | extern void inet_put_port(struct sock *sk); | 250 | extern void inet_put_port(struct sock *sk); |
| 251 | 251 | ||
diff --git a/include/net/netfilter/ipv6/nf_defrag_ipv6.h b/include/net/netfilter/ipv6/nf_defrag_ipv6.h new file mode 100644 index 000000000000..94dd54d76b48 --- /dev/null +++ b/include/net/netfilter/ipv6/nf_defrag_ipv6.h | |||
| @@ -0,0 +1,6 @@ | |||
| 1 | #ifndef _NF_DEFRAG_IPV6_H | ||
| 2 | #define _NF_DEFRAG_IPV6_H | ||
| 3 | |||
| 4 | extern void nf_defrag_ipv6_enable(void); | ||
| 5 | |||
| 6 | #endif /* _NF_DEFRAG_IPV6_H */ | ||
diff --git a/include/net/netfilter/nf_tproxy_core.h b/include/net/netfilter/nf_tproxy_core.h index 208b46f4d6d2..cd85b3bc8327 100644 --- a/include/net/netfilter/nf_tproxy_core.h +++ b/include/net/netfilter/nf_tproxy_core.h | |||
| @@ -5,15 +5,201 @@ | |||
| 5 | #include <linux/in.h> | 5 | #include <linux/in.h> |
| 6 | #include <linux/skbuff.h> | 6 | #include <linux/skbuff.h> |
| 7 | #include <net/sock.h> | 7 | #include <net/sock.h> |
| 8 | #include <net/inet_sock.h> | 8 | #include <net/inet_hashtables.h> |
| 9 | #include <net/inet6_hashtables.h> | ||
| 9 | #include <net/tcp.h> | 10 | #include <net/tcp.h> |
| 10 | 11 | ||
| 12 | #define NFT_LOOKUP_ANY 0 | ||
| 13 | #define NFT_LOOKUP_LISTENER 1 | ||
| 14 | #define NFT_LOOKUP_ESTABLISHED 2 | ||
| 15 | |||
| 11 | /* look up and get a reference to a matching socket */ | 16 | /* look up and get a reference to a matching socket */ |
| 12 | extern struct sock * | 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 * | ||
| 13 | nf_tproxy_get_sock_v4(struct net *net, const u8 protocol, | 67 | nf_tproxy_get_sock_v4(struct net *net, const u8 protocol, |
| 14 | const __be32 saddr, const __be32 daddr, | 68 | const __be32 saddr, const __be32 daddr, |
| 15 | const __be16 sport, const __be16 dport, | 69 | const __be16 sport, const __be16 dport, |
| 16 | const struct net_device *in, bool listening); | 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 | daddr, dport, | ||
| 86 | in->ifindex); | ||
| 87 | |||
| 88 | /* NOTE: we return listeners even if bound to | ||
| 89 | * 0.0.0.0, those are filtered out in | ||
| 90 | * xt_socket, since xt_TPROXY needs 0 bound | ||
| 91 | * listeners too */ | ||
| 92 | |||
| 93 | break; | ||
| 94 | case NFT_LOOKUP_ESTABLISHED: | ||
| 95 | sk = inet_lookup_established(net, &tcp_hashinfo, | ||
| 96 | saddr, sport, daddr, dport, | ||
| 97 | in->ifindex); | ||
| 98 | break; | ||
| 99 | default: | ||
| 100 | WARN_ON(1); | ||
| 101 | sk = NULL; | ||
| 102 | break; | ||
| 103 | } | ||
| 104 | break; | ||
| 105 | case IPPROTO_UDP: | ||
| 106 | sk = udp4_lib_lookup(net, saddr, sport, daddr, dport, | ||
| 107 | in->ifindex); | ||
| 108 | if (sk && lookup_type != NFT_LOOKUP_ANY) { | ||
| 109 | int connected = (sk->sk_state == TCP_ESTABLISHED); | ||
| 110 | int wildcard = (inet_sk(sk)->inet_rcv_saddr == 0); | ||
| 111 | |||
| 112 | /* NOTE: we return listeners even if bound to | ||
| 113 | * 0.0.0.0, those are filtered out in | ||
| 114 | * xt_socket, since xt_TPROXY needs 0 bound | ||
| 115 | * listeners too */ | ||
| 116 | if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) || | ||
| 117 | (lookup_type == NFT_LOOKUP_LISTENER && connected)) { | ||
| 118 | sock_put(sk); | ||
| 119 | sk = NULL; | ||
| 120 | } | ||
| 121 | } | ||
| 122 | break; | ||
| 123 | default: | ||
| 124 | WARN_ON(1); | ||
| 125 | sk = NULL; | ||
| 126 | } | ||
| 127 | |||
| 128 | pr_debug("tproxy socket lookup: proto %u %08x:%u -> %08x:%u, lookup type: %d, sock %p\n", | ||
| 129 | protocol, ntohl(saddr), ntohs(sport), ntohl(daddr), ntohs(dport), lookup_type, sk); | ||
| 130 | |||
| 131 | return sk; | ||
| 132 | } | ||
| 133 | |||
| 134 | #if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE) | ||
| 135 | static inline struct sock * | ||
| 136 | nf_tproxy_get_sock_v6(struct net *net, const u8 protocol, | ||
| 137 | const struct in6_addr *saddr, const struct in6_addr *daddr, | ||
| 138 | const __be16 sport, const __be16 dport, | ||
| 139 | const struct net_device *in, int lookup_type) | ||
| 140 | { | ||
| 141 | struct sock *sk; | ||
| 142 | |||
| 143 | /* look up socket */ | ||
| 144 | switch (protocol) { | ||
| 145 | case IPPROTO_TCP: | ||
| 146 | switch (lookup_type) { | ||
| 147 | case NFT_LOOKUP_ANY: | ||
| 148 | sk = inet6_lookup(net, &tcp_hashinfo, | ||
| 149 | saddr, sport, daddr, dport, | ||
| 150 | in->ifindex); | ||
| 151 | break; | ||
| 152 | case NFT_LOOKUP_LISTENER: | ||
| 153 | sk = inet6_lookup_listener(net, &tcp_hashinfo, | ||
| 154 | daddr, ntohs(dport), | ||
| 155 | in->ifindex); | ||
| 156 | |||
| 157 | /* NOTE: we return listeners even if bound to | ||
| 158 | * 0.0.0.0, those are filtered out in | ||
| 159 | * xt_socket, since xt_TPROXY needs 0 bound | ||
| 160 | * listeners too */ | ||
| 161 | |||
| 162 | break; | ||
| 163 | case NFT_LOOKUP_ESTABLISHED: | ||
| 164 | sk = __inet6_lookup_established(net, &tcp_hashinfo, | ||
| 165 | saddr, sport, daddr, ntohs(dport), | ||
| 166 | in->ifindex); | ||
| 167 | break; | ||
| 168 | default: | ||
| 169 | WARN_ON(1); | ||
| 170 | sk = NULL; | ||
| 171 | break; | ||
| 172 | } | ||
| 173 | break; | ||
| 174 | case IPPROTO_UDP: | ||
| 175 | sk = udp6_lib_lookup(net, saddr, sport, daddr, dport, | ||
| 176 | in->ifindex); | ||
| 177 | if (sk && lookup_type != NFT_LOOKUP_ANY) { | ||
| 178 | int connected = (sk->sk_state == TCP_ESTABLISHED); | ||
| 179 | int wildcard = ipv6_addr_any(&inet6_sk(sk)->rcv_saddr); | ||
| 180 | |||
| 181 | /* NOTE: we return listeners even if bound to | ||
| 182 | * 0.0.0.0, those are filtered out in | ||
| 183 | * xt_socket, since xt_TPROXY needs 0 bound | ||
| 184 | * listeners too */ | ||
| 185 | if ((lookup_type == NFT_LOOKUP_ESTABLISHED && (!connected || wildcard)) || | ||
| 186 | (lookup_type == NFT_LOOKUP_LISTENER && connected)) { | ||
| 187 | sock_put(sk); | ||
| 188 | sk = NULL; | ||
| 189 | } | ||
| 190 | } | ||
| 191 | break; | ||
| 192 | default: | ||
| 193 | WARN_ON(1); | ||
| 194 | sk = NULL; | ||
| 195 | } | ||
| 196 | |||
| 197 | pr_debug("tproxy socket lookup: proto %u %pI6:%u -> %pI6:%u, lookup type: %d, sock %p\n", | ||
| 198 | protocol, saddr, ntohs(sport), daddr, ntohs(dport), lookup_type, sk); | ||
| 199 | |||
| 200 | return sk; | ||
| 201 | } | ||
| 202 | #endif | ||
| 17 | 203 | ||
| 18 | static inline void | 204 | static inline void |
| 19 | nf_tproxy_put_sock(struct sock *sk) | 205 | nf_tproxy_put_sock(struct sock *sk) |
diff --git a/include/net/udp.h b/include/net/udp.h index a184d3496b13..200b82848c9a 100644 --- a/include/net/udp.h +++ b/include/net/udp.h | |||
| @@ -183,6 +183,9 @@ extern int udp_lib_setsockopt(struct sock *sk, int level, int optname, | |||
| 183 | extern struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, | 183 | extern struct sock *udp4_lib_lookup(struct net *net, __be32 saddr, __be16 sport, |
| 184 | __be32 daddr, __be16 dport, | 184 | __be32 daddr, __be16 dport, |
| 185 | int dif); | 185 | int dif); |
| 186 | extern struct sock *udp6_lib_lookup(struct net *net, const struct in6_addr *saddr, __be16 sport, | ||
| 187 | const struct in6_addr *daddr, __be16 dport, | ||
| 188 | int dif); | ||
| 186 | 189 | ||
| 187 | /* | 190 | /* |
| 188 | * SNMP statistics for UDP and UDP-Lite | 191 | * SNMP statistics for UDP and UDP-Lite |
