* conntrack: confirm existing but do not create new entries @ 2021-08-18 15:53 Eugene Crosser 2021-08-18 16:13 ` Florian Westphal 0 siblings, 1 reply; 9+ messages in thread From: Eugene Crosser @ 2021-08-18 15:53 UTC (permalink / raw) To: netfilter [-- Attachment #1.1: Type: text/plain, Size: 1091 bytes --] Hello, 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. I was hoping to keep conntracking enabled in the outgoing/raw hook, but in the prerouting/raw hook disable conntracking _unless_ an entry (previously created by an outgoing packet) already exists. In other words, *make incoming packets update existing entries but never create new entries*. Looking at the code in resolve_normal_ct(), apparently there is no any special flag or anything for that. But maybe it is possible to have a rule in the prerouting/raw chain that would conditionally set `notrack` flag depending on a lookup in the conntrack table? Or maybe there are other suggestions how to achieve the goal (of not letting "unexpected" incoming packets fill conntrack table)? Thank you, Eugene [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: conntrack: confirm existing but do not create new entries 2021-08-18 15:53 conntrack: confirm existing but do not create new entries Eugene Crosser @ 2021-08-18 16:13 ` Florian Westphal 2021-08-18 16:20 ` Eugene Crosser 2021-08-19 7:44 ` Eugene Crosser 0 siblings, 2 replies; 9+ messages in thread From: Florian Westphal @ 2021-08-18 16:13 UTC (permalink / raw) To: Eugene Crosser; +Cc: netfilter Eugene Crosser <crosser@average.org> 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. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: conntrack: confirm existing but do not create new entries 2021-08-18 16:13 ` Florian Westphal @ 2021-08-18 16:20 ` Eugene Crosser 2021-08-19 7:44 ` Eugene Crosser 1 sibling, 0 replies; 9+ messages in thread From: Eugene Crosser @ 2021-08-18 16:20 UTC (permalink / raw) To: Florian Westphal; +Cc: netfilter [-- Attachment #1.1: Type: text/plain, Size: 915 bytes --] On 18/08/2021 18:13, Florian Westphal wrote: > Eugene Crosser <crosser@average.org> 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. Oh, cool trick! I will try that, thank you very much! Eugene [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: conntrack: confirm existing but do not create new entries 2021-08-18 16:13 ` Florian Westphal 2021-08-18 16:20 ` Eugene Crosser @ 2021-08-19 7:44 ` Eugene Crosser 2021-08-19 9:09 ` Florian Westphal 1 sibling, 1 reply; 9+ messages in thread From: Eugene Crosser @ 2021-08-19 7:44 UTC (permalink / raw) To: Florian Westphal; +Cc: netfilter [-- Attachment #1.1: Type: text/plain, Size: 1479 bytes --] On 18/08/2021 18:13, Florian Westphal wrote: > Eugene Crosser <crosser@average.org> 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. Maybe I'd be able to determine which traffic is transit on prerouting stage (by IP addresses or interfaces) and set "notrack" selectively... 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?.. Thanks again in any case! Eugene [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: conntrack: confirm existing but do not create new entries 2021-08-19 7:44 ` Eugene Crosser @ 2021-08-19 9:09 ` Florian Westphal 2021-08-19 13:47 ` Eugene Crosser 0 siblings, 1 reply; 9+ messages in thread From: Florian Westphal @ 2021-08-19 9:09 UTC (permalink / raw) To: Eugene Crosser; +Cc: Florian Westphal, netfilter Eugene Crosser <crosser@average.org> wrote: > On 18/08/2021 18:13, Florian Westphal wrote: > > Eugene Crosser <crosser@average.org> 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. From your original post i concluded its this: <Your_Host> ----> <internet> ... and no forwarding at all. Requirement is to prevent NEW entries when traffic is incoming (but not a reply). With above, its really this: <some_network> <---> <Your_Host> <---> <internet> 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. If you are concerned about flood from <internet> -> <Your_Host> .. then you can drop traffic coming from public interface in INPUT if its NEW. (assuming you still track packets coming in via the 'public' interface, else that won't work). > 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. 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. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: conntrack: confirm existing but do not create new entries 2021-08-19 9:09 ` Florian Westphal @ 2021-08-19 13:47 ` Eugene Crosser 2021-08-19 14:18 ` Florian Westphal 0 siblings, 1 reply; 9+ messages in thread From: Eugene Crosser @ 2021-08-19 13:47 UTC (permalink / raw) To: Florian Westphal; +Cc: netfilter [-- Attachment #1.1: Type: text/plain, Size: 5161 bytes --] On 19/08/2021 11:09, Florian Westphal wrote: > Eugene Crosser <crosser@average.org> wrote: >> On 18/08/2021 18:13, Florian Westphal wrote: >>> Eugene Crosser <crosser@average.org> 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 #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: conntrack: confirm existing but do not create new entries 2021-08-19 13:47 ` Eugene Crosser @ 2021-08-19 14:18 ` Florian Westphal 2021-08-23 13:31 ` Eugene Crosser 0 siblings, 1 reply; 9+ messages in thread From: Florian Westphal @ 2021-08-19 14:18 UTC (permalink / raw) To: Eugene Crosser; +Cc: Florian Westphal, netfilter Eugene Crosser <crosser@average.org> wrote: > On 19/08/2021 11:09, Florian Westphal wrote: > > 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. Yes, conntrack hooks at prerouting and output, so by the the input or forward are reached the conntrack lookup was already done. Hence, NOTRACK has to be decided before conntrack lookup/create. > >> 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. I don't see how it can work, something does need to create entries, else __nf_conntrack_find_get() never finds an entry, so init_conntrack() is never called, so table is always empty. > 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? You mean, 'cancelling' earlier NOTRACK rule? I'm not aware of such a feature. ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: conntrack: confirm existing but do not create new entries 2021-08-19 14:18 ` Florian Westphal @ 2021-08-23 13:31 ` Eugene Crosser 2021-08-23 13:57 ` Mathew Heard 0 siblings, 1 reply; 9+ messages in thread From: Eugene Crosser @ 2021-08-23 13:31 UTC (permalink / raw) To: Florian Westphal; +Cc: netfilter [-- Attachment #1.1: Type: text/plain, Size: 2935 bytes --] On 19/08/2021 16:18, Florian Westphal wrote: > Eugene Crosser <crosser@average.org> wrote: ... >>>> 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. > > I don't see how it can work, something does need to create entries, else > __nf_conntrack_find_get() never finds an entry, so init_conntrack() is > never called, so table is always empty. I was (probably incorrectly?) assuming that __nf_conntrack_find_get() looks up in the "main" table, so there will be entries created by previous packets that went "in the opposite direction" and did not have the "track only when entry exists" flag. In my case, packets that have traversed the OUTPUT chain. By the way, another way to implement such feature would be a settable flag in the skb "do not commit to the main conntrack table"?.. I need to check how "fib daddr type local" will work in the presence of VRFs that may be forwarding the same addresses that in the default VRF are going to INPUT. Basing decision on the input interface is kind of undesirable for us, because there are so many, and some may be named differently on different hardware. >> 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? > > You mean, 'cancelling' earlier NOTRACK rule? I'm not aware of such a > feature. That's what I thought. That means that different entities that need to control `notrack` cannot pile up "exceptions on top of exceptions" and have to cooperate very stringently. If I want to have a chain that ends with unconditional catch-all "notrack", then everyone who needs to enable tracking for a specific class of traffic must have rules in the same chain. But we can work with that. Eugene [-- Attachment #2: OpenPGP digital signature --] [-- Type: application/pgp-signature, Size: 488 bytes --] ^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: conntrack: confirm existing but do not create new entries 2021-08-23 13:31 ` Eugene Crosser @ 2021-08-23 13:57 ` Mathew Heard 0 siblings, 0 replies; 9+ messages in thread From: Mathew Heard @ 2021-08-23 13:57 UTC (permalink / raw) To: netfilter Perhaps see https://github.com/X4BNet/xt_NOCREATE On Mon, 23 Aug 2021 at 23:31, Eugene Crosser <crosser@average.org> wrote: > > On 19/08/2021 16:18, Florian Westphal wrote: > > Eugene Crosser <crosser@average.org> wrote: > ... > >>>> 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. > > > > I don't see how it can work, something does need to create entries, else > > __nf_conntrack_find_get() never finds an entry, so init_conntrack() is > > never called, so table is always empty. > > I was (probably incorrectly?) assuming that __nf_conntrack_find_get() looks up > in the "main" table, so there will be entries created by previous packets that > went "in the opposite direction" and did not have the "track only when entry > exists" flag. In my case, packets that have traversed the OUTPUT chain. > > By the way, another way to implement such feature would be a settable flag in > the skb "do not commit to the main conntrack table"?.. > > I need to check how "fib daddr type local" will work in the presence of VRFs > that may be forwarding the same addresses that in the default VRF are going to > INPUT. Basing decision on the input interface is kind of undesirable for us, > because there are so many, and some may be named differently on different hardware. > > >> 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? > > > > You mean, 'cancelling' earlier NOTRACK rule? I'm not aware of such a > > feature. > > That's what I thought. That means that different entities that need to control > `notrack` cannot pile up "exceptions on top of exceptions" and have to cooperate > very stringently. If I want to have a chain that ends with unconditional > catch-all "notrack", then everyone who needs to enable tracking for a specific > class of traffic must have rules in the same chain. But we can work with that. > > Eugene > ^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2021-08-23 13:57 UTC | newest] Thread overview: 9+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2021-08-18 15:53 conntrack: confirm existing but do not create new entries Eugene Crosser 2021-08-18 16:13 ` Florian Westphal 2021-08-18 16:20 ` Eugene Crosser 2021-08-19 7:44 ` Eugene Crosser 2021-08-19 9:09 ` Florian Westphal 2021-08-19 13:47 ` Eugene Crosser 2021-08-19 14:18 ` Florian Westphal 2021-08-23 13:31 ` Eugene Crosser 2021-08-23 13:57 ` Mathew Heard
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.