root/net/netfilter/xt_socket.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. socket_match
  2. socket_mt4_v0
  3. socket_mt4_v1_v2_v3
  4. socket_mt6_v1_v2_v3
  5. socket_mt_enable_defrag
  6. socket_mt_v1_check
  7. socket_mt_v2_check
  8. socket_mt_v3_check
  9. socket_mt_init
  10. socket_mt_exit

   1 // SPDX-License-Identifier: GPL-2.0-only
   2 /*
   3  * Transparent proxy support for Linux/iptables
   4  *
   5  * Copyright (C) 2007-2008 BalaBit IT Ltd.
   6  * Author: Krisztian Kovacs
   7  */
   8 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
   9 #include <linux/module.h>
  10 #include <linux/skbuff.h>
  11 #include <linux/netfilter/x_tables.h>
  12 #include <linux/netfilter_ipv4/ip_tables.h>
  13 #include <net/tcp.h>
  14 #include <net/udp.h>
  15 #include <net/icmp.h>
  16 #include <net/sock.h>
  17 #include <net/inet_sock.h>
  18 #include <net/netfilter/ipv4/nf_defrag_ipv4.h>
  19 
  20 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
  21 #include <linux/netfilter_ipv6/ip6_tables.h>
  22 #include <net/inet6_hashtables.h>
  23 #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
  24 #endif
  25 
  26 #include <net/netfilter/nf_socket.h>
  27 #include <linux/netfilter/xt_socket.h>
  28 
  29 /* "socket" match based redirection (no specific rule)
  30  * ===================================================
  31  *
  32  * There are connections with dynamic endpoints (e.g. FTP data
  33  * connection) that the user is unable to add explicit rules
  34  * for. These are taken care of by a generic "socket" rule. It is
  35  * assumed that the proxy application is trusted to open such
  36  * connections without explicit iptables rule (except of course the
  37  * generic 'socket' rule). In this case the following sockets are
  38  * matched in preference order:
  39  *
  40  *   - match: if there's a fully established connection matching the
  41  *     _packet_ tuple
  42  *
  43  *   - match: if there's a non-zero bound listener (possibly with a
  44  *     non-local address) We don't accept zero-bound listeners, since
  45  *     then local services could intercept traffic going through the
  46  *     box.
  47  */
  48 static bool
  49 socket_match(const struct sk_buff *skb, struct xt_action_param *par,
  50              const struct xt_socket_mtinfo1 *info)
  51 {
  52         struct sk_buff *pskb = (struct sk_buff *)skb;
  53         struct sock *sk = skb->sk;
  54 
  55         if (sk && !net_eq(xt_net(par), sock_net(sk)))
  56                 sk = NULL;
  57 
  58         if (!sk)
  59                 sk = nf_sk_lookup_slow_v4(xt_net(par), skb, xt_in(par));
  60 
  61         if (sk) {
  62                 bool wildcard;
  63                 bool transparent = true;
  64 
  65                 /* Ignore sockets listening on INADDR_ANY,
  66                  * unless XT_SOCKET_NOWILDCARD is set
  67                  */
  68                 wildcard = (!(info->flags & XT_SOCKET_NOWILDCARD) &&
  69                             sk_fullsock(sk) &&
  70                             inet_sk(sk)->inet_rcv_saddr == 0);
  71 
  72                 /* Ignore non-transparent sockets,
  73                  * if XT_SOCKET_TRANSPARENT is used
  74                  */
  75                 if (info->flags & XT_SOCKET_TRANSPARENT)
  76                         transparent = inet_sk_transparent(sk);
  77 
  78                 if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard &&
  79                     transparent && sk_fullsock(sk))
  80                         pskb->mark = sk->sk_mark;
  81 
  82                 if (sk != skb->sk)
  83                         sock_gen_put(sk);
  84 
  85                 if (wildcard || !transparent)
  86                         sk = NULL;
  87         }
  88 
  89         return sk != NULL;
  90 }
  91 
  92 static bool
  93 socket_mt4_v0(const struct sk_buff *skb, struct xt_action_param *par)
  94 {
  95         static struct xt_socket_mtinfo1 xt_info_v0 = {
  96                 .flags = 0,
  97         };
  98 
  99         return socket_match(skb, par, &xt_info_v0);
 100 }
 101 
 102 static bool
 103 socket_mt4_v1_v2_v3(const struct sk_buff *skb, struct xt_action_param *par)
 104 {
 105         return socket_match(skb, par, par->matchinfo);
 106 }
 107 
 108 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
 109 static bool
 110 socket_mt6_v1_v2_v3(const struct sk_buff *skb, struct xt_action_param *par)
 111 {
 112         const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo;
 113         struct sk_buff *pskb = (struct sk_buff *)skb;
 114         struct sock *sk = skb->sk;
 115 
 116         if (sk && !net_eq(xt_net(par), sock_net(sk)))
 117                 sk = NULL;
 118 
 119         if (!sk)
 120                 sk = nf_sk_lookup_slow_v6(xt_net(par), skb, xt_in(par));
 121 
 122         if (sk) {
 123                 bool wildcard;
 124                 bool transparent = true;
 125 
 126                 /* Ignore sockets listening on INADDR_ANY
 127                  * unless XT_SOCKET_NOWILDCARD is set
 128                  */
 129                 wildcard = (!(info->flags & XT_SOCKET_NOWILDCARD) &&
 130                             sk_fullsock(sk) &&
 131                             ipv6_addr_any(&sk->sk_v6_rcv_saddr));
 132 
 133                 /* Ignore non-transparent sockets,
 134                  * if XT_SOCKET_TRANSPARENT is used
 135                  */
 136                 if (info->flags & XT_SOCKET_TRANSPARENT)
 137                         transparent = inet_sk_transparent(sk);
 138 
 139                 if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard &&
 140                     transparent && sk_fullsock(sk))
 141                         pskb->mark = sk->sk_mark;
 142 
 143                 if (sk != skb->sk)
 144                         sock_gen_put(sk);
 145 
 146                 if (wildcard || !transparent)
 147                         sk = NULL;
 148         }
 149 
 150         return sk != NULL;
 151 }
 152 #endif
 153 
 154 static int socket_mt_enable_defrag(struct net *net, int family)
 155 {
 156         switch (family) {
 157         case NFPROTO_IPV4:
 158                 return nf_defrag_ipv4_enable(net);
 159 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
 160         case NFPROTO_IPV6:
 161                 return nf_defrag_ipv6_enable(net);
 162 #endif
 163         }
 164         WARN_ONCE(1, "Unknown family %d\n", family);
 165         return 0;
 166 }
 167 
 168 static int socket_mt_v1_check(const struct xt_mtchk_param *par)
 169 {
 170         const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo;
 171         int err;
 172 
 173         err = socket_mt_enable_defrag(par->net, par->family);
 174         if (err)
 175                 return err;
 176 
 177         if (info->flags & ~XT_SOCKET_FLAGS_V1) {
 178                 pr_info_ratelimited("unknown flags 0x%x\n",
 179                                     info->flags & ~XT_SOCKET_FLAGS_V1);
 180                 return -EINVAL;
 181         }
 182         return 0;
 183 }
 184 
 185 static int socket_mt_v2_check(const struct xt_mtchk_param *par)
 186 {
 187         const struct xt_socket_mtinfo2 *info = (struct xt_socket_mtinfo2 *) par->matchinfo;
 188         int err;
 189 
 190         err = socket_mt_enable_defrag(par->net, par->family);
 191         if (err)
 192                 return err;
 193 
 194         if (info->flags & ~XT_SOCKET_FLAGS_V2) {
 195                 pr_info_ratelimited("unknown flags 0x%x\n",
 196                                     info->flags & ~XT_SOCKET_FLAGS_V2);
 197                 return -EINVAL;
 198         }
 199         return 0;
 200 }
 201 
 202 static int socket_mt_v3_check(const struct xt_mtchk_param *par)
 203 {
 204         const struct xt_socket_mtinfo3 *info =
 205                                     (struct xt_socket_mtinfo3 *)par->matchinfo;
 206         int err;
 207 
 208         err = socket_mt_enable_defrag(par->net, par->family);
 209         if (err)
 210                 return err;
 211         if (info->flags & ~XT_SOCKET_FLAGS_V3) {
 212                 pr_info_ratelimited("unknown flags 0x%x\n",
 213                                     info->flags & ~XT_SOCKET_FLAGS_V3);
 214                 return -EINVAL;
 215         }
 216         return 0;
 217 }
 218 
 219 static struct xt_match socket_mt_reg[] __read_mostly = {
 220         {
 221                 .name           = "socket",
 222                 .revision       = 0,
 223                 .family         = NFPROTO_IPV4,
 224                 .match          = socket_mt4_v0,
 225                 .hooks          = (1 << NF_INET_PRE_ROUTING) |
 226                                   (1 << NF_INET_LOCAL_IN),
 227                 .me             = THIS_MODULE,
 228         },
 229         {
 230                 .name           = "socket",
 231                 .revision       = 1,
 232                 .family         = NFPROTO_IPV4,
 233                 .match          = socket_mt4_v1_v2_v3,
 234                 .checkentry     = socket_mt_v1_check,
 235                 .matchsize      = sizeof(struct xt_socket_mtinfo1),
 236                 .hooks          = (1 << NF_INET_PRE_ROUTING) |
 237                                   (1 << NF_INET_LOCAL_IN),
 238                 .me             = THIS_MODULE,
 239         },
 240 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
 241         {
 242                 .name           = "socket",
 243                 .revision       = 1,
 244                 .family         = NFPROTO_IPV6,
 245                 .match          = socket_mt6_v1_v2_v3,
 246                 .checkentry     = socket_mt_v1_check,
 247                 .matchsize      = sizeof(struct xt_socket_mtinfo1),
 248                 .hooks          = (1 << NF_INET_PRE_ROUTING) |
 249                                   (1 << NF_INET_LOCAL_IN),
 250                 .me             = THIS_MODULE,
 251         },
 252 #endif
 253         {
 254                 .name           = "socket",
 255                 .revision       = 2,
 256                 .family         = NFPROTO_IPV4,
 257                 .match          = socket_mt4_v1_v2_v3,
 258                 .checkentry     = socket_mt_v2_check,
 259                 .matchsize      = sizeof(struct xt_socket_mtinfo1),
 260                 .hooks          = (1 << NF_INET_PRE_ROUTING) |
 261                                   (1 << NF_INET_LOCAL_IN),
 262                 .me             = THIS_MODULE,
 263         },
 264 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
 265         {
 266                 .name           = "socket",
 267                 .revision       = 2,
 268                 .family         = NFPROTO_IPV6,
 269                 .match          = socket_mt6_v1_v2_v3,
 270                 .checkentry     = socket_mt_v2_check,
 271                 .matchsize      = sizeof(struct xt_socket_mtinfo1),
 272                 .hooks          = (1 << NF_INET_PRE_ROUTING) |
 273                                   (1 << NF_INET_LOCAL_IN),
 274                 .me             = THIS_MODULE,
 275         },
 276 #endif
 277         {
 278                 .name           = "socket",
 279                 .revision       = 3,
 280                 .family         = NFPROTO_IPV4,
 281                 .match          = socket_mt4_v1_v2_v3,
 282                 .checkentry     = socket_mt_v3_check,
 283                 .matchsize      = sizeof(struct xt_socket_mtinfo1),
 284                 .hooks          = (1 << NF_INET_PRE_ROUTING) |
 285                                   (1 << NF_INET_LOCAL_IN),
 286                 .me             = THIS_MODULE,
 287         },
 288 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
 289         {
 290                 .name           = "socket",
 291                 .revision       = 3,
 292                 .family         = NFPROTO_IPV6,
 293                 .match          = socket_mt6_v1_v2_v3,
 294                 .checkentry     = socket_mt_v3_check,
 295                 .matchsize      = sizeof(struct xt_socket_mtinfo1),
 296                 .hooks          = (1 << NF_INET_PRE_ROUTING) |
 297                                   (1 << NF_INET_LOCAL_IN),
 298                 .me             = THIS_MODULE,
 299         },
 300 #endif
 301 };
 302 
 303 static int __init socket_mt_init(void)
 304 {
 305         return xt_register_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg));
 306 }
 307 
 308 static void __exit socket_mt_exit(void)
 309 {
 310         xt_unregister_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg));
 311 }
 312 
 313 module_init(socket_mt_init);
 314 module_exit(socket_mt_exit);
 315 
 316 MODULE_LICENSE("GPL");
 317 MODULE_AUTHOR("Krisztian Kovacs, Balazs Scheidler");
 318 MODULE_DESCRIPTION("x_tables socket match module");
 319 MODULE_ALIAS("ipt_socket");
 320 MODULE_ALIAS("ip6t_socket");

/* [<][>][^][v][top][bottom][index][help] */