Re: pf: drop tcp packet when syn AND fin flags are set

2022-03-14 Thread Alexander Bluhm
On Mon, Mar 14, 2022 at 10:38:46AM +0100, Remi Locherer wrote:
> This is how OpenBSD responds with pf disabled:
> 192.168.201.21.20 > 192.168.201.29.22: SF 0:0(0) win 8192
> 192.168.201.29.22 > 192.168.201.21.20: S 2641340782:2641340782(0) ack 1 win 
> 16384  (DF)
> 
> So pf behaves kind of similar to that.

This matches what I read in tcp_input().

> But even with T/TCP or TFO, I don't a legit use of a TCP packet with
> SYN and FIN set together.

You can send a SYN, Data (e.g.  HTTP Request) and FIN (EOF) in one
packet.  Our stack does not support this and ignores Data and FIN.

> If we want to handle TFO then pf should probably inspect the TFO
> option header and coocky.

That's a different story.  For now we should stay compatible and
improve security.  I am not sure what we should do to achieve this.

> With pf disabled:
> 192.168.201.21.20 > 192.168.201.29.22: SF [tcp sum ok] 0:1000(1000) ack 0 win 
> 8192 (ttl 64, id 1, len 1040)
> 192.168.201.29.22 > 192.168.201.21.20: R [tcp sum ok] 0:0(0) win 0 (DF) (ttl 
> 64, id 55619, len 40)

A misunderstanding.  I wanted to see

192.168.201.21.20 > 192.168.201.29.22: S [tcp sum ok] 0:1000(1000) win 8192 (t
tl 64, id 1, len 1040)
192.168.201.29.22 > 192.168.201.21.20: SF [tcp sum ok] 689392523:689392523(0) a
ck 1 win 16384  (DF) (ttl 64, id 10777, len 44)

I would expect the next ACK acknowledges the FIN.

As our stack does not support this, it is a bit tricky to generate.
When sending scpay packets the stack must not interfere.  I solved
a somehow simmilar problem in src/regress/sys/net/pf_state.

> Did T/TCP specify the combination of SYN and FIN flags?

2.2  Transaction Sequences

 CLOSED   LISTEN
 #1  SYN-SENT*-->  -->   CLOSE-WAIT*
 #2  TIME-WAIT   <--  <--   LAST-ACK*

> With TFO a client can send a cookie and data together with the SYN.
> But a FIN flag? I did not find a hint for that in the RFC.

I did not find SYN+FIN in TFO RFC.  Probably they only think about
HTTP connection keep-alive.  But why not?  FIN is just end of data.
When you can send data, you can also append FIN in the same packet.

> > Or should we strip data and FIN from both SYN packets to disable
> > TFO?

Don't know.  Perhaps it is the other way around.  Without TFO SYN+FIN
looks stange.  As T/TCP is obsolete, I guess it is not allowed in
the generic initial SYN-Packet.  But SYN+ACK+FIN may be different.

> In the TCP stack or pf?

The stack can do what it supports.  pf should protect other stacks.
We are talking about normalize TCP.  There we can remove everything
that looks strange and could confuse foreign TCP stacks.  But we
should not block things that are used in the wild.  Maybe that was
the idea to strip the FIN instead of dropping the packet.

bluhm



Re: pf: drop tcp packet when syn AND fin flags are set

2022-03-14 Thread Remi Locherer
On Mon, Mar 14, 2022 at 01:27:14AM +0100, Alexander Bluhm wrote:
> On Sun, Mar 13, 2022 at 11:24:33PM +0100, Remi Locherer wrote:
> > Hi,
> > 
> > When pf processes a TCP packet with SYN and FIN flags set, it removes
> > the FIN flag and continuous processing it. I propose we change that and
> > let pf drop such a packet. I don't see any legit use for combining these
> > two flags in the same packet.
> > 
> > Henning added this comment 7 years ago:
> > XXX why clear instead of drop?
> > 
> > Damjan Dimitrov approached me with this. He got a request that his firewall
> > should drop TCP packets with SYN and FIN flags set. But with pf this can
> > currently not be done because the FIN flag is cleared before rule 
> > processing.
> > 
> > I tested the behaviour with scapy:
> > send(IP(dst="172.24.217.34")/TCP(dport=23,flags="SF"))
> > 
> > Opinions? OKs?
> 
> RFC 1644 TCP Extensions for Transactions (T/TCP) allows it
> RFC 6247 declares T/TCP historic due to security issues
> RFC 7413 TCP Fast Open (TFO) might reintroduce it
> 
> The intension of the clear FIN in pf might be to convert T/TCP into
> regular TCP.  But then the data should also be scrubbed.  Our stack
> ignores SYN+data and SYN+FIN.  I think it puts such a connection
> attempt into the syn-cache.  Of course without data and FIN to avoid
> DoS.

This is how OpenBSD responds with pf disabled:
192.168.201.21.20 > 192.168.201.29.22: SF 0:0(0) win 8192
192.168.201.29.22 > 192.168.201.21.20: S 2641340782:2641340782(0) ack 1 win 
16384  (DF)

So pf behaves kind of similar to that.

But even with T/TCP or TFO, I don't a legit use of a TCP packet with
SYN and FIN set together.

If we want to handle TFO then pf should probably inspect the TFO
option header and coocky.

> What about SYN+ACK+data+FIN ?  When we ack this, the 3-way handhake
> is complete.  I don't see why we should not allow it.  Could you
> disable pf and see if our TCP stack can handle this?

With pf disabled:
192.168.201.21.20 > 192.168.201.29.22: SF [tcp sum ok] 0:1000(1000) ack 0 win 
8192 (ttl 64, id 1, len 1040)
192.168.201.29.22 > 192.168.201.21.20: R [tcp sum ok] 0:0(0) win 0 (DF) (ttl 
64, id 55619, len 40)

The same but without initial ACK and FIN:
192.168.201.21.20 > 192.168.201.29.22: S [tcp sum ok] 0:1000(1000) win 8192 
(ttl 64, id 1, len 1040)
192.168.201.29.22 > 192.168.201.21.20: S [tcp sum ok] 689392523:689392523(0) 
ack 1 win 16384  (DF) (ttl 64, id 10777, len 44)

> 
> Maybe it should be
> 
>   /* No transactional TCP */
>   if ((flags & (TH_ACK|TH_FIN)) == TH_FIN)
>   goto tcp_drop;
> 

Did T/TCP specify the combination of SYN and FIN flags?

With TFO a client can send a cookie and data together with the SYN.
But a FIN flag? I did not find a hint for that in the RFC.

> Or should we strip data and FIN from both SYN packets to disable
> TFO?

In the TCP stack or pf? An OpenBSD router with activated pf might be used to
protect hosts with support for TFO. So pf should probably not strip data and
the TFO cookie from SYN packets. But this does not imply that the TCP stack
has to support TFO IMHO.

