Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 08 Jul 2019 18:22:38 +0300
From:      Paul <devgs@ukr.net>
To:        Michael Tuexen <tuexen@freebsd.org>
Cc:        freebsd-net@freebsd.org
Subject:   Re[2]: Issues with TCP Timestamps allocation
Message-ID:  <1562599181.734953000.1l9a1d23@frv39.fwdcdn.com>
In-Reply-To: <DF65CA7F-B5FC-499D-B053-0531596D230C@freebsd.org>
References:  <1562579483.67527000.24rw4xi5@frv39.fwdcdn.com> <32FD061B-245C-41D2-81DE-1B4756A7173D@freebsd.org> <1562591379.369129000.gpmxvurq@frv39.fwdcdn.com> <DF65CA7F-B5FC-499D-B053-0531596D230C@freebsd.org>

next in thread | previous in thread | raw e-mail | index | archive | help


8 July 2019, 17:12:21, by "Michael Tuexen" <tuexen@freebsd.org>:

> > On 8. Jul 2019, at 15:24, Paul <devgs@ukr.net> wrote:
> > 
> > Hi Michael,
> > 
> > 8 July 2019, 15:53:15, by "Michael Tuexen" <tuexen@freebsd.org>:
> > 
> >>> On 8. Jul 2019, at 12:37, Paul <devgs@ukr.net> wrote:
> >>> 
> >>> Hi team,
> >>> 
> >>> Recently we had an upgrade to 12 Stable. Immediately after, we have started 
> >>> seeing some strange connection establishment timeouts to some fixed number
> >>> of external (world) hosts. The issue was persistent and easy to reproduce.
> >>> Thanks to a patience and dedication of our system engineer we have tracked  
> >>> this issue down to a specific commit:
> >>> 
> >>> https://svnweb.freebsd.org/base?view=revision&revision=338053
> >>> 
> >>> This patch was also back-ported into 11 Stable:
> >>> 
> >>> https://svnweb.freebsd.org/base?view=revision&revision=348435
> >>> 
> >>> Among other things this patch changes the timestamp allocation strategy,
> >>> by introducing a deterministic randomness via a hash function that takes
> >>> into account a random key as well as source address, source port, dest
> >>> address and dest port. As the result, timestamp offsets of different
> >>> tuples (SA,SP,DA,DP) will be wildly different and will jump from small 
> >>> to large numbers and back, as long as something in the tuple changes.
> >> Hi Paul,
> >> 
> >> this is correct.
> >> 
> >> Please note that the same happens with the old method, if two hosts with
> >> different uptimes are bind a consumer grade NAT.
> > 
> > If NAT does not replace timestamps then yes, it should be the case.
> > 
> >>> 
> >>> After performing various tests of hosts that produce the above mentioned 
> >>> issue we came to conclusion that there are some interesting implementations 
> >>> that drop SYN packets with timestamps smaller  than the largest timestamp 
> >>> value from streams of all recent or current connections from a specific 
> >>> address. This looks as some kind of SYN flood protection.
> >> This also breaks multiple hosts with different uptimes behind a consumer
> >> level NAT talking to such a server.
> >>> 
> >>> To ensure that each external host is not going to see a wild jumps of 
> >>> timestamp values I propose a patch that removes ports from the equation
> >>> all together, when calculating the timestamp offset:
> >>> 
> >>> Index: sys/netinet/tcp_subr.c
> >>> ===================================================================
> >>> --- sys/netinet/tcp_subr.c	(revision 348435)
> >>> +++ sys/netinet/tcp_subr.c	(working copy)
> >>> @@ -2224,7 +2224,22 @@
> >>> uint32_t
> >>> tcp_new_ts_offset(struct in_conninfo *inc)
> >>> {
> >>> -	return (tcp_keyed_hash(inc, V_ts_offset_secret));
> >>> +        /* 
> >>> +         * Some implementations show a strange behaviour when a wildly random 
> >>> +         * timestamps allocated for different streams. It seems that only the
> >>> +         * SYN packets are affected. Observed implementations drop SYN packets
> >>> +         * with timestamps smaller than the largest timestamp value of all 
> >>> +         * recent or current connections from specific a address. To mitigate 
> >>> +         * this we are going to ensure that each host will always observe 
> >>> +         * timestamps as increasing no matter the stream: by dropping ports
> >>> +         * from the equation.
> >>> +         */ 
> >>> +        struct in_conninfo inc_copy = *inc;
> >>> +
> >>> +        inc_copy.inc_fport = 0;
> >>> +        inc_copy.inc_lport = 0;
> >>> +
> >>> +	return (tcp_keyed_hash(&inc_copy, V_ts_offset_secret));
> >>> }
> >>> 
> >>> /*
> >>> 
> >>> In any case, the solution of the uptime leak, implemented in rev338053 is 
> >>> not going to suffer, because a supposed attacker is currently able to use 
> >>> any fixed values of SP and DP, albeit not 0, anyway, to remove them out 
> >>> of the equation.
> >> Can you describe how a peer can compute the uptime from two observed timestamps?
> >> I don't see how you can do that...
> > 
> > Supposed attacker could run a script that continuously monitors timestamps,
> > for example via a periodic TCP connection from a fixed local port (eg 12345) 
> > and a fixed local address to the fixed victim's address and port (eg 80).
> > Whenever large discrepancy is observed, attacker can assume that reboot has 
> > happened (due to V_ts_offset_secret re-generation), hence the received 
> > timestamp is considered an approximate point of reboot from which the uptime
> > can be calculated, until the next reboot and so on.
> Ahh, I see. The patch we are talking about is not intended to protect against
> continuous monitoring, which is something you can always do. You could even
> watch for service availability and detect reboots. A change of the local key
> would also look similar to a reboot without a temporary loss of connectivity.
> 
> Thanks for the clarification.
> > 
> >>> 
> >>> There is the list of example hosts that we were able to reproduce the 
> >>> issue with:
> >>> 
> >>> curl -v http://88.99.60.171:80
> >>> curl -v http://163.172.71.252:80
> >>> curl -v http://5.9.242.150:80
> >>> curl -v https://185.134.205.105:443
> >>> curl -v https://136.243.1.231:443
> >>> curl -v https://144.76.196.4:443
> >>> curl -v http://94.127.191.194:80
> >>> 
> >>> To reproduce, call curl repeatedly with a same URL some number of times. 
> >>> You are going  to see some of the requests stuck in 
> >>> `*    Trying XXX.XXX.XXX.XXX...`
> >>> 
> >>> For some reason, the easiest way to reproduce the issue is with nc:
> >>> 
> >>> $ echo "foooooo" | nc -v 88.99.60.171 80
> >>> 
> >>> Only a few such calls are required until one of them is stuck on connect():
> >>> issuing SYN packets with an exponential backoff.
> >> Thanks for providing an end-point to test with. I'll take a look.
> >> Just to be clear: You are running a FreeBSD client against one of the above
> >> servers and experience the problem with the new timestamp computations.
> >> 
> >> You are not running arbitrary clients against a FreeBSD server...
> > 
> > We are talking about FreeBSD being the client. Peers that yield this unwanted
> > behaviour are unknown. Little bit of tinkering showed that some of them run 
> > Debian:
> > 
> > telnet 88.99.60.171 22
> > Trying 88.99.60.171...
> > Connected to 88.99.60.171.
> > Escape character is '^]'.
> > SSH-2.0-OpenSSH_6.7p1 Debian-5+deb8u3
> Also some are hosted by Hetzner, but not all. I'll will look into
> this tomorrow, since I'm on a deadline today (well it is 2am tomorrow
> morning, to be precise)...

Thanks a lot, I would appreciate that.

> 
> Best regards
> Michael 
> > 
> > 
> >> 
> >> Best regards
> >> Michael
> >> 
> >> 
> 
> 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?1562599181.734953000.1l9a1d23>