Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Transparent proxy support for Linux/iptables
0004  *
0005  * Copyright (C) 2007-2008 BalaBit IT Ltd.
0006  * Author: Krisztian Kovacs
0007  */
0008 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0009 #include <linux/module.h>
0010 #include <linux/skbuff.h>
0011 #include <linux/netfilter/x_tables.h>
0012 #include <linux/netfilter_ipv4/ip_tables.h>
0013 #include <net/tcp.h>
0014 #include <net/udp.h>
0015 #include <net/icmp.h>
0016 #include <net/sock.h>
0017 #include <net/inet_sock.h>
0018 #include <net/netfilter/ipv4/nf_defrag_ipv4.h>
0019 
0020 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
0021 #include <linux/netfilter_ipv6/ip6_tables.h>
0022 #include <net/inet6_hashtables.h>
0023 #include <net/netfilter/ipv6/nf_defrag_ipv6.h>
0024 #endif
0025 
0026 #include <net/netfilter/nf_socket.h>
0027 #include <linux/netfilter/xt_socket.h>
0028 
0029 /* "socket" match based redirection (no specific rule)
0030  * ===================================================
0031  *
0032  * There are connections with dynamic endpoints (e.g. FTP data
0033  * connection) that the user is unable to add explicit rules
0034  * for. These are taken care of by a generic "socket" rule. It is
0035  * assumed that the proxy application is trusted to open such
0036  * connections without explicit iptables rule (except of course the
0037  * generic 'socket' rule). In this case the following sockets are
0038  * matched in preference order:
0039  *
0040  *   - match: if there's a fully established connection matching the
0041  *     _packet_ tuple
0042  *
0043  *   - match: if there's a non-zero bound listener (possibly with a
0044  *     non-local address) We don't accept zero-bound listeners, since
0045  *     then local services could intercept traffic going through the
0046  *     box.
0047  */
0048 static bool
0049 socket_match(const struct sk_buff *skb, struct xt_action_param *par,
0050          const struct xt_socket_mtinfo1 *info)
0051 {
0052     struct sk_buff *pskb = (struct sk_buff *)skb;
0053     struct sock *sk = skb->sk;
0054 
0055     if (sk && !net_eq(xt_net(par), sock_net(sk)))
0056         sk = NULL;
0057 
0058     if (!sk)
0059         sk = nf_sk_lookup_slow_v4(xt_net(par), skb, xt_in(par));
0060 
0061     if (sk) {
0062         bool wildcard;
0063         bool transparent = true;
0064 
0065         /* Ignore sockets listening on INADDR_ANY,
0066          * unless XT_SOCKET_NOWILDCARD is set
0067          */
0068         wildcard = (!(info->flags & XT_SOCKET_NOWILDCARD) &&
0069                 sk_fullsock(sk) &&
0070                 inet_sk(sk)->inet_rcv_saddr == 0);
0071 
0072         /* Ignore non-transparent sockets,
0073          * if XT_SOCKET_TRANSPARENT is used
0074          */
0075         if (info->flags & XT_SOCKET_TRANSPARENT)
0076             transparent = inet_sk_transparent(sk);
0077 
0078         if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard &&
0079             transparent && sk_fullsock(sk))
0080             pskb->mark = sk->sk_mark;
0081 
0082         if (sk != skb->sk)
0083             sock_gen_put(sk);
0084 
0085         if (wildcard || !transparent)
0086             sk = NULL;
0087     }
0088 
0089     return sk != NULL;
0090 }
0091 
0092 static bool
0093 socket_mt4_v0(const struct sk_buff *skb, struct xt_action_param *par)
0094 {
0095     static struct xt_socket_mtinfo1 xt_info_v0 = {
0096         .flags = 0,
0097     };
0098 
0099     return socket_match(skb, par, &xt_info_v0);
0100 }
0101 
0102 static bool
0103 socket_mt4_v1_v2_v3(const struct sk_buff *skb, struct xt_action_param *par)
0104 {
0105     return socket_match(skb, par, par->matchinfo);
0106 }
0107 
0108 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
0109 static bool
0110 socket_mt6_v1_v2_v3(const struct sk_buff *skb, struct xt_action_param *par)
0111 {
0112     const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo;
0113     struct sk_buff *pskb = (struct sk_buff *)skb;
0114     struct sock *sk = skb->sk;
0115 
0116     if (sk && !net_eq(xt_net(par), sock_net(sk)))
0117         sk = NULL;
0118 
0119     if (!sk)
0120         sk = nf_sk_lookup_slow_v6(xt_net(par), skb, xt_in(par));
0121 
0122     if (sk) {
0123         bool wildcard;
0124         bool transparent = true;
0125 
0126         /* Ignore sockets listening on INADDR_ANY
0127          * unless XT_SOCKET_NOWILDCARD is set
0128          */
0129         wildcard = (!(info->flags & XT_SOCKET_NOWILDCARD) &&
0130                 sk_fullsock(sk) &&
0131                 ipv6_addr_any(&sk->sk_v6_rcv_saddr));
0132 
0133         /* Ignore non-transparent sockets,
0134          * if XT_SOCKET_TRANSPARENT is used
0135          */
0136         if (info->flags & XT_SOCKET_TRANSPARENT)
0137             transparent = inet_sk_transparent(sk);
0138 
0139         if (info->flags & XT_SOCKET_RESTORESKMARK && !wildcard &&
0140             transparent && sk_fullsock(sk))
0141             pskb->mark = sk->sk_mark;
0142 
0143         if (sk != skb->sk)
0144             sock_gen_put(sk);
0145 
0146         if (wildcard || !transparent)
0147             sk = NULL;
0148     }
0149 
0150     return sk != NULL;
0151 }
0152 #endif
0153 
0154 static int socket_mt_enable_defrag(struct net *net, int family)
0155 {
0156     switch (family) {
0157     case NFPROTO_IPV4:
0158         return nf_defrag_ipv4_enable(net);
0159 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
0160     case NFPROTO_IPV6:
0161         return nf_defrag_ipv6_enable(net);
0162 #endif
0163     }
0164     WARN_ONCE(1, "Unknown family %d\n", family);
0165     return 0;
0166 }
0167 
0168 static int socket_mt_v1_check(const struct xt_mtchk_param *par)
0169 {
0170     const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo;
0171     int err;
0172 
0173     err = socket_mt_enable_defrag(par->net, par->family);
0174     if (err)
0175         return err;
0176 
0177     if (info->flags & ~XT_SOCKET_FLAGS_V1) {
0178         pr_info_ratelimited("unknown flags 0x%x\n",
0179                     info->flags & ~XT_SOCKET_FLAGS_V1);
0180         return -EINVAL;
0181     }
0182     return 0;
0183 }
0184 
0185 static int socket_mt_v2_check(const struct xt_mtchk_param *par)
0186 {
0187     const struct xt_socket_mtinfo2 *info = (struct xt_socket_mtinfo2 *) par->matchinfo;
0188     int err;
0189 
0190     err = socket_mt_enable_defrag(par->net, par->family);
0191     if (err)
0192         return err;
0193 
0194     if (info->flags & ~XT_SOCKET_FLAGS_V2) {
0195         pr_info_ratelimited("unknown flags 0x%x\n",
0196                     info->flags & ~XT_SOCKET_FLAGS_V2);
0197         return -EINVAL;
0198     }
0199     return 0;
0200 }
0201 
0202 static int socket_mt_v3_check(const struct xt_mtchk_param *par)
0203 {
0204     const struct xt_socket_mtinfo3 *info =
0205                     (struct xt_socket_mtinfo3 *)par->matchinfo;
0206     int err;
0207 
0208     err = socket_mt_enable_defrag(par->net, par->family);
0209     if (err)
0210         return err;
0211     if (info->flags & ~XT_SOCKET_FLAGS_V3) {
0212         pr_info_ratelimited("unknown flags 0x%x\n",
0213                     info->flags & ~XT_SOCKET_FLAGS_V3);
0214         return -EINVAL;
0215     }
0216     return 0;
0217 }
0218 
0219 static void socket_mt_destroy(const struct xt_mtdtor_param *par)
0220 {
0221     if (par->family == NFPROTO_IPV4)
0222         nf_defrag_ipv4_disable(par->net);
0223 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
0224     else if (par->family == NFPROTO_IPV6)
0225         nf_defrag_ipv6_disable(par->net);
0226 #endif
0227 }
0228 
0229 static struct xt_match socket_mt_reg[] __read_mostly = {
0230     {
0231         .name       = "socket",
0232         .revision   = 0,
0233         .family     = NFPROTO_IPV4,
0234         .match      = socket_mt4_v0,
0235         .hooks      = (1 << NF_INET_PRE_ROUTING) |
0236                   (1 << NF_INET_LOCAL_IN),
0237         .me     = THIS_MODULE,
0238     },
0239     {
0240         .name       = "socket",
0241         .revision   = 1,
0242         .family     = NFPROTO_IPV4,
0243         .match      = socket_mt4_v1_v2_v3,
0244         .destroy    = socket_mt_destroy,
0245         .checkentry = socket_mt_v1_check,
0246         .matchsize  = sizeof(struct xt_socket_mtinfo1),
0247         .hooks      = (1 << NF_INET_PRE_ROUTING) |
0248                   (1 << NF_INET_LOCAL_IN),
0249         .me     = THIS_MODULE,
0250     },
0251 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
0252     {
0253         .name       = "socket",
0254         .revision   = 1,
0255         .family     = NFPROTO_IPV6,
0256         .match      = socket_mt6_v1_v2_v3,
0257         .checkentry = socket_mt_v1_check,
0258         .matchsize  = sizeof(struct xt_socket_mtinfo1),
0259         .destroy    = socket_mt_destroy,
0260         .hooks      = (1 << NF_INET_PRE_ROUTING) |
0261                   (1 << NF_INET_LOCAL_IN),
0262         .me     = THIS_MODULE,
0263     },
0264 #endif
0265     {
0266         .name       = "socket",
0267         .revision   = 2,
0268         .family     = NFPROTO_IPV4,
0269         .match      = socket_mt4_v1_v2_v3,
0270         .checkentry = socket_mt_v2_check,
0271         .destroy    = socket_mt_destroy,
0272         .matchsize  = sizeof(struct xt_socket_mtinfo1),
0273         .hooks      = (1 << NF_INET_PRE_ROUTING) |
0274                   (1 << NF_INET_LOCAL_IN),
0275         .me     = THIS_MODULE,
0276     },
0277 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
0278     {
0279         .name       = "socket",
0280         .revision   = 2,
0281         .family     = NFPROTO_IPV6,
0282         .match      = socket_mt6_v1_v2_v3,
0283         .checkentry = socket_mt_v2_check,
0284         .destroy    = socket_mt_destroy,
0285         .matchsize  = sizeof(struct xt_socket_mtinfo1),
0286         .hooks      = (1 << NF_INET_PRE_ROUTING) |
0287                   (1 << NF_INET_LOCAL_IN),
0288         .me     = THIS_MODULE,
0289     },
0290 #endif
0291     {
0292         .name       = "socket",
0293         .revision   = 3,
0294         .family     = NFPROTO_IPV4,
0295         .match      = socket_mt4_v1_v2_v3,
0296         .checkentry = socket_mt_v3_check,
0297         .destroy    = socket_mt_destroy,
0298         .matchsize  = sizeof(struct xt_socket_mtinfo1),
0299         .hooks      = (1 << NF_INET_PRE_ROUTING) |
0300                   (1 << NF_INET_LOCAL_IN),
0301         .me     = THIS_MODULE,
0302     },
0303 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES)
0304     {
0305         .name       = "socket",
0306         .revision   = 3,
0307         .family     = NFPROTO_IPV6,
0308         .match      = socket_mt6_v1_v2_v3,
0309         .checkentry = socket_mt_v3_check,
0310         .destroy    = socket_mt_destroy,
0311         .matchsize  = sizeof(struct xt_socket_mtinfo1),
0312         .hooks      = (1 << NF_INET_PRE_ROUTING) |
0313                   (1 << NF_INET_LOCAL_IN),
0314         .me     = THIS_MODULE,
0315     },
0316 #endif
0317 };
0318 
0319 static int __init socket_mt_init(void)
0320 {
0321     return xt_register_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg));
0322 }
0323 
0324 static void __exit socket_mt_exit(void)
0325 {
0326     xt_unregister_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg));
0327 }
0328 
0329 module_init(socket_mt_init);
0330 module_exit(socket_mt_exit);
0331 
0332 MODULE_LICENSE("GPL");
0333 MODULE_AUTHOR("Krisztian Kovacs, Balazs Scheidler");
0334 MODULE_DESCRIPTION("x_tables socket match module");
0335 MODULE_ALIAS("ipt_socket");
0336 MODULE_ALIAS("ip6t_socket");