Why do you want to do it?
There may be many reasons why you want to do it, but for us a simple reason comes to mind. We want to allow users to use a jumphost to jump into our IPv6 net from IPv4, but they don't need shell access for it. So by allowing them to jump, but denying a shell, we have a jumphost with way fewer security concerns than if it was just a normal SSH Host.
This way, with a small edit of the .ssh/config, we can provide a nearly transparent jump with just an added intermediate authentication to go through.
How to do it in sshd_config
The first solution coming to most minds would be some combination of AllowUsers, DenyUsers or the group variant. That seems easiest and you can easily implement either a blacklist or whitelist, but it won't work, since denying a user also denies them the ability to make use of the jumphost feature.
Another solution would be to give the users the nologin executable as a shell, which will work for denying them access to the host itself, but feels like a rather inelegant solution. It's much better to simply define the solution in the sshd_config, since there it's a single option, and it doesn't rely on the correct configuration of every user's shell, which adds a further risk that something can go wrong.
With the thought that we want a simple, central solution in mind, let's look at our options. In the sshd_config, we want to either define a whitelist or a blacklist, so the Match keyword is a natural candidate to do it.
Here is an example for a blacklist:
Now that we have a match for the jumphost users, let's get to denying the shell access. From what I've seen, there are two very simple solutions to that. For the examples we use a simple whitelist, but of course every form of matching described earlier will work too.
This overrides every command send with /bin/true, so no shell or execution of programs through ssh. Basically, it is a much nicer version of the nologin-shell described above. Still, I feel that this is still not the most elegant and efficient solution, since it will still run the command. That step is not needed I feel, and the next solution is more elegant to my mind.
This version tells the SSH the number of allowed open shell, login or subsystem sessions permitted per network connection. So with this set to 0, none of the above is allowed, but it is still permitting proxying, which is just what we want. I feel this is the most elegant solution, since it will disallow commands and shells, and does it without substituting it with a small command, so forgoing the (in my mind) unnecessary step.
There may be other solutions, but I feel the 'MaxSessions 0' solution is doing exactly what we want from the jumphost, so this is the
one implemented on our jumphost. The 'ForceCommand' and nologin solutions work too, but through executing a command they take an extra
step, which, given current hardware, is not really noticeable, but can be avoided, so why not avoid it?
To configure a jumphost in sshd_config for a set of users, you can either use a whitelist for shellaccess or a blacklist for just jumping.
So for a quick reference here are the matches you put at the end of the sshd_config: