Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support UNIX sockets for server and viewer #160

Closed
calestyo opened this issue Mar 31, 2015 · 21 comments
Closed

support UNIX sockets for server and viewer #160

calestyo opened this issue Mar 31, 2015 · 21 comments
Labels
enhancement New feature or request

Comments

@calestyo
Copy link

calestyo commented Mar 31, 2015

Hi.

It would be nice if the connection would work via UNIX sockets, for both the server and the client.

This would be a great security boost, since on a local system, connection to the server socket can be controlled via normal file permissions (which isn't possible for inet sockets), and to the remote the socket can be forwarded via SSH.

Cheers,
Chris.

@CendioOssman
Copy link
Member

Just a FYI, file permissions aren't respected on Unix sockets on all operating systems, and OpenSSH can forward Unix sockets. So security should be enforced using authentication.

But this might be a useful feature anyway. If nothing else it makes it easier to deal with port allocation.

@CendioOssman CendioOssman added the enhancement New feature or request label Mar 31, 2015
@calestyo
Copy link
Author

Well than that's something the respective OS need to fix. And then of course SSH can also just forward those sockets, which it can access.

And getting other ways of proper authentication into VNC is probably a lost cause - actually I'd say that using the user permissions of the local system is the proper way, which is also what many other daemons (e.g. DBMS) offer and do.

@hifi
Copy link
Contributor

hifi commented Jun 29, 2015

I've done something like this with no "upstream" support. The point is to run Xvnc on the remote server in classic inetd mode (stdin/stdout) and then forward that to local UNIX socket. Then, attach stdin/stdout of a ssh session to that socket. This works with any OpenSSH version and current TigerVNC Xvnc server. You also need some sort of session in $HOME/.xinitrc for it to do anything useful.

https://gist.github.com/hifi/4321ffe9d56612b2449f (vncpipe.pl in $HOME of target system)

Client side, I've used netcat with OpenSSH to convert the ssh stdin and stdout into a localhost bound TCP socket:

nc -l 1234 -e "ssh user@host ./vncpipe.pl"

Finally connect TigerVNC without any authentication to localhost port 1234. This does work on Windows as well if you have OpenSSH ssh.exe and nc.exe.

Pros:

  • Server side is secure with UNIX sockets
  • Connection encryption and authentication done with SSH
  • Multiple users can run their own Xvnc sessions simultaneously
  • If you don't log out of the X session it will continue running in the background and reconnecting will resume it
  • You can resize the client and server resizes with it (TigerVNC client/server feature)

Cons:

  • Only one connection to the same Xvnc session because -inetd mode with vncpipe.pl
  • Need to install vncpipe.pl and Perl on the target system
  • Odd client side connection without support in TigerVNC
  • Because of above, client depends on netcat (does work on Windows though!)

To fix all the cons:

  • Add support in the client for piping the stdin/stdout of a SSH session directly as the VNC stream
  • Add UNIX socket support to Xvnc
  • Add a new program/wrapper for Xvnc that does what vncpipe.pl currently does but better allowing multiple shared connections when Xvnc supports UNIX sockets
  • Client would connect and run the new program/wrapper instead of vncpipe

Note that OpenSSH UNIX socket forwarding is not required for this which is a fairly new feature.

Most of the suggested new features are very trivial to implement and UNIX sockets just require different initialization and command line arguments for the server. Client side SSH integration can be hacked around by having local exec option where you can give ssh command line and it will assume stdin/stdout of the command will be the VNC stream or something along these lines. The startup wrapper only needs to run Xvnc if the specified local UNIX socket does not exist, otherwise just pipe through stdin/stdout to the socket.

If there's any desire from anyone to +1 this, I could look into adding some of the support but I'm not qualified to do this kind of work which involves data security.

@calestyo
Copy link
Author

Nice work... at least until stuff is properly integrated into the VNC server/client itself.

The remaining major problem with that script solution seems to be the there is no or only weak authentication on the client side?
Anyone who can connect to the listening nc (i.e. everyone on localhost), can not only trigger the ssh to be run under the context of the user who run nc, but also use that user's credentials for ssh.

@hifi
Copy link
Contributor

hifi commented Jun 29, 2015

Yes, there's no authentication used client side and if implemented properly none is needed as everything is handled by SSH which is a lot nicer to use when you can depend on your existing account and public key to open up your VNC session instead of having yet another authentication layer and password to remember (or certificate).

And you're correct that the listening nc is open to others between you issuing the command and TigerVNC connecting to it. However, in many situations that's not a real security concern (single user systems) so I didn't include it as a con.

I thought about adding simple 'ProxyCommand' support like in SSH to the TigerVNC client that takes a command to run and it would use its stdin and stdout as the input and output stream. That might have other uses where you want custom transport or authentication and it will eliminate the security concern while making it a lot more convenient to use. However, something like openssh-askpass is needed so that it doesn't use stdin to prompt for a password or passphrase.

With only ProxyCommand added the server side script is already fully usable if you don't mind having no session sharing support. It might have a few bugs here and there like stale local UNIX socket if there's an unclean shutdown and it will in its current form require manual intervention.

@calestyo
Copy link
Author

Hmm don't understand what you mean.
With ssh you authenticate/authorize the tunnel between remote and local host, but not between remote server software and local client software.
In your setup SSH connects the remote UNIX host to a local TCP port (AFAIU),... and anyone who can connect to that local TCP port (typically at least each local user) can thus connect to the remote server software.
Either at any time, when you use netcat as above with -e, i.e. it will execute ssh in the "other user's" context when anyone connects to the local TCP port... (btw: -e is not supported by the openbsd netcat version, which is default in at least debian distros)....
...or, when not using that nc spwaning, once the main user set up the ssh tunnel manually.

Something like ProxyCommand inside the VNC client, would of course solve this, cause then not locally listening TCP port would be needed anymore.
That's basically an alternative to the "make the client support using UNIX sockets"...

@hifi
Copy link
Contributor

hifi commented Jun 30, 2015

What I tried to say is that nc doesn't by default listen for more than one connection (requires -k for re-listening after previous has closed) and if you need to do password authentication or passphrase it asks that only after the client has connected. So for example when I start up nc it just waits there until my TigerVNC connects to it and then immediately it asks for my key passphrase. If it would ask that prior to connecting the VNC client someone else would have connected to the port first.

If -e isn't supported, you can most definitely use socat instead. Don't know the command line though. Nmap ncat supports -e which is available on Fedora at least.

I will look into ProxyCommand if I can manage with the C++ code base.

@calestyo
Copy link
Author

Sure,... but than there's in principle a race condition... another user on the local system could theoretically be faster then me with connecting to the socket.
Plus, this assumes that you actually have to enter some password at the ssh level.
I for example run completely passwordless there, as my system is so heavily secured&encrypted...everyone who manages to get into it, really deserves having my ssh keys ;-)

