StreamLocal forwarding

Rogan Dawes rogan at dawes.za.net
Sun Apr 24 05:07:28 AEST 2016


Hi folks,

(3rd time I am sending this message, none of the other appear to have
made it through!)

Using "OpenSSH_6.9p1 Ubuntu-2ubuntu0.1, OpenSSL 1.0.2d 9 Jul 2015" on
the server, "OpenSSH_7.2p2, OpenSSL 1.0.2g  1 Mar 2016" on the client.

I am trying to use sshtunnel with StreamLocal forwarding to enable me
to connect back to the client's ssh port, without having to arbitrate
ports between clients.

The idea is to configure the server to allow StreamLocalForwarding via
a unique Unix socket on the host, that relays back to the client.

i.e. on the client (named gateway for this example, but will be unique
once deployed in volume):

/usr/bin/ssh -o CheckHostIP=yes -o LogLevel=INFO -o
ServerAliveCountMax=3 -o ServerAliveInterval=5 -o
StrictHostKeyChecking=yes -o TCPKeepAlive=yes -o
StreamLocalBindUnlink=yes -o ExitOnForwardFailure=yes -o BatchMode=yes
-nN -R /sshvpn/gateway:127.0.0.1:22 -p 52221 sshvpn at host

On the server:

Match User sshvpn
  ChrootDirectory /var/sshvpn/
  AllowTCPForwarding no
  AllowStreamLocalForwarding yes
  StreamLocalBindUnlink yes

Then to connect to the client:

$ ssh -o ProxyCommand='socat /var/sshvpn/sshvpn/gateway' root at gateway

So, it works fine the first time, when the socket does not exist. Once
the connection terminates, and the client attempts to log in again, it
fails because the socket already exists:

debug1: user sshvpn matched 'User sshvpn' at line 89
debug3: match found
debug3: reprocess config:90 setting ChrootDirectory /var/sshvpn/
debug3: reprocess config:91 setting AllowTCPForwarding no
debug3: reprocess config:92 setting AllowStreamLocalForwarding yes
debug3: reprocess config:93 setting StreamLocalBindUnlink yes
[...snip...]
debug1: server_input_global_request: rtype
streamlocal-forward at openssh.com want_reply 1
debug1: server_input_global_request: streamlocal-forward listen path
/sshvpn/gateway
debug3: channel_setup_fwd_listener_streamlocal: type 19 path /sshvpn/gateway
bind: Address already in use
unix_listener: cannot bind to path: /sshvpn/gateway

I am aware of the StreamLocalBindUnlink option, and you can see that
it is set on both the client and the server, but it doesn't seem to be
effective.

I also ran it under ltrace, and got the following:

24079 write(2, "debug3: channel_setup_fwd_listen"..., 78)  = 78
24079 umask(0177)                                          = 02
24079 socket(1, 1, 0)                                      = 8
24079 bind(8, 0x7ffc4f8915c0, 110, -1)                     = -1
24079 __errno_location()                                   = 0x7f03f55a5710
24079 strerror(98)                                         = "Address
already in use"

>From this, it appears that there is no attempt to unlink the socket if
it already exists, as would be expected from this code
(https://github.com/openssh/openssh-portable/blob/7de4b03a6e4071d454b72927ffaf52949fa34545/misc.c#L1083):

sock = socket(PF_UNIX, SOCK_STREAM, 0);
if (sock < 0) {
saved_errno = errno;
error("socket: %.100s", strerror(errno));
errno = saved_errno;
return -1;
}
if (unlink_first == 1) {
if (unlink(path) != 0 && errno != ENOENT)
error("unlink(%s): %.100s", path, strerror(errno));
}
if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
saved_errno = errno;
error("bind: %.100s", strerror(errno));
close(sock);
error("%s: cannot bind to path: %s", __func__, path);
errno = saved_errno;
return -1;
}

What am I missing?

Rogan


More information about the openssh-unix-dev mailing list