Re: conntrack: confirm existing but do not create new entries

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

 



On 19/08/2021 11:09, Florian Westphal wrote:
> Eugene Crosser <crosser@xxxxxxxxxxx> wrote:
>> On 18/08/2021 18:13, Florian Westphal wrote:
>>> Eugene Crosser <crosser@xxxxxxxxxxx> wrote:
>>>> My use case is to set up a stateful firewall allowing any outgoing connection
>>>> from a host, and restricting incoming, which obviously requires conntracking.
>>>> The twist is that there exists a rather high probability of DoS-like incoming
>>>> traffic, that easily overflows conntrack table with unconfirmed entries, even
>>>> though their lifetime is very short.
>>>
>>> Create a rule that drops NEW packets in prerouting hook. For iptables,
>>> mangle will work (raw is too early).  For nftables, youl need to choose
>>> a hook prioriy of -199 or higher (-198, ... to anything below 2**31).
>>>
>>> Such packets will create a new connection entry, but because packet gets
>>> dropped before confirmation the entry will not be committed to the table.
>>
>> Unfortunately this approach does not work for my case.
>> I cannot drop packets before I know that they are going to the INPUT path.
>> The point of the exercise is to route transit traffic without conntracking it
>> (because tracking will overflow the table), but conntrack traffic to/from the
>> host itself.
> 
> Confirmation  (== commit of NEW to contnrack table) occurs at end of INPUT
> (incoming case) or POSTROUTING (for locally originating and forwarded traffic)
> 
>> Maybe I'd be able to determine which traffic is transit on prerouting stage (by
>> IP addresses or interfaces) and set "notrack" selectively...
> 
> You might have to clarify what you are looking for.

Yes, I oversimplified our case and omitted the part that turned to be important.
This is a host for multiple VMs. We want VM traffic to go through unfiltered and
_untracked_ because tracking _this_ traffic overflows the table.

Traffic to the host itself (management and configuration) needs to be filtered,
and to do it effectively we need stateful firewall, hence it should be tracked.
Flooding of the table by traffic that ends up in the INPUT path is not really a
concern, and we would drop bad traffic anyway, preventing ct entries from being
committed (as far as I understood your explanation).

So the problem, as far as I understand it, is that decision to track or not
track has to be taken _before_ the decision between FORWARD and INPUT. We want
FORWARD to go (ahem) forward without modifying the table, and INPUT to be
processed against the table to be able to decide if it belongs to an existing
outgoing connection.

That _could_ be achieved if the "track/notrack" switch had a third position:
"try to track, but if there was no existing entry, pretend that it's notrack".

> And you don't want to track forwarded traffic (but still want to track
> locally originating traffic).
> 
> Only choice in that case is to NOTRACK in raw/PREROUTING based on incoming
> interface.

Yeah, I guess we'd have to settle on something like that (or based on the
destination IP address being "in our management network" maybe). That's be more
fragile w.r.t. possible future changes of interfaces / addresses.

>> Yet I am surprised that a flag meaning "conntrack, but only to confirm exiting
>> entries" does not exist. Would not it be useful to have?..
> 
> How would that even work?
>
> To know if a given packet is a reply there needs to be a record in the
> state table.

I was guessing this piece of code

=====
        /* look for tuple match */
        zone = nf_ct_zone_tmpl(tmpl, skb, &tmp);
        hash = hash_conntrack_raw(&tuple, state->net);
        h = __nf_conntrack_find_get(state->net, zone, &tuple, hash);
        if (!h) {
                h = init_conntrack(state->net, tmpl, &tuple,
                                   skb, dataoff, hash);
                if (!h)
                        return 0;
                if (IS_ERR(h))
                        return PTR_ERR(h);
        }
        ct = nf_ct_tuplehash_to_ctrack(h);
=====

could _not_ call `init_conntrack()` depending on the (hypothetical) "track only
when entry exists" flag, and return early otherwise?.. But my understanding of
the workings of netfilter is really poor, it is very likely that I am missing
something crucial.

> If you are only looking for 'remote' vs 'locally generated' traffic, you might
> want to have a look at the socket match, which could be used to detect
> if an incoming packet would match a local socket.
> 
> There is also the 'addrtype' match, which could be used to detect
> (at prerouting) if the routing table says that the daddr is local (or not).
> 
> But depending on wheter you are using NAT this might not work.

Oh, this is a very good hint! I'll need to check if that can be used for our
case. We need NAT, but in the paths between specific interfaces, where we can
enable conntrack separately. So it might work!

While I am here, may I ask: is there a "correct" way to re-enable conntrack that
was disabled in someone else's chain that happened to run before mine?

Thanks once again,

Eugene

Attachment: OpenPGP_signature
Description: OpenPGP digital signature


[Index of Archives]     [Linux Netfilter Development]     [Linux Kernel Networking Development]     [Netem]     [Berkeley Packet Filter]     [Linux Kernel Development]     [Advanced Routing & Traffice Control]     [Bugtraq]

  Powered by Linux