Hi, Question: Can a TCP server (running on the same host as the OpenSSH server) know the user id/name of a user forwarding an TCP port ? I.e. if someone on some client machine does ssh -L9999:localhost:9999 someuser at somehost nc localhost 9999 and a service accepts the connection on port localhost:9999 on somehost, can it somehow safely read out the user name "someuser"? Long explanation: We consider using SSH port forwarding as a way to enforce authentication and authorization in an old application (running on Linux) exposing a quite a few TCP connections. On the client side the clients can use OpenSSH client or Putty to make a Socks proxy. If their application framework already supports Socks they do not have to change much to connect. Or something like libssh can be used to include the ssh client side into the application. On the server side the sshd_config can be used to set up allowed ports per user or group. This is, however, not good enough, because the application will not know the original user id, so it can niether log actions, nor allow or block actions not allowed for that particular user. So my question is: Is there any way to let the TCP application server know the user id of the SSH forwarded TCP connection? If no, would it be possible to set up the OpenSSH server to do something special per destination port basis, such as connecting to a UNIX socket instead of a TCP socket or sending the user ID as the first thing on the connection ? (We could use UNIX socket forwarding, but the the client side can't use a Socks, and most other clients such as libssh does not support it either...) Regards, Esben
I think what you are looking for is ident <https://en.wikipedia.org/wiki/Ident_protocol>, but while I could see using it for auditing purposes I would be uncomfortable recommending it as an authentication mechanism. You would need to be running some identd (available in any Linux distro, usually gidentd), often through inetd/xinetd. --Greg On Sun, Jan 03, 2016 at 01:03:27AM +0100, Esben Nielsen wrote:> Hi, > > Question: > > Can a TCP server (running on the same host as the OpenSSH server) know > the user id/name of a user forwarding an TCP port ? > > I.e. if someone on some client machine does > ssh -L9999:localhost:9999 someuser at somehost > nc localhost 9999 > and a service accepts the connection on port localhost:9999 on > somehost, can it somehow safely read out the user name "someuser"? > > Long explanation: > > We consider using SSH port forwarding as a way to enforce > authentication and authorization in an old application (running on > Linux) exposing a quite a few TCP connections. > > On the client side the clients can use OpenSSH client or Putty to make > a Socks proxy. If their application framework already supports Socks > they do not have to change much to connect. Or something like libssh > can be used to include the ssh client side into the application. > > On the server side the sshd_config can be used to set up allowed ports > per user or group. This is, however, not good enough, because the > application will not know the original user id, so it can niether log > actions, nor allow or block actions not allowed for that particular > user. > > So my question is: > Is there any way to let the TCP application server know the user id of > the SSH forwarded TCP connection? > If no, would it be possible to set up the OpenSSH server to do > something special per destination port basis, such as connecting to a > UNIX socket instead of a TCP socket or sending the user ID as the > first thing on the connection ? > (We could use UNIX socket forwarding, but the the client side can't > use a Socks, and most other clients such as libssh does not support it > either...) > > Regards, > Esben > _______________________________________________ > openssh-unix-dev mailing list > openssh-unix-dev at mindrot.org > https://lists.mindrot.org/mailman/listinfo/openssh-unix-dev >
On Sun, Jan 3, 2016 at 11:03 AM, Esben Nielsen <nielsen.esben at gmail.com> wrote:> Can a TCP server (running on the same host as the OpenSSH server) know > the user id/name of a user forwarding an TCP port ? > > I.e. if someone on some client machine does > ssh -L9999:localhost:9999 someuser at somehost > nc localhost 9999 > and a service accepts the connection on port localhost:9999 on > somehost, can it somehow safely read out the user name "someuser"?If sshd is running with PrivilegeSeparation (which it does by default) then the sshd for that connection will be running as "someuser". On Linux, your application can figure out what that user is by calling getsockopt with SO_PEERCRED on the socket (there's example code in https://anongit.mindrot.org/openssh.git/tree/openbsd-compat/bsd-getpeereid.c) -- Darren Tucker (dtucker at zip.com.au) GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 Good judgement comes with experience. Unfortunately, the experience usually comes from bad judgement.
Den s?ndag den 3. januar 2016 skrev Darren Tucker <dtucker at zip.com.au>:> On Sun, Jan 3, 2016 at 11:03 AM, Esben Nielsen <nielsen.esben at gmail.com > <javascript:;>> wrote: > > Can a TCP server (running on the same host as the OpenSSH server) know > > the user id/name of a user forwarding an TCP port ? > > > > I.e. if someone on some client machine does > > ssh -L9999:localhost:9999 someuser at somehost > > nc localhost 9999 > > and a service accepts the connection on port localhost:9999 on > > somehost, can it somehow safely read out the user name "someuser"? > > If sshd is running with PrivilegeSeparation (which it does by default) > then the sshd for that connection will be running as "someuser". On > Linux, your application can figure out what that user is by calling > getsockopt with SO_PEERCRED on the socket (there's example code in > > https://anongit.mindrot.org/openssh.git/tree/openbsd-compat/bsd-getpeereid.c > ) > > -- >Darren Tucker (dtucker at zip.com.au)> GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 > Good judgement comes with experience. Unfortunately, the experience > usually comes from bad judgement. >-- Sendt fra Gmail Mobil
Unfortunately, SO_PEERCRED only works of UNIX domain sockets. For local tcp connections the UID is returened as -1. A solution could be to make a mapping option in sshd_config along with OpenPermit, such forwarding to say localhost:4000 can be remapped to UNIX socket /var/forwards/4000. Esben Den s?ndag den 3. januar 2016 skrev Darren Tucker <dtucker at zip.com.au>:> On Sun, Jan 3, 2016 at 11:03 AM, Esben Nielsen <nielsen.esben at gmail.com > <javascript:;>> wrote: > > Can a TCP server (running on the same host as the OpenSSH server) know > > the user id/name of a user forwarding an TCP port ? > > > > I.e. if someone on some client machine does > > ssh -L9999:localhost:9999 someuser at somehost > > nc localhost 9999 > > and a service accepts the connection on port localhost:9999 on > > somehost, can it somehow safely read out the user name "someuser"? > > If sshd is running with PrivilegeSeparation (which it does by default) > then the sshd for that connection will be running as "someuser". On > Linux, your application can figure out what that user is by calling > getsockopt with SO_PEERCRED on the socket (there's example code in > > https://anongit.mindrot.org/openssh.git/tree/openbsd-compat/bsd-getpeereid.c > ) > > -- > Darren Tucker (dtucker at zip.com.au) > GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4 37C9 C982 80C7 8FF4 FA69 > Good judgement comes with experience. Unfortunately, the experience > usually comes from bad judgement. >-- Sendt fra Gmail Mobil
On Sun, 3 Jan 2016, Esben Nielsen wrote:> Hi, > > Question: > > Can a TCP server (running on the same host as the OpenSSH server) know > the user id/name of a user forwarding an TCP port ?No; there are a number of impediments to implementing it. The SSH protocol doesn't support sending this information. It could conceivably be added as an extension though. We'd need to be careful in designing this - many users would be surprised if ssh started "leaking" user identifiers across forwarding channels. If the lack of protocol support was solved, another problem would be how the information is relayed to the next application. I'm not aware of a kernel mechanism to allow an application to fake a user identity across a local socket. Next problem: if one existed, it would almost certainly require root privileges and sshd takes great care to get rid off root privileges wherever possible. They certainly aren't used for port forwarding. TLDR: doing this is hard (I haven't even gone into user/uid mapping problems) and not likely to happen soon, sorry. -d
I propose making options in sshd_config to set up a mapping for each port: if the user tries to forward localhost:4000 you can specify in sshd_config that it is a UNIX socket connect to say /var/sshforward/4000.sock. Now the service can listen on /var/sshforward/4000.sock and use SO_PEERCRED (which is not working on local top sockets on my system at least). Esben Den mandag den 4. januar 2016 skrev Damien Miller <djm at mindrot.org>:> On Sun, 3 Jan 2016, Esben Nielsen wrote: > > > Hi, > > > > Question: > > > > Can a TCP server (running on the same host as the OpenSSH server) know > > the user id/name of a user forwarding an TCP port ? > > No; there are a number of impediments to implementing it. > > The SSH protocol doesn't support sending this information. It could > conceivably be added as an extension though. We'd need to be careful > in designing this - many users would be surprised if ssh started "leaking" > user identifiers across forwarding channels. > > If the lack of protocol support was solved, another problem would be > how the information is relayed to the next application. I'm not aware of > a kernel mechanism to allow an application to fake a user identity > across a local socket. > > Next problem: if one existed, it would almost certainly require root > privileges and sshd takes great care to get rid off root privileges > wherever possible. They certainly aren't used for port forwarding. > > TLDR: doing this is hard (I haven't even gone into user/uid mapping > problems) and not likely to happen soon, sorry. > > -d > > >-- Sendt fra Gmail Mobil
Damien Miller wrote:> > Can a TCP server (running on the same host as the OpenSSH server) know > > the user id/name of a user forwarding an TCP port ? > > No; there are a number of impediments to implementing it. > > The SSH protocol doesn't support sending this information.The original question was about the server-side username. I guess the solution is platform-specific. //Peter
On 03/01/16 01:03, Esben Nielsen wrote:> Hi, > > Question: > > Can a TCP server (running on the same host as the OpenSSH server) know > the user id/name of a user forwarding an TCP port ? > (...) > > So my question is: > Is there any way to let the TCP application server know the user id of > the SSH forwarded TCP connection?Yes. For instance a naive implementation could run a root netstat -e -tp looking for the other side of its connection. Even with an optimized search of the connection, I think you would need to end up with a root process scanning all fds per check, though. Additionally, I should note that you seem to be attempting the wrong solution ("tacklinh openssh in the middle") for your problem of authorizing users, making it needlessly complex. For instance, given that you seem to be developing the server side of the application, why don't you require socks authentication? (yes, socks protocol supports authentication, and even if the client implementation doesn't, it'd be easier to fix it than your solution) Regards