> > Index: pf_norm.c
> > ===
> > RCS file: /cvs/src/sys/net/pf_norm.c,v
> > retrieving revision 1.223
> > diff -u -p -r1.223 pf_norm.c
> > --- pf_norm.c   10 Mar 2021 10:21:48 -  1.223
> > +++ pf_norm.c   13 Mar 2022 15:39:42 -
> > @@ -1117,8 +1117,9 @@ pf_normalize_tcp(struct pf_pdesc *pd)
> > if (flags & TH_RST)
> > goto tcp_drop;
> >  
> > -   if (flags & TH_FIN) /* XXX why clear instead of drop? */
> > -   flags &= ~TH_FIN;
> > +   /* Illegal packet */
> > +   if (flags & TH_FIN)
> > +   goto tcp_drop;
> > } else {
> > /* Illegal packet */
> > if (!(flags & (TH_ACK|TH_RST)))
> > 
> 



Re: pf: drop tcp packet when syn AND fin flags are set

2022-03-13 Thread Alexander Bluhm
On Sun, Mar 13, 2022 at 11:24:33PM +0100, Remi Locherer wrote:
> Hi,
> 
> When pf processes a TCP packet with SYN and FIN flags set, it removes
> the FIN flag and continuous processing it. I propose we change that and
> let pf drop such a packet. I don't see any legit use for combining these
> two flags in the same packet.
> 
> Henning added this comment 7 years ago:
> XXX why clear instead of drop?
> 
> Damjan Dimitrov approached me with this. He got a request that his firewall
> should drop TCP packets with SYN and FIN flags set. But with pf this can
> currently not be done because the FIN flag is cleared before rule processing.
> 
> I tested the behaviour with scapy:
> send(IP(dst="172.24.217.34")/TCP(dport=23,flags="SF"))
> 
> Opinions? OKs?

RFC 1644 TCP Extensions for Transactions (T/TCP) allows it
RFC 6247 declares T/TCP historic due to security issues
RFC 7413 TCP Fast Open (TFO) might reintroduce it

The intension of the clear FIN in pf might be to convert T/TCP into
regular TCP.  But then the data should also be scrubbed.  Our stack
ignores SYN+data and SYN+FIN.  I think it puts such a connection
attempt into the syn-cache.  Of course without data and FIN to avoid
DoS.

What about SYN+ACK+data+FIN ?  When we ack this, the 3-way handhake
is complete.  I don't see why we should not allow it.  Could you
disable pf and see if our TCP stack can handle this?

Maybe it should be

/* No transactional TCP */
if ((flags & (TH_ACK|TH_FIN)) == TH_FIN)
goto tcp_drop;

Or should we strip data and FIN from both SYN packets to disable
TFO?

bluhm

> Index: pf_norm.c
> ===
> RCS file: /cvs/src/sys/net/pf_norm.c,v
> retrieving revision 1.223
> diff -u -p -r1.223 pf_norm.c
> --- pf_norm.c 10 Mar 2021 10:21:48 -  1.223
> +++ pf_norm.c 13 Mar 2022 15:39:42 -
> @@ -1117,8 +1117,9 @@ pf_normalize_tcp(struct pf_pdesc *pd)
>   if (flags & TH_RST)
>   goto tcp_drop;
>  
> - if (flags & TH_FIN) /* XXX why clear instead of drop? */
> - flags &= ~TH_FIN;
> + /* Illegal packet */
> + if (flags & TH_FIN)
> + goto tcp_drop;
>   } else {
>   /* Illegal packet */
>   if (!(flags & (TH_ACK|TH_RST)))
> 



pf: drop tcp packet when syn AND fin flags are set

2022-03-13 Thread Remi Locherer
Hi,

When pf processes a TCP packet with SYN and FIN flags set, it removes
the FIN flag and continuous processing it. I propose we change that and
let pf drop such a packet. I don't see any legit use for combining these
two flags in the same packet.

Henning added this comment 7 years ago:
XXX why clear instead of drop?

Damjan Dimitrov approached me with this. He got a request that his firewall
should drop TCP packets with SYN and FIN flags set. But with pf this can
currently not be done because the FIN flag is cleared before rule processing.

I tested the behaviour with scapy:
send(IP(dst="172.24.217.34")/TCP(dport=23,flags="SF"))

Opinions? OKs?

Remi


Index: pf_norm.c
===
RCS file: /cvs/src/sys/net/pf_norm.c,v
retrieving revision 1.223
diff -u -p -r1.223 pf_norm.c
--- pf_norm.c   10 Mar 2021 10:21:48 -  1.223
+++ pf_norm.c   13 Mar 2022 15:39:42 -
@@ -1117,8 +1117,9 @@ pf_normalize_tcp(struct pf_pdesc *pd)
if (flags & TH_RST)
goto tcp_drop;
 
-   if (flags & TH_FIN) /* XXX why clear instead of drop? */
-   flags &= ~TH_FIN;
+   /* Illegal packet */
+   if (flags & TH_FIN)
+   goto tcp_drop;
} else {
/* Illegal packet */
if (!(flags & (TH_ACK|TH_RST)))