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 void socket_mt_destroy(const struct xt_mtdtor_param *par) 220 { 221 if (par->family == NFPROTO_IPV4) 222 nf_defrag_ipv4_disable(par->net); 223 else if (par->family == NFPROTO_IPV6) 224 nf_defrag_ipv4_disable(par->net); 225 } 226 227 static struct xt_match socket_mt_reg[] __read_mostly = { 228 { 229 .name = "socket", 230 .revision = 0, 231 .family = NFPROTO_IPV4, 232 .match = socket_mt4_v0, 233 .hooks = (1 << NF_INET_PRE_ROUTING) | 234 (1 << NF_INET_LOCAL_IN), 235 .me = THIS_MODULE, 236 }, 237 { 238 .name = "socket", 239 .revision = 1, 240 .family = NFPROTO_IPV4, 241 .match = socket_mt4_v1_v2_v3, 242 .destroy = socket_mt_destroy, 243 .checkentry = socket_mt_v1_check, 244 .matchsize = sizeof(struct xt_socket_mtinfo1), 245 .hooks = (1 << NF_INET_PRE_ROUTING) | 246 (1 << NF_INET_LOCAL_IN), 247 .me = THIS_MODULE, 248 }, 249 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) 250 { 251 .name = "socket", 252 .revision = 1, 253 .family = NFPROTO_IPV6, 254 .match = socket_mt6_v1_v2_v3, 255 .checkentry = socket_mt_v1_check, 256 .matchsize = sizeof(struct xt_socket_mtinfo1), 257 .destroy = socket_mt_destroy, 258 .hooks = (1 << NF_INET_PRE_ROUTING) | 259 (1 << NF_INET_LOCAL_IN), 260 .me = THIS_MODULE, 261 }, 262 #endif 263 { 264 .name = "socket", 265 .revision = 2, 266 .family = NFPROTO_IPV4, 267 .match = socket_mt4_v1_v2_v3, 268 .checkentry = socket_mt_v2_check, 269 .destroy = socket_mt_destroy, 270 .matchsize = sizeof(struct xt_socket_mtinfo1), 271 .hooks = (1 << NF_INET_PRE_ROUTING) | 272 (1 << NF_INET_LOCAL_IN), 273 .me = THIS_MODULE, 274 }, 275 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) 276 { 277 .name = "socket", 278 .revision = 2, 279 .family = NFPROTO_IPV6, 280 .match = socket_mt6_v1_v2_v3, 281 .checkentry = socket_mt_v2_check, 282 .destroy = socket_mt_destroy, 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 #endif 289 { 290 .name = "socket", 291 .revision = 3, 292 .family = NFPROTO_IPV4, 293 .match = socket_mt4_v1_v2_v3, 294 .checkentry = socket_mt_v3_check, 295 .destroy = socket_mt_destroy, 296 .matchsize = sizeof(struct xt_socket_mtinfo1), 297 .hooks = (1 << NF_INET_PRE_ROUTING) | 298 (1 << NF_INET_LOCAL_IN), 299 .me = THIS_MODULE, 300 }, 301 #if IS_ENABLED(CONFIG_IP6_NF_IPTABLES) 302 { 303 .name = "socket", 304 .revision = 3, 305 .family = NFPROTO_IPV6, 306 .match = socket_mt6_v1_v2_v3, 307 .checkentry = socket_mt_v3_check, 308 .destroy = socket_mt_destroy, 309 .matchsize = sizeof(struct xt_socket_mtinfo1), 310 .hooks = (1 << NF_INET_PRE_ROUTING) | 311 (1 << NF_INET_LOCAL_IN), 312 .me = THIS_MODULE, 313 }, 314 #endif 315 }; 316 317 static int __init socket_mt_init(void) 318 { 319 return xt_register_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg)); 320 } 321 322 static void __exit socket_mt_exit(void) 323 { 324 xt_unregister_matches(socket_mt_reg, ARRAY_SIZE(socket_mt_reg)); 325 } 326 327 module_init(socket_mt_init); 328 module_exit(socket_mt_exit); 329 330 MODULE_LICENSE("GPL"); 331 MODULE_AUTHOR("Krisztian Kovacs, Balazs Scheidler"); 332 MODULE_DESCRIPTION("x_tables socket match module"); 333 MODULE_ALIAS("ipt_socket"); 334 MODULE_ALIAS("ip6t_socket"); 335