Skip to content

Commit 681f130

Browse files
edumazetummakynes
authored andcommitted
netfilter: xt_socket: add XT_SOCKET_NOWILDCARD flag
xt_socket module can be a nice replacement to conntrack module in some cases (SYN filtering for example) But it lacks the ability to match the 3rd packet of TCP handshake (ACK coming from the client). Add a XT_SOCKET_NOWILDCARD flag to disable the wildcard mechanism. The wildcard is the legacy socket match behavior, that ignores LISTEN sockets bound to INADDR_ANY (or ipv6 equivalent) iptables -I INPUT -p tcp --syn -j SYN_CHAIN iptables -I INPUT -m socket --nowildcard -j ACCEPT Signed-off-by: Eric Dumazet <edumazet@google.com> Cc: Patrick McHardy <kaber@trash.net> Cc: Jesper Dangaard Brouer <brouer@redhat.com> Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
1 parent 6547a22 commit 681f130

2 files changed

Lines changed: 69 additions & 8 deletions

File tree

include/uapi/linux/netfilter/xt_socket.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,17 @@
55

66
enum {
77
XT_SOCKET_TRANSPARENT = 1 << 0,
8+
XT_SOCKET_NOWILDCARD = 1 << 1,
89
};
910

1011
struct xt_socket_mtinfo1 {
1112
__u8 flags;
1213
};
14+
#define XT_SOCKET_FLAGS_V1 XT_SOCKET_TRANSPARENT
15+
16+
struct xt_socket_mtinfo2 {
17+
__u8 flags;
18+
};
19+
#define XT_SOCKET_FLAGS_V2 (XT_SOCKET_TRANSPARENT | XT_SOCKET_NOWILDCARD)
1320

1421
#endif /* _XT_SOCKET_H */

net/netfilter/xt_socket.c

Lines changed: 62 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -163,8 +163,11 @@ socket_match(const struct sk_buff *skb, struct xt_action_param *par,
163163
bool wildcard;
164164
bool transparent = true;
165165

166-
/* Ignore sockets listening on INADDR_ANY */
167-
wildcard = (sk->sk_state != TCP_TIME_WAIT &&
166+
/* Ignore sockets listening on INADDR_ANY,
167+
* unless XT_SOCKET_NOWILDCARD is set
168+
*/
169+
wildcard = (!(info->flags & XT_SOCKET_NOWILDCARD) &&
170+
sk->sk_state != TCP_TIME_WAIT &&
168171
inet_sk(sk)->inet_rcv_saddr == 0);
169172

170173
/* Ignore non-transparent sockets,
@@ -197,7 +200,7 @@ socket_mt4_v0(const struct sk_buff *skb, struct xt_action_param *par)
197200
}
198201

199202
static bool
200-
socket_mt4_v1(const struct sk_buff *skb, struct xt_action_param *par)
203+
socket_mt4_v1_v2(const struct sk_buff *skb, struct xt_action_param *par)
201204
{
202205
return socket_match(skb, par, par->matchinfo);
203206
}
@@ -259,7 +262,7 @@ extract_icmp6_fields(const struct sk_buff *skb,
259262
}
260263

261264
static bool
262-
socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par)
265+
socket_mt6_v1_v2(const struct sk_buff *skb, struct xt_action_param *par)
263266
{
264267
struct ipv6hdr *iph = ipv6_hdr(skb);
265268
struct udphdr _hdr, *hp = NULL;
@@ -302,8 +305,11 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par)
302305
bool wildcard;
303306
bool transparent = true;
304307

305-
/* Ignore sockets listening on INADDR_ANY */
306-
wildcard = (sk->sk_state != TCP_TIME_WAIT &&
308+
/* Ignore sockets listening on INADDR_ANY
309+
* unless XT_SOCKET_NOWILDCARD is set
310+
*/
311+
wildcard = (!(info->flags & XT_SOCKET_NOWILDCARD) &&
312+
sk->sk_state != TCP_TIME_WAIT &&
307313
ipv6_addr_any(&inet6_sk(sk)->rcv_saddr));
308314

309315
/* Ignore non-transparent sockets,
@@ -331,6 +337,28 @@ socket_mt6_v1(const struct sk_buff *skb, struct xt_action_param *par)
331337
}
332338
#endif
333339

340+
static int socket_mt_v1_check(const struct xt_mtchk_param *par)
341+
{
342+
const struct xt_socket_mtinfo1 *info = (struct xt_socket_mtinfo1 *) par->matchinfo;
343+
344+
if (info->flags & ~XT_SOCKET_FLAGS_V1) {
345+
pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V1);
346+
return -EINVAL;
347+
}
348+
return 0;
349+
}
350+
351+
static int socket_mt_v2_check(const struct xt_mtchk_param *par)
352+
{
353+
const struct xt_socket_mtinfo2 *info = (struct xt_socket_mtinfo2 *) par->matchinfo;
354+
355+
if (info->flags & ~XT_SOCKET_FLAGS_V2) {
356+
pr_info("unknown flags 0x%x\n", info->flags & ~XT_SOCKET_FLAGS_V2);
357+
return -EINVAL;
358+
}
359+
return 0;
360+
}
361+
334362
static struct xt_match socket_mt_reg[] __read_mostly = {
335363
{
336364
.name = "socket",
@@ -345,7 +373,8 @@ static struct xt_match socket_mt_reg[] __read_mostly = {
345373
.name = "socket",
346374
.revision = 1,
347375
.family = NFPROTO_IPV4,
348-
.match = socket_mt4_v1,
376+
.match = socket_mt4_v1_v2,
377+
.checkentry = socket_mt_v1_check,
349378
.matchsize = sizeof(struct xt_socket_mtinfo1),
350379
.hooks = (1 << NF_INET_PRE_ROUTING) |
351380
(1 << NF_INET_LOCAL_IN),
@@ -356,7 +385,32 @@ static struct xt_match socket_mt_reg[] __read_mostly = {
356385
.name = "socket",
357386
.revision = 1,
358387
.family = NFPROTO_IPV6,
359-
.match = socket_mt6_v1,
388+
.match = socket_mt6_v1_v2,
389+
.checkentry = socket_mt_v1_check,
390+
.matchsize = sizeof(struct xt_socket_mtinfo1),
391+
.hooks = (1 << NF_INET_PRE_ROUTING) |
392+
(1 << NF_INET_LOCAL_IN),
393+
.me = THIS_MODULE,
394+
},
395+
#endif
396+
{
397+
.name = "socket",
398+
.revision = 2,
399+
.family = NFPROTO_IPV4,
400+
.match = socket_mt4_v1_v2,
401+
.checkentry = socket_mt_v2_check,
402+
.matchsize = sizeof(struct xt_socket_mtinfo1),
403+
.hooks = (1 << NF_INET_PRE_ROUTING) |
404+
(1 << NF_INET_LOCAL_IN),
405+
.me = THIS_MODULE,
406+
},
407+
#ifdef XT_SOCKET_HAVE_IPV6
408+
{
409+
.name = "socket",
410+
.revision = 2,
411+
.family = NFPROTO_IPV6,
412+
.match = socket_mt6_v1_v2,
413+
.checkentry = socket_mt_v2_check,
360414
.matchsize = sizeof(struct xt_socket_mtinfo1),
361415
.hooks = (1 << NF_INET_PRE_ROUTING) |
362416
(1 << NF_INET_LOCAL_IN),

0 commit comments

Comments
 (0)