Re: [PATCH nftables 1/4] socket: add support for "wildcard" key

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Sat, 22 Aug 2020 08:22:00 +0200
Balazs Scheidler <bazsi77@xxxxxxxxx> wrote:

> 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@xxxxxxxxx>
> ---
>  src/evaluate.c     | 5 ++++-
>  src/parser_bison.y | 2 ++
>  src/parser_json.c  | 2 ++
>  src/scanner.l      | 1 +
>  src/socket.c       | 6 ++++++
>  5 files changed, 15 insertions(+), 1 deletion(-)
> 
> diff --git a/src/evaluate.c b/src/evaluate.c
> index b64ed3c0..28dade8a 100644
> --- a/src/evaluate.c
> +++ b/src/evaluate.c
> @@ -1999,8 +1999,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)
>  {
>  	int maxval = 0;
> +	
> +	enum nft_socket_keys key = (*expr)->socket.key;

The empty line before this isn't needed: it's another declaration.

>  
> -	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);
> diff --git a/src/parser_bison.y b/src/parser_bison.y
> index d4e99417..fff941e5 100644
> --- a/src/parser_bison.y
> +++ b/src/parser_bison.y
> @@ -213,6 +213,7 @@ int nft_lex(void *, void *, void *);
>  
>  %token SOCKET			"socket"
>  %token TRANSPARENT		"transparent"
> +%token WILDCARD			"wildcard"
>  
>  %token TPROXY			"tproxy"
>  
> @@ -4591,6 +4592,7 @@ socket_expr		:	SOCKET	socket_key
>  
>  socket_key 		: 	TRANSPARENT	{ $$ = NFT_SOCKET_TRANSPARENT; }
>  			|	MARK		{ $$ = NFT_SOCKET_MARK; }
> +			|	WILDCARD	{ $$ = NFT_SOCKET_WILDCARD; }
>  			;
>  
>  offset_opt		:	/* empty */	{ $$ = 0; }
> diff --git a/src/parser_json.c b/src/parser_json.c
> index 59347168..ac89166e 100644
> --- a/src/parser_json.c
> +++ b/src/parser_json.c
> @@ -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.");
> diff --git a/src/scanner.l b/src/scanner.l
> index 45699c85..90b36615 100644
> --- a/src/scanner.l
> +++ b/src/scanner.l
> @@ -268,6 +268,7 @@ addrstring	({macaddr}|{ip4addr}|{ip6addr})
>  
>  "socket"		{ return SOCKET; }
>  "transparent"		{ return TRANSPARENT;}
> +"wildcard"		{ return WILDCARD;}

For consistency, { return WILDCARD; } (TRANSPARENT is an exception).

>  
>  "tproxy"		{ return TPROXY; }
>  
> diff --git a/src/socket.c b/src/socket.c
> index d78a163a..673e5d0f 100644
> --- a/src/socket.c
> +++ b/src/socket.c
> @@ -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,

You could also use boolean_type for this, see e.g. the meta ipsec
attribute.

-- 
Stefano




[Index of Archives]     [Netfitler Users]     [Berkeley Packet Filter]     [LARTC]     [Bugtraq]     [Yosemite Forum]

  Powered by Linux