[980] in linux-net channel archive
Re: Rejecting tcp connections before accept()
daemon@ATHENA.MIT.EDU (Nick Simicich)
Thu Aug 24 02:27:44 1995
Date: Wed, 23 Aug 1995 09:28:49 -29900
From: Nick Simicich <njs@scifi.maid.com>
To: "Stephen R. van den Berg" <srb@cuci.nl>
cc: linux-net@vger.rutgers.edu
In-Reply-To: <199508220826.KAA05602@hera.cuci.nl>
On Tue, 22 Aug 1995, Stephen R. van den Berg wrote:
The point here is that we want to allow people who we want to accept
connections from to to see that we are listening on a port, while not
giving any indication to people we don't want to connect to that we are
listening at all.
Why is this good? If you can avoid sending a syn-ack to a syn before
vetting the origin address, you can avoid sequence number attacks.
Sequence number attacks require that you do a couple of successful opens
(from an untrusted host) to a port you can reach before you send the
packets with the forged origin address and the guessed sequence numbers.
It doesn't matter if the port is closed immediately.
An additional benefit is that someone who is untrusted can't map your
host.
Now the whole purpose of this is to write an amazingly secure inetd that
would be the front end to every TCP based service on your machine. If
anything else does a traditional insecure listen, you are compromised.
netstat and /proc/net/tcp should indicate that this socket is waiting in
this state rather than a normal listen state, of course.
> Mike Shaver <shaver@neon.ingenia.com> wrote:
> >Or you could add a hear() system call that would return a struct
> >something *, which could be checked for stuff like source and
> >destination address and port before calling accept()...
>
> Not necessary. Simply give getpeername() the ability to operate
> on the socket you are listening on. It should then return the
> address of the next connection that is to be accepted.
> But you still need an ioctl() of sorts to throw away the connection
> is you don't want it.
Classically, the user issues a socket(), bind(), listen(), and then waits
in an accept(). Accept() is the blocking call that you get the socket
from and that you fork() after.
Also, classically, I think that a certain amount of processing happens at
the point of the accept - the three part handshake happens before the
socket is returned. This path could be left unchanged.
If someone is listening on more than one port (inetd, say) you a
select() on a bunch of sockets that have a listen()s the classic
indication is that you can do an accept and that it will not block.
Therefore the three part handshake has to be completed and we have to be
ready to accept() and have it return a socket() without delay before
select() completes.
Changes in these behaviours (some versions of WinSock, for example)
remarkably change how you have to write programs so that they won't block.
These semantics are important, and we can't change them for existing
programs.
I think we need a socket option that changes these behaviours so that
classic programs continue to work, but a new program can be written that
does socket(), bind(), listen(), setsockopt(s,delay_synack), select(),
getpeername(), and then either the ioctl(s) which triggers the RST packet
(reject()) (which simulates the 'no one is listening' behaviour), or the
accept(), which then blocks until the three part handshake is completed,
and returns a socket (or times out).
A disadvantage of this is that you can be flooded with forged syns and
send syn-acks whereas you might never have seen these before. This may
also be an advantage as a bunch of opens failing after syn may indicate
that you are under a sequence number attack.
Or maybe it returns a partially open port and sends the SYN-ACK and delays
for the rest of the three part handshake before the next I/O operation so
that you can do the fork and loop back to the select in the server.
> --
> Sincerely, srb@cuci.nl
> Stephen R. van den Berg (AKA BuGless).
>
> In this signature, the concluding three words `were left out'.
>
Nick Simicich - njs@scifi.emi.net - (last choice) njs@bcrvm1.vnet.ibm.com
http://scifi.emi.net/njs.html -- Stop by and Light Up The World!