[EMAIL PROTECTED] writes:

> So I've got a bunch of scripts that rsh to systems
> and run some tests. The only problem is the tests
> exectute and close and a new rsh is issued. The rsh
> is refused because it comes in on the same socket as
> the previous one.

Sort-of.

> I'm assuming this is for security
> purposes. 

Sort-of.

> You wouldn't want anyone piggy backing off
> your root rsh.

True, but this has nothing to do with the problem that you mention.

> Anyway, I digress. Is it possible to
> change the timeout for these sockets using some sort
> of user space command.
> 
> i.e. on solaris:
> ndd /dev/tcp \? yields:
> tcp_time_wait_interval
> 
> Changing this via ndd makes this problem go away. This
> is a closed network so security isn't an issue.

This isn't strictly security problem.  This is actually a combination
of Its a "how does the OS implement TCP?"  problem, combined with some
fundamental properties of the r(sh|cp|etc) commands.

rsh et al. don't use random-but-unique-on-the-client (called
"ephemeral") ports numbers on the client side -- rsh uses what are
called reserved ports.  It aquires these ports with rresvport().

Acquiring reserved ports requires root privileges -- you'll notice
that rsh is suid root for this purpose, just so ordinary users can use
rsh too.  Why does rsh use reserved ports?  Because rshd, the daemon
listening on the server side, will ignore requests from non-reserved
ports.  And why does rshd do this?  Because otherwise anybody could
write their own rsh and have it supply somebody elses credentials (Joe
Cracker patches together a rsh client that says "hey, I'm actually
running as John Q. Public!").  So this situation is avoided....

However, by not using ephemeral ports, rsh runs into problems with the
fundamental manner in which TCP works -- TCP's TIME_WAIT state.

So, if you invoke rsh once, you might get a given reserved ports on
the client side of the connection (for example, let's just say TCP
port #1023).  So a TCP connection between TCP port #1023 on the client
and TCP port #514 (the rshd port #) is setup.  Great.

Then you quit out of rsh.  So the TCP connection is torn down, right?
Not necessarily.  The state of the TCP connection on the server side
might (no, that's not strong enough -- how about "almost certainly
will") enter a state called the TIME_WAIT state.  The whole reason why
this state exists is to enable TCP to tear down connections reliably
and to prevent duplicated/late packets from affecting later
connections.

OK, so the state of that particular TCP connection on the server
(rshd) side is that it is in the TIME_WAIT state.

Now you come along and try to rsh to that same server again....


Here's where the "how does an OS implement a TCP stack?" question
comes in.  In a couple of different ways...

rresvport() is usually stupid.  Generally this call starts at a
constant value (1023) (grep for (IPPORT_RESERVED-1) in the Linux
kernel code) and then it works down from there (the range of reserved
ports is generally 0-1024).  rresvport() returns the first port that
it can reserve, if it can reserve one at all.

But if you call rsh a second time, rresvport() is called again, and
the likelyhood that you'll get the same reserved port that you had on
the first invocation of rsh is *very high*.

So then your TCP stack, acting on rsh's behalf, tries to contact the
rshd server on the remote machine.  So you're using the exact same TCP
port numbers that you used on your first invocation to rsh.

If the TCP stack wasn't careful, it might mistake these new packets
for packets involved with the previous invocation of rsh.  This would
be VERY BAD.

This is why the TIME_WAIT state exists -- it is a period of time in
which the network flushes out misrouted/late traffic.

So because the connection is in the TIME_WAIT state, the OS/stack on
the server side of the connection refuses the connection.  This is The
Right Thing to do.

There are generally two different ways to aleviate this problem.  The
way chosen by the BSD guys has been to play games with the TCP
sequence numbers such that a new connection to a connection in the
TIME_WAIT state is accepted *if* the sequence numbers are greater than
those used in the previous connection.  This is a *gross* hack, but it
works.  The last time I checked, the Linux folks balked at this gross
hack, and IIRC, they solved this problem by making rresvport() a
little bit smarter/more random.  But, IIRC, this is a relatively
recent kernel addition.


So, tuning your Solaris kernel with ndd to shorten the TIME_WAIT state
also aleviates the problem; however, doing this increases the
likelyhood that your TCP will accept packets that it really should
have ignored.  This probably isn't a big deal, but myself, I wouldn't
tune my kernel in this manner.  The TIME_WAIT state exists for good
reason, and there's good reason to not muck with this value.

Hope this helps,

--kevin
-- 
Kevin D. Clark ([EMAIL PROTECTED]) |
Cetacean Networks, Inc.                            |   Give me a decent UNIX
Portsmouth, N.H. (USA)                             |  and I can move the world
[EMAIL PROTECTED] (PGP Key Available)       |


**********************************************************
To unsubscribe from this list, send mail to
[EMAIL PROTECTED] with the following text in the
*body* (*not* the subject line) of the letter:
unsubscribe gnhlug
**********************************************************

Reply via email to