[980] in linux-net channel archive

home help back first fref pref prev next nref lref last post

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!


home help back first fref pref prev next nref lref last post