]> git.ipfire.org Git - thirdparty/nftables.git/commitdiff
socket: add support for "wildcard" key
authorBalazs Scheidler <bazsi77@gmail.com>
Sat, 29 Aug 2020 07:04:01 +0000 (09:04 +0200)
committerPablo Neira Ayuso <pablo@netfilter.org>
Sat, 29 Aug 2020 11:16:46 +0000 (13:16 +0200)
iptables had a "-m socket --transparent" which didn't match sockets that are
bound to all addresses (e.g.  0.0.0.0 for ipv4, and ::0 for ipv6).  It was
possible to override this behavior by using --nowildcard, in which case it
did match zero bound sockets as well.

The issue is that nftables never included the wildcard check, so in effect
it behaved like "iptables -m socket --transparent --nowildcard" with no
means to exclude wildcarded listeners.

This is a problem as a user-space process that binds to 0.0.0.0:<port> that
enables IP_TRANSPARENT would effectively intercept traffic going in _any_
direction on the specific port, whereas in most cases, transparent proxies
would only need this for one specific address.

The solution is to add "socket wildcard" key to the nft_socket module, which
makes it possible to match on the wildcardness of a socket from
one's ruleset.

This is how to use it:

table inet haproxy {
chain prerouting {
         type filter hook prerouting priority -150; policy accept;
socket transparent 1 socket wildcard 0 mark set 0x00000001
}
}

This patch effectively depends on its counterpart in the kernel.

Signed-off-by: Balazs Scheidler <bazsi77@gmail.com>
Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
include/linux/netfilter/nf_tables.h
src/evaluate.c
src/parser_bison.y
src/parser_json.c
src/scanner.l
src/socket.c

index 1341b52f069423db112ec1ecc9b91856bc6ec086..10be073aeb8dd63942192ea7f1ac9536dbbaad79 100644 (file)
@@ -996,10 +996,12 @@ enum nft_socket_attributes {
  *
  * @NFT_SOCKET_TRANSPARENT: Value of the IP(V6)_TRANSPARENT socket option
  * @NFT_SOCKET_MARK: Value of the socket mark
+ * @NFT_SOCKET_WILDCARD: Whether the socket is zero-bound (e.g. 0.0.0.0 or ::0)
  */
 enum nft_socket_keys {
        NFT_SOCKET_TRANSPARENT,
        NFT_SOCKET_MARK,
+       NFT_SOCKET_WILDCARD,
        __NFT_SOCKET_MAX
 };
 #define NFT_SOCKET_MAX (__NFT_SOCKET_MAX - 1)
index 320a464f91628a85510ca9aba62727f826ebe6d5..8f133ea8c384f741eb8ab5874e6c3d426bb9d5a9 100644 (file)
@@ -1998,9 +1998,11 @@ static int expr_evaluate_meta(struct eval_ctx *ctx, struct expr **exprp)
 
 static int expr_evaluate_socket(struct eval_ctx *ctx, struct expr **expr)
 {
+       enum nft_socket_keys key = (*expr)->socket.key;
        int maxval = 0;
 
-       if((*expr)->socket.key == NFT_SOCKET_TRANSPARENT)
+       if (key == NFT_SOCKET_TRANSPARENT ||
+           key == NFT_SOCKET_WILDCARD)
                maxval = 1;
        __expr_set_context(&ctx->ectx, (*expr)->dtype, (*expr)->byteorder,
                           (*expr)->len, maxval);
index 95adc48fdd7b1bd4b822f6e096afc47c17a762db..d938f5665a678201792e1fed8e4d9e923f69be05 100644 (file)
@@ -213,6 +213,7 @@ int nft_lex(void *, void *, void *);
 
 %token SOCKET                  "socket"
 %token TRANSPARENT             "transparent"
+%token WILDCARD                        "wildcard"
 
 %token TPROXY                  "tproxy"
 
@@ -4595,6 +4596,7 @@ socket_expr               :       SOCKET  socket_key
 
 socket_key             :       TRANSPARENT     { $$ = NFT_SOCKET_TRANSPARENT; }
                        |       MARK            { $$ = NFT_SOCKET_MARK; }
+                       |       WILDCARD        { $$ = NFT_SOCKET_WILDCARD; }
                        ;
 
 offset_opt             :       /* empty */     { $$ = 0; }
index 59347168cdc86a7cc2b900ce6bba1d4c4adb867e..ac89166ec8a92699392dd1a05caff839a71343cb 100644 (file)
@@ -427,6 +427,8 @@ static struct expr *json_parse_socket_expr(struct json_ctx *ctx,
                keyval = NFT_SOCKET_TRANSPARENT;
        else if (!strcmp(key, "mark"))
                keyval = NFT_SOCKET_MARK;
+       else if (!strcmp(key, "wildcard"))
+               keyval = NFT_SOCKET_WILDCARD;
 
        if (keyval == -1) {
                json_error(ctx, "Invalid socket key value.");
index 45699c85d7d0d68fe0eda6ab05adb84ec73ec62d..9e6464f9b700efbd669816e213a174eb275561c8 100644 (file)
@@ -268,6 +268,7 @@ addrstring  ({macaddr}|{ip4addr}|{ip6addr})
 
 "socket"               { return SOCKET; }
 "transparent"          { return TRANSPARENT;}
+"wildcard"             { return WILDCARD; }
 
 "tproxy"               { return TPROXY; }
 
index d78a163a21fa3a3855f7d23f23e1234f09fa3861..673e5d0f570d6ca9ea380105f2de55c04200d659 100644 (file)
@@ -26,6 +26,12 @@ const struct socket_template socket_templates[] = {
                .len            = 4 * BITS_PER_BYTE,
                .byteorder      = BYTEORDER_HOST_ENDIAN,
        },
+       [NFT_SOCKET_WILDCARD] = {
+               .token          = "wildcard",
+               .dtype          = &integer_type,
+               .len            = BITS_PER_BYTE,
+               .byteorder      = BYTEORDER_HOST_ENDIAN,
+       },
 };
 
 static void socket_expr_print(const struct expr *expr, struct output_ctx *octx)