All of lore.kernel.org
 help / color / mirror / Atom feed
* nftables: origin sport after dstnat
@ 2022-12-06 22:03 Aaron Fischer
  2022-12-07 11:29 ` Florian Westphal
  0 siblings, 1 reply; 4+ messages in thread
From: Aaron Fischer @ 2022-12-06 22:03 UTC (permalink / raw)
  To: netfilter

[-- Attachment #1: Type: text/plain, Size: 2572 bytes --]

Hi!

I want to use nftables along with Docker. Docker itself does not
support nftables, so I use the nf_tables backend for iptables. This
way, Docker uses iptables commands to setup all needed chains and
rules. So far so good.

The following chains will be setup by Docker (I shorten it for the
relevant information):

table ip filter {
	chain FORWARD {
		type filter hook forward priority filter; policy drop;
		counter packets 6 bytes 360 jump DOCKER-USER
	}
	chain DOCKER {
		iifname != "docker0" oifname "docker0" ip daddr 172.17.0.2 tcp dport 5000 counter packets 0 bytes 0 accept
	}
	chain DOCKER-USER {
	}
}
table ip nat {
	chain DOCKER {
		iifname "docker0" counter packets 0 bytes 0 return
		iifname != "docker0" tcp dport 8448 counter packets 6 bytes 360 # xt_DNAT
	}
	chain PREROUTING {
		type nat hook prerouting priority dstnat; policy accept;
		# xt_addrtype counter packets 6 bytes 360 jump DOCKER
	}
}

Here I started a Docker container with "-p 8448:5000" (map the host
port 8448 to the docker internal port 5000). If a package enters, it
will land in the PREROUTING NAT chain (dstnat), jump to the DOCKER
chain and here the dnat happen. This is all set up from the Docker
daemon itself. The only way for me to intercept traffic is the
DOCKER-USER chain (FORWARD FILTER), which will be created by Docker
and will be put on top of all other rules in this chain.

Now I want to stablish a whitelist for host ports. Meaning: I want
to control which ports are "open" from the outside, regardless what
Docker is doing.

My first idea was to use the DOCKER-USER chain and add a simple rule
which will drop all traffic which is not coming from the whitelisted
port list:

tcp sport != {
  8448,
} drop

The problem is that the DOCKER-USER chain is behind the dnat, so I
can't use "sport", because it is already a random port from the dnat :(

With a trace in that chain, I got this (sport is 57484, a random port)
and the filter rule does not work.

trace id 2a3fb2fd ip filter DOCKER-USER packet: iif "eth0" oif "docker0" ether saddr 52:54:00:8e:37:c7 ether daddr 52:54:00:9c:e5:b7 ip saddr 192.168.122.1 ip daddr 172.17.0.2 ip dscp cs0 ip ecn not-ect ip ttl 63 ip id 57921 ip length 60 tcp sport 57484 tcp dport 5000 tcp flags == syn tcp window 64240 
trace id 2a3fb2fd ip filter DOCKER-USER rule tcp sport != 8448
counter packets 6 bytes 360 drop (verdict drop)

Is there a way to somehow access the origin sport (8448 in my case), so
I can filter for it in the FORWARD chain?

Thanks!
Aaron

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: nftables: origin sport after dstnat
  2022-12-06 22:03 nftables: origin sport after dstnat Aaron Fischer
@ 2022-12-07 11:29 ` Florian Westphal
  2022-12-07 23:31   ` Aaron Fischer
  0 siblings, 1 reply; 4+ messages in thread
From: Florian Westphal @ 2022-12-07 11:29 UTC (permalink / raw)
  To: Aaron Fischer; +Cc: netfilter

Aaron Fischer <mail@aaron-fischer.net> wrote:
> The problem is that the DOCKER-USER chain is behind the dnat, so I
> can't use "sport", because it is already a random port from the dnat :(
> 
> With a trace in that chain, I got this (sport is 57484, a random port)
> and the filter rule does not work.
> 
> trace id 2a3fb2fd ip filter DOCKER-USER packet: iif "eth0" oif "docker0" ether saddr 52:54:00:8e:37:c7 ether daddr 52:54:00:9c:e5:b7 ip saddr 192.168.122.1 ip daddr 172.17.0.2 ip dscp cs0 ip ecn not-ect ip ttl 63 ip id 57921 ip length 60 tcp sport 57484 tcp dport 5000 tcp flags == syn tcp window 64240 
> trace id 2a3fb2fd ip filter DOCKER-USER rule tcp sport != 8448
> counter packets 6 bytes 360 drop (verdict drop)
> 
> Is there a way to somehow access the origin sport (8448 in my case), so
> I can filter for it in the FORWARD chain?

Yes, the original addresses are stored in conntrack: 'ct original proto-src 8448'

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: nftables: origin sport after dstnat
  2022-12-07 11:29 ` Florian Westphal
@ 2022-12-07 23:31   ` Aaron Fischer
  2022-12-08  7:48     ` Florian Westphal
  0 siblings, 1 reply; 4+ messages in thread
From: Aaron Fischer @ 2022-12-07 23:31 UTC (permalink / raw)
  To: netfilter

[-- Attachment #1: Type: text/plain, Size: 1251 bytes --]

On Wed, 7 Dec 2022 12:29:00 +0100 Florian Westphal <fw@strlen.de> wrote:
> Aaron Fischer <mail@aaron-fischer.net> wrote:
> > Is there a way to somehow access the origin sport (8448 in my
> > case), so I can filter for it in the FORWARD chain?  
> 
> Yes, the original addresses are stored in conntrack: 'ct original
> proto-src 8448'

Thank you for this valuable hint! I've tested it with this bare minimum
config:

alpine-test:/etc# cat nft-ct.nft 
#!/usr/sbin/nft -f

flush ruleset

table ip filter {
    chain INPUT {
        type filter hook input priority filter
        policy accept
    }

    chain FORWARD {
        type filter hook forward priority filter
        policy drop
        ct original proto-src 8448 accept
    }
}

But the config seems invalid:

alpine-test:/etc# nft -c -f /etc/nft-ct.nft 
/etc/nft-ct.nft:14:31-34: Error: Can't parse symbolic invalid
expressions ct original proto-src 8448 accept
                                  ^^^^

Not sure why. Various examples and the man page also show it that way
you mentioned. The sourcecode gives me not much more insight how the
syntax should be. Why is 8448 an "invalid" type?

I use the latest version of the nft tool (v1.0.5).

Aaron

[-- Attachment #2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 833 bytes --]

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: nftables: origin sport after dstnat
  2022-12-07 23:31   ` Aaron Fischer
@ 2022-12-08  7:48     ` Florian Westphal
  0 siblings, 0 replies; 4+ messages in thread
From: Florian Westphal @ 2022-12-08  7:48 UTC (permalink / raw)
  To: Aaron Fischer; +Cc: netfilter

Aaron Fischer <mail@aaron-fischer.net> wrote:
>     chain FORWARD {
>         type filter hook forward priority filter
>         policy drop
>         ct original proto-src 8448 accept

You need to prepend the l4 protocol that needs to be matched.

meta l4proto tcp ct original proto-src 8448 accept

> Why is 8448 an "invalid" type?

Because nft can't infer it from the available info.

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2022-12-08  7:48 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-12-06 22:03 nftables: origin sport after dstnat Aaron Fischer
2022-12-07 11:29 ` Florian Westphal
2022-12-07 23:31   ` Aaron Fischer
2022-12-08  7:48     ` Florian Westphal

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.