Reputation: 467
I wonder if there is any way to retrieve, for both a server and a client connected through ssh (OpenSSH), some unique session identifier (let this be USID).
This would be used to restrict the execution of a specific (custom) software (let it be a.exe), so it can only be executed through a specific ssh session, even if other users (potentially root) have access to that executable:
The communication channels between X and C, X and S are secure, so the only issue here is retrieving that USID without having to write my own ssh client and/or server.
Any ideas?
Upvotes: 2
Views: 4125
Reputation: 9679
I'm responding 14 years later, which has seen quite a bit of development in the public space in the area. Even though you probably do not require an update anymore, I'll respond anyway, for readers who run into this via public search like I did.
You are really phrasing two problems:
You are really asking a solution for the second bit, but I'll cover both.
Assuming you really require a session ID to be passed from a client to a server, one way to do it without hacking the client or the server is to build a wrapper around the client.
A small wrapper can generate a UUID, export it into the environment, then pass it via SendEnv YOUR_VARIABLE_NAME
.
#!/bin/bash
export SSH_SESSION_ID=$(uuidgen) # this is your USID
ssh -O SendEnv SSH_SESSION_ID "$1" # or set it in ~/.ssh/config, or /etc/ssh/ssh_config
Aside from having the client SendEnv
, your server needs to accept it. Adjust /etc/ssh/sshd_config
to AcceptEnv SSH_SESSION_ID
.
See an answer on passing environment variables.
Identifying the connection could be interesting for another reason; tracing job execution across machines and joining the spans together with OpenTelemetry, or pairing the access with a user for legal reasons, or for analysis reasons. I would not really do it for security / ACL reasons.
You can likely do a hack with tcpwrappers
(/etc/hosts.allow
) and the aclexec
stanza in there. sshd : ALL : aclexec /opt/sshd-hosts_options.sh %a
would pass in the address as the first argument to your custom script, but you can pass in multiple arguments. %p
would give you the PID that's trying to do ACLing, so you can inspect procfs (/proc/PID/...
) for the connections incoming to that server. If the wrapper around the client uses ProxyCommand
to specify an intermediary for the connection, you can inspect what the source TCP port is, and register that with your ACLing service (assumption: ACLing service trusts the client to register the source port), allowing the server's aclexec
script to validate the connection is really coming from a trusted party.
Caveat: around 2017, there was chatter about tcpwrappers being deprecated and possibly removed from OpenSSH. I'm on Debian, and use of tcpwrappers on incoming connections works fine; Fedora's docs say it's removed by default on Fedora 28.
Yet another caveat: If a user uses a bouncer or uses a non-local relay via ProxyCommand
, you might also have a different address/port visible via tcpwrappers.
It is possible to instead just focus on the actual goal: ensure that the trusted machine is "safe enough".
Instead of the complication with the connection itself, let's focus on just giving the authentication token which is valid for 'long enough', as long as the machine is trusted.
SSH comes with a new type of keys which are not really keys: they're certificates. They're not in the formats of usual TLS certificates (though they can be converted), but the main benefit for us is that they have expiration time, and can be revoked.
Manpages for ssh-keygen
, sshd_config
etc contain enough information: see
mainly TrustedUserCAKeys
, but also CASignatureAlgorithms
, HostCertificate
, RevokedKeys
.
Eventually the cert expires, and if the client became untrusted in the meantime, the service you write to issue certs rejects the request.
Downside: User can, of course, still copy the cert from a trusted machine to an untrusted machine.
Depending on your setup, if you have a functioning Kerberos install, you might instead choose to reject connections to Kerberos from untrusted machines. This would also prevent the user from SSHing from an untrusted machine.
Downside: Ticket could still be copied from a trusted machine to an untrusted one.
All in all:
I would rather build the SSH CA / Kerberos infrastructure and care about "is the server able to present a trustworthy ssh cert / Kerberos ticket", and have a short max age of a cert, than actually identify the connection with a session ID.
I wrote a bit more, but I felt like I went into too many details. If the shortened text is lacking in detail too much, please ask for clarification; in particular, I removed some tcpwrappers
samples, some random ideas about identifying connections and some ramblings about SSH CA.
Upvotes: 1
Reputation: 5031
seems to me in a round about way, you are trying to re-implement kerberos. Seems to me that you want to GSSAPI secure the transport between client and server; so your client needs to authenticate to the server.
Typical way of doing this would be to 'kinit' to a prinicpal using a keytab, and then passing this credential to the server. Kerberos ensures that it's reasonably hard to fake.
that's probably going to be a little less brittle than the method that you describe above.
-Ace
Upvotes: 1