To serve up a service over TCP, some program has to call
listen() to get a listening socket, and that same program or one related to it has to call
accept() to accept the individual incoming TCP connections as further connected sockets.
OpenSSH's server dæmon operates in two basic modes in this regard.
- It is started without the
-i option. It executes
listen() and then loops repeatedly calling
fork()ing off child processes for every incoming connection.
- It is started with the
-i option. It expects something else to have called
fork(), and to have executed it with the connected socket as an already-open file descriptor.
The latter mode is the
nowait style of TCP server under the old
inetd superserver, the
Accept=yes style of TCP socket unit in systemd, and the style of server that works with Daniel J. Bernstein's UCSPI-TCP.
The former mode unfortunately does not correspond with the
wait style of TCP server under
inetd and the
Accept=no style of TCP server under systemd. OpenSSH does not speak the
LISTEN_FDS protocol and does not acknowledge already-open file descriptors for listening sockets. Additionally unfortunate is that some people encourage this mode of use and it is thus likely the way that OpenSSH is set up to run on your system.
Because what you want is the latter mode.
ssh -i inside something else that looks at the information about the remote end of the connnection and does stuff based upon what it finds before then
ssh -i. (UCSPI-TCP makes this very easy, as the remote end information is put into environment variables.) You then invoke the wrapper instead of invoking
ssh -i directly.
The particulars of doing this are up to you, because they depend from things that you haven't told us, such as what service management system you are using.
It could range widely from a drop-in snippet with a different
ExecStart in a systemd service unit through a revised
xinetd config file to a replacement
./service program in a nosh service bundle.
An alternative approach, which will work with the non-
-i invocation mode but which does not generalize beyond certain options of one particular program giving one particular service (as the aforegiven approach in contrast does), is to use the
Match mechanism in the
sshd_config file. This cannot do anything except set a subset of OpenSSH options, including the log level, and of course doesn't apply even to other SSH server softwares, let alone to other types of service.
Be sensible in your wrapper.
The SSH connection proper is not up and running at the time that it executes; you should not (for security) read any data from the network connection, nor write any to it; and the only things to be doing are checking addresses/ports against lists and thence configuring per-session settings in some way.