Allow UNIX socket forwarding, but disallow TCP forwarding?

Thomas Orozco thomas at aptible.com
Sat Nov 19 01:18:59 AEDT 2016


Hi there!

We're trying to set up OpenSSH to allow socket forwarding, but
disallow TCP forwarding.

The "intuitive" configuration doesn't appear to work (more on that below!):

```
AllowTCPForwarding no
AllowStreamLocalForwarding yes
PermitOpen any
```

First a note about our use case.

We're using OpenSSH on a bastion host (technically, OpenSSH itself is
running within a container on a bastion host, but that's not very
important here) and using it to punch holes in our network for
authorized users.

Here's an example, we have a bastion host that's accessible to both
Alice and Bob (who may or may not be adversarial towards each other).

Both users have one database running on a server that's accessible
*behind* the bastion host (it's reasonably easy for both Alice and Bob
to find the IP for this). We want Alice to be able to access her own
DB, and Bob to access his, but we don't want them to access each
other's database.

So, to let Alice and Bob log in to our bastion host, we want to
provide them with (short-term) SSH Certificates that essentially:

- Allow port forwarding.
- Set up a force command that runs socat listening on a specific UNIX
socket and forwarding to the user's database (I'm simplifying a little
bit here). Currently, Bob and Alice use the same user, so we randomize
the socket name to prevent them from simply connecting to the other's
socket. In the longer term, they might use different users altogether.

Now, hopefully, this makes some sense!

Assuming it does, here's the problem we're running into: this
configuration doesn't actually work. When we attempt to create a port
forward with it, SSHD doesn't allow it:

```
debug1: server_input_channel_open: ctype
direct-streamlocal at openssh.com rchan 7 win 2097152 max 32768
debug1: server_request_direct_streamlocal: originator 127.0.0.1 port
54402, target MY_SOCKET
Received request to connect to path MY_SOCKET, but the request was denied.
debug1: server_input_channel_open: failure direct-streamlocal at openssh.com
```

This appears to be caused by the fact that if TCP forwarding is
disabled, the function do_authenticated in session.c will disable all
forwarding (by calling channel_disable_adm_local_opens).

But, unfortunately, enabling TCP forwarding here would defeat what
we're trying to do: that'd allow Alice and Bob to directly establish a
port forward to one of the database hosts behind the bastion host,
bypassing the socat tunnel altogether.

Now, we tried using PermitOpen to lock that down, but unfortunately,
that doesn't appear to work either:

- It appears that for a stream local forward, SSHD matches the path of
the socket against the hosts allowed in PermitOpen, which
unfortunately doesn't work for us here, so we can't restrict forwards
that way.
- It *also* appears that SSHD matches the port -2 against PermitOpen
for a stream local forward, but -2 isn't a valid port in PermitOpen :)

Now, digging a little further, the following patch *appears* to make
things work (it allows stream local forwarding, but continues to
disallow TCP forwarding — at least in my trivial testing...):

diff --git a/session.c b/session.c
index 85805f5..0717c2c 100644
--- a/session.c
+++ b/session.c
@@ -256,9 +256,9 @@ do_authenticated(Authctxt *authctxt)
        setproctitle("%s", authctxt->pw->pw_name);

        /* setup the channel layer */
-       /* XXX - streamlocal? */
        if (no_port_forwarding_flag ||
-           (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
+           ((options.allow_tcp_forwarding & FORWARD_LOCAL) == 0) &&
+            (options.allow_streamlocal_forwarding & FORWARD_LOCAL) == 0)
                channel_disable_adm_local_opens();
        else
                channel_permit_all_opens();


So, my questions to you are:

- Is this a use case that makes sense for OpenSSH?
- If so, how appropriate is the above patch? As I mentioned, in my
testing, it doesn't appear to allow TCP forwarding when it should be
disabled, but I don't understand exactly what the
`options.allow_tcp_forwarding & FORWARD_LOCAL) == 0` condition is
looking for yet, so this is likely to be totally the wrong way to go
about this.

Thanks in advance!

-- Thomas

-- 
*Disclaimer: This e-mail and any attachments may contain confidential 
information. If you are not the intended recipient, any disclosure, 
copying, distribution or use of any information contained herein is 
strictly prohibited. *

*If you have received this transmission in error, please immediately notify 
security at aptible.com <security at aptible.com> or call (866) 296-5003 and 
destroy the original transmission and any attachments without reading or 
saving.*


More information about the openssh-unix-dev mailing list