[Bug 1054] Nmap Causing SSH Session to Prematurely End
bugzilla-daemon at mindrot.org
bugzilla-daemon at mindrot.org
Fri Jun 10 00:59:05 EST 2005
http://bugzilla.mindrot.org/show_bug.cgi?id=1054
Summary: Nmap Causing SSH Session to Prematurely End
Product: Portable OpenSSH
Version: 3.8.1p1
Platform: All
OS/Version: Mac OS X
Status: NEW
Severity: normal
Priority: P2
Component: ssh
AssignedTo: bitbucket at mindrot.org
ReportedBy: patrick.osullivan at rutgers.edu
comp.security.ssh posting and reply from Richard Silverman below:
While trying to troubleshoot a seperate problem, I came across a strange,
repeatable behavior that I haven't been able to find any further information on.
In short, I'm establishing a simple port forward from 'terrapin' to
192.168.1.120 via 'osgiliath,' another host on 192.168.1.0/24. An Nmap of the
port I'm forwarding on the local machine causes the SSH session to end. To
establish the connection, I issue the following command:
--
terrapin:~ irish$ ssh -vvv -L 3389:192.168.1.120:3389 irish at osgiliath.foo.com
--
Since I maxed verbosity, there's quite a lot of logging but at some point it
logs in. The weirdness comes in when I then nmap localhost (originally a full
sweep but just the single port is shown below).
--
terrapin:~ irish$ nmap -sT -p 3389 localhost
Starting nmap V. 3.00 ( www.insecure.org/nmap/ )
Interesting ports on localhost (127.0.0.1):
Port State Service
3389/tcp open ms-term-serv
Nmap run completed -- 1 IP address (1 host up) scanned in 0 seconds
--
In the process of that, the following happens in the original SSH session:
--
irish at osgiliath:~$ exitdebug1: Connection to port 3389 forwarding to
192.168.1.120 port 3389 requested.
debug2: fd 9 setting TCP_NODELAY
debug2: fd 9 is O_NONBLOCK
debug2: fd 9 is O_NONBLOCK
debug1: channel 3: new [direct-tcpip]
debug2: channel 3: open confirm rwindow 131072 rmax 32768
debug2: channel 3: read<=0 rfd 9 len -1
debug2: channel 3: read failed
debug2: channel 3: close_read
debug2: channel 3: input open -> drain
debug2: channel 3: ibuf empty
debug2: channel 3: send eof
debug2: channel 3: input drain -> closed
debug2: channel 3: rcvd eof
debug2: channel 3: output open -> drain
debug2: channel 3: obuf empty
debug2: channel 3: close_write
debug2: channel 3: chan_shutdown_write: shutdown() failed for fd9: Invalid argument
debug2: channel 3: output drain -> closed
debug2: channel 3: rcvd close
debug3: channel 3: will not send data after close
debug2: channel 3: send close
debug2: channel 3: is dead
debug2: channel 3: garbage collecting
debug1: channel 3: free: direct-tcpip: listening port 3389 for 192.168.1.120
port 3389, connect from 127.0.0.1 port 65397, nchannels 4
debug3: channel 3: status: The following connections are open:
#2 client-session (t4 r0 i0/0 o0/0 fd 6/7)
#3 direct-tcpip: listening port 3389 for 192.168.1.120 port 3389, connect from
127.0.0.1 port 65397 (t4 r1 i3/0 o3/0 fd 9/9)
debug3: channel 3: close_fds r 9 w 9 e -1
debug1: client_input_channel_req: channel 2 rtype exit-status reply 0
debug2: channel 2: rcvd eof
debug2: channel 2: output open -> drain
debug2: channel 2: rcvd close
debug2: channel 2: close_read
debug2: channel 2: input open -> closed
debug3: channel 2: will not send data after close
logout
debug3: channel 2: will not send data after close
debug2: channel 2: obuf empty
debug2: channel 2: close_write
debug2: channel 2: output drain -> closed
debug2: channel 2: almost dead
debug2: channel 2: gc: notify user
debug2: channel 2: gc: user detached
debug2: channel 2: send close
debug2: channel 2: is dead
debug2: channel 2: garbage collecting
debug1: channel 2: free: client-session, nchannels 3
debug3: channel 2: status: The following connections are open:
#2 client-session (t4 r0 i3/0 o3/0 fd -1/-1)
debug3: channel 2: close_fds r -1 w -1 e 8
debug1: channel 0: free: port listener, nchannels 2
debug3: channel 0: status: The following connections are open:
debug3: channel 0: close_fds r 4 w 4 e -1
debug1: channel 1: free: port listener, nchannels 1
debug3: channel 1: status: The following connections are open:
debug3: channel 1: close_fds r 5 w 5 e -1
Connection to osgiliath.foo.com closed.
debug1: Transferred: stdin 0, stdout 0, stderr 54 bytes in 16.6 seconds
debug1: Bytes per second: stdin 0.0, stdout 0.0, stderr 3.3
debug1: Exit status 0
terrapin:~ irish$
--
Is this expected behavior? Is SSH supposed to exit as it did? Relevant version
information is as follows:
terrapin:~ irish$ uname -a
Darwin terrapin 8.0.0 Darwin Kernel Version 8.0.0: Sat Mar 26 14:15:22 PST 2005;
root:xnu-792.obj~1/RELEASE_PPC Power Macintosh powerpc
terrapin:~ irish$ ssh -V
OpenSSH_3.8.1p1, OpenSSL 0.9.7b 10 Apr 2003
irish at osgiliath:~$ uname -a
Linux osgiliath 2.4.23 #2 SMP Sat Jan 3 13:09:12 EST 2004 i686 GNU/Linux
irish at osgiliath:~$ dpkg -s ssh | grep Version
Version: 1:3.8.1p1-8.sarge.4
irish at osgiliath:~$ dpkg -s openssl | grep Version
Version: 0.9.7e-3
--
Richard's reply:
This appears to be a bug in OpenSSH, which only shows up when a TCP
connection to a forwarded port is closed extremely quickly after being
opened. The problem is here:
[channels.c]
static void
port_open_helper(Channel *c, char *rtype)
{
int direct;
char buf[1024];
char *remote_ipaddr = get_peer_ipaddr(c->sock);
>>>>>> u_short remote_port = get_peer_port(c->sock);
This is called very shortly after processing a connection opened on a
forwarded port, channel_post_port_listener(). I couldn't replicate this
by telnetting to the port, or even with a simple Perl program to open and
immediately close a connection:
----------------------------------------------------------------------
#!/usr/bin/perl
use IO::Socket;
use Carp;
($server,$port) = @ARGV;
$socket = IO::Socket::INET->new(PeerAddr => $server,
PeerPort => $port)
|| croak(qq*cannot connect to "$server"*);
$socket->close();
----------------------------------------------------------------------
However, with nmap -sT, I get this:
debug1: Connection to port 2001 forwarding to localhost port 22 requested.
debug1: channel 2: new [direct-tcpip]
debug1: getpeername failed: Transport endpoint is not connected
Nmap is written in C so is faster, and also if you look at the network
traffic, it simply sends a RST after the TCP handshake, whereas these
other test do the more graceful FIN/ACK/FIN/ACK sequence. The upshot is
that the close happens extremely quickly. Now, ssh exits at this point
because get_peer_port() does this:
[canohost.c]
if (getpeername(sock, (struct sockaddr *)&from, &fromlen) < 0) {
debug("getpeername failed: %.100s", strerror(errno));
cleanup_exit(255);
}
So ssh immediately exits if getpeername() fails. This is a bad choice,
since here is a non-catastrophic (if uncommon) failure mode: the
connection may already closed by the time execution reaches this point.
The code should be changed so that OpenSSH handles this case and
continues.
-- Richard Silverman res at qoxp.net
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.
More information about the openssh-bugs
mailing list