btw: I had a look at Xvnc -inet.
With the one from tightvnc,.. simply nothing happens when you pass -inet (i.e. the process exits without error.
With the one from Debian's vnc4server package, one actually gets the RFB prompt to stdout,.. but apparently it still opens a (random) TCP port and listens on it.

So that would AFAICS make the whole idea useless... cause local users at the remote system could then still connect to that TCP port, right?

@hifi
Copy link
Contributor

hifi commented Jun 30, 2015

In practice, how many local users a normal GUI enabled system has? One. I'm not saying it's not a security issue, just that it's not very meaningful.

Updated the gist with -nolisten tcp so that the X server doesn't listen on a local TCP port. Also for the record I did use TigerVNC's Xvnc because it supports resize unlike any other Xvnc implementation. I think it also performs the best, maybe others didn't have jpeg support for example.

@hifi
Copy link
Contributor

hifi commented Jun 30, 2015

Updated gist with a proof-of-concept patch that adds shaky ProxyCommand like support by abusing the VNC server name as the proxy command and passes it to /bin/sh. It works just fine like:

vncviewer "ssh user@host ./vncpipe.pl"

The way I made a simple PipeSocket class does not work on Windows AFAIK where pipes are not stdio compatible so it's not portable. Making it portable on Windows would require making completely new implementation of InStream and OutStream that work on named pipes and ReadFile/WriteFile. For it to be useful it definitely needs to run on Windows though.

I might try this for the Java client next where portability is easier to achieve.

@bphinz
Copy link
Contributor

bphinz commented Jun 30, 2015

On Tue, Jun 30, 2015 at 3:21 PM, Toni Spets wrote:

Updated gist with a proof-of-concept patch that adds shaky ProxyCommand
like support by abusing the VNC server name as the proxy command and passes
it to /bin/sh. It works just fine like:

vncviewer "ssh user@host ./vncpipe.pl"

The way I made a simple PipeSocket class does not work on Windows AFAIK
where pipes are not stdio compatible so it's not portable. Making it
portable on Windows would require making completely new implementation of
InStream and OutStream that work on named pipes and ReadFile/WriteFile. For
it to be useful it definitely needs to run on Windows though.

I might try this for the Java client next where portability is easier to
achieve.

AFAIK, all java implementations of unix domain sockets rely on JNI, but if
you find otherwise I would be interested to hear about it.

Thanks,
-brian

@calestyo
Copy link
Author

In practice, how many local users a normal GUI enabled system has?
One. I'm not saying it's not a security issue, just that it's not very meaningful.
Well speak only for yourself... ;-)

We have here at the institute workstations where each user can connect to... so running a VNC server as my user, where everyone can connect to is not acceptable.
Actually getting proper user based authentication was the whole/main reason for asking for UNIX socket support.
But -nolisten tcp actually does the job :-)

I would also like to use TigerVNC (tightvnc seems to be pretty unmaintained)... unfortunately it's not yet packaged for Debian :-(
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=650394
That's the only reason I tried it with the other implementation.

@hifi
Copy link
Contributor

hifi commented Jul 1, 2015

AFAIK, all java implementations of unix domain sockets rely on JNI, but if you find otherwise I would be interested to hear about it.

I didn't add UNIX socket support to TigerVNC viewer in the patch but stdio/stdout piping which can effectively do what I need and more. This is what I was going to do with the Java client as well. Though, the Java client has integrated SSH support so I'd be more interested to leverage that instead directly.

I was wrong about one of the cons. Shared sessions actually work fine since in -inetd mode the listening socket is duplicated and at least TigerVNC's Xvnc accepts more than one connection simultaneously. So technically it's not really needed to add UNIX socket support to Xvnc as the Perl wrapper works quite fine with it. Maybe add more error checking so that dead Xvnc can be detected and the stale socket removed.

@hifi
Copy link
Contributor

hifi commented Jul 1, 2015

We have here at the institute workstations where each user can connect to... so running a VNC server as my user, where everyone can connect to is not acceptable.

Meant the client side socket on the desktop you run netcat on. Naturally server side needs to be secured against other users if the whole point is to run multiple Xvnc sessions by multiple users.

I also know the sad state of TigerVNC on Debian based distributions. Hopefully it will get properly packaged as you also noticed the other VNC implementations are not very much maintained anymore. For server side stuff, RHEL/CentOS fortunately package and ship TigerVNC and EL7 already has very usable version in so that has been my main target so far regarding Xvnc.

@hifi
Copy link
Contributor

hifi commented Jul 4, 2015

hifi@1f3d9d0

Here's a test commit to add suppot for both in the Java client. Can use stdin/stdout and direct exec channel over integrated SSH client. The boilerplates are a bit weird but I'm not going to put more effort in this unless there's actual interest to merge something like it.

@CendioOssman
Copy link
Member

Sorry, I didn't realise you were waiting for feedback.

I think the idea is very interesting, and I see no major obstacles towards merging (once the code is reasonably polished).

There are several components here, so let's take one step at a time. Let's start with adding UNIX socket support to Xvnc/libvnc.so and the clients.

@hifi
Copy link
Contributor

hifi commented Dec 1, 2015

What needs to be implemented depends on how the full chain will operate.

What has been implemented and what can be currently hacked around depends on stdio instead of UNIX domain sockets and they are used only as a workaround.

In my opinion, ideally, there would be no UNIX domain sockets at all or they would be an implementation detail and all communication happens with stdio and exec channel over ssh. The clients don't need any other support than ssh exec channel or optionally like I've currently gisted, just stdio support and the transport layer (ssh) is glued on top externally.

However, I do understand that UNIX sockets might be useful for something else and they could be implemented separately. However, I think many have wanted the same outcome as I have so UNIX sockets would be rather irrelevant in the end.

There are two actual use cases for it, though. First would be connecting to an existing X session (not using Xvnc) and second would be launching Xvnc like in my gists. It should also be configurable if the Xvnc should exit when the user disconnects or stay in the background. There are no implementations for the first case in my gists but ideally it would work the same way for the clients.

@JensTimmerman
Copy link

@hifi are there any updates on this?
I really like your idea, it would allow us to solve a the 'password' problem, letting ssh and stdio doing the authentication and authorization would let us do this with public/private keys. So I'm all in favour, however, it doesn't sound like your solution belongs in this issue? Maybe we can create a sepearate issue/pull request for this wonderful solution?

@hifi
Copy link
Contributor

hifi commented May 27, 2016

@JensTimmerman I opened issue #250 over 6 months ago but the developers don't believe in it so it came to a dead end.

@ryanlovett
Copy link

Fyi, someone wrote a patch against an old version of tigervnc server to enable local unix sockets:
https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=709571

@CendioOssman
Copy link
Member

Thank you. Nice find. :)
Hopefully we just need a small cleanup of that to merge it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

6 participants