Generally, the shutdown schedule is working as expected:
- The parent SSH server service is stopped first, hence no new connections can be established.
- The existing connection workers are however not stopped. This is an intended feature, so
systemctl restart ssh does not abort the connection, and it is possible to maintain the system, upgrade the SSH server package, and even switch from one SSH server to another (purge OpenSSH, install Dropbear, vice versa) while connected via SSH, and the connection remains intact, instead of aborting the operation in an unfinished state. This is achieved by KillMode=process in both: dropbear.service as well as ssh.service, as you can check on all Linux distros, and upstream systemd units.
- The network connection is terminated late, but it is explicitly terminated as part of
networking.service at some point of the “regular” shutdown schedule. The SSH connection workers are not scheduled anywhere to be terminated, hence systemd just sends a kill signal to those after the regular schedule finished, like it does to all remaining processes that are still up at this point.
It seems logind is terminating SSH client connections as well on shutdown, via session cgroup. I am not sure why dietpi-kill_ssh is not working for you, as it should have the same effect. Maybe in edge cases, it needs to be explicitly ordered After=networking.service (or better After=network.target), to assure it is stopped before network is teared down (the ordering directives are reversed on shutdown). Can you test this:
G_CONFIG_INJECT 'After=' 'After=network.target' /etc/systemd/system/dietpi-kill_ssh.service '\[Unit\]'
systemctl enable dietpi-kill_ssh
And to define more precisely when it runs, after the SSH server services (parent processes) stopped:
G_CONFIG_INJECT 'Before=' 'Before=dropbear.service ssh.service' /etc/systemd/system/dietpi-kill_ssh.service '\[Unit\]'
systemctl daemon-reload
When enabling persistent journal logs, one can check the shutdown schedule. This is how it looks like on two of my systems:
journalctl -u dropbear -u ssh -u dietpi-kill_ssh -u network.target -u network-online.target -u networking
One with Dropbear:
May 02 17:01:13 host systemd[1]: Starting dietpi-kill_ssh.service - DietPi-Kill_SSH on shutdown...
May 02 17:01:13 host dropbear[558]: [558] May 02 17:01:13 Early exit: Terminated by signal
May 02 17:01:13 host systemd[1]: Stopping dropbear.service - Dropbear...
May 02 17:01:13 host dropbear[930]: [930] May 02 17:01:13 Exit (root) from <XXXX>: Terminated by signal
May 02 17:01:13 host dropbear[930]: [930] May 02 17:01:13 syslogin_perform_logout: logout(pts/0) returned an error: No such file or directory
May 02 17:01:13 host systemd[1]: dropbear.service: Deactivated successfully.
May 02 17:01:13 host systemd[1]: dropbear.service: Unit process 935 (screen) remains running after unit stopped.
May 02 17:01:13 host systemd[1]: dropbear.service: Unit process 936 (bash) remains running after unit stopped.
May 02 17:01:13 host systemd[1]: dropbear.service: Unit process 1120 (systemctl) remains running after unit stopped.
May 02 17:01:13 host systemd[1]: dropbear.service: Unit process 1121 (systemd-tty-ask) remains running after unit stopped.
May 02 17:01:13 host systemd[1]: Stopped dropbear.service - Dropbear.
May 02 17:01:13 host systemd[1]: dropbear.service: Consumed 1.280s CPU time over 44.561s wall clock time, 37.5M memory peak.
May 02 17:01:14 host systemd[1]: Stopped target network-online.target - Network is Online.
May 02 17:01:15 host systemd[1]: dietpi-kill_ssh.service: Deactivated successfully.
May 02 17:01:15 host systemd[1]: Finished dietpi-kill_ssh.service - DietPi-Kill_SSH on shutdown.
May 02 17:01:25 host systemd[1]: Stopped target network.target - Network.
May 02 17:01:25 host systemd[1]: Stopping networking.service - Raise network interfaces...
May 02 17:01:25 host systemd[1]: networking.service: Deactivated successfully.
May 02 17:01:25 host systemd[1]: Stopped networking.service - Raise network interfaces.
One with OpenSSH:
May 02 12:56:49 host systemd[1]: Starting dietpi-kill_ssh.service - DietPi-Kill_SSH on shutdown...
May 02 12:56:49 host systemd[1]: Stopping ssh.service - OpenBSD Secure Shell server...
May 02 12:56:49 host systemd[1]: ssh.service: Deactivated successfully.
May 02 12:56:49 host systemd[1]: ssh.service: Unit process 2968812 (screen) remains running after unit stopped.
May 02 12:56:49 host systemd[1]: ssh.service: Unit process 3992509 (gpg-agent) remains running after unit stopped.
May 02 12:56:49 host systemd[1]: ssh.service: Unit process 2009186 (bash) remains running after unit stopped.
May 02 12:56:49 host systemd[1]: ssh.service: Unit process 3489706 (sshd-session) remains running after unit stopped.
May 02 12:56:49 host systemd[1]: ssh.service: Unit process 3489712 (sshd-session) remains running after unit stopped.
May 02 12:56:49 host systemd[1]: ssh.service: Unit process 3489716 (screen) remains running after unit stopped.
May 02 12:56:49 host systemd[1]: ssh.service: Unit process 3501386 (systemctl) remains running after unit stopped.
May 02 12:56:49 host systemd[1]: ssh.service: Unit process 3501387 (systemd-tty-ask) remains running after unit stopped.
May 02 12:56:49 host systemd[1]: Stopped ssh.service - OpenBSD Secure Shell server.
May 02 12:56:49 host systemd[1]: ssh.service: Consumed 32min 42.363s CPU time over 1w 4d 7h 56min 43.474s wall clock time, 14.9G memory peak.
May 02 12:56:51 host systemd[1]: dietpi-kill_ssh.service: Deactivated successfully.
May 02 12:56:51 host systemd[1]: Finished dietpi-kill_ssh.service - DietPi-Kill_SSH on shutdown.
May 02 12:56:52 host systemd[1]: Stopped target network-online.target - Network is Online.
May 02 12:56:52 host systemd[1]: Stopped target network.target - Network.
May 02 12:56:52 host systemd[1]: Stopping networking.service - Raise network interfaces...
May 02 12:56:52 host systemd[1]: networking.service: Deactivated successfully.
May 02 12:56:52 host systemd[1]: Stopped networking.service - Raise network interfaces.
You can see the logs form the SSH service stop, leaving the processes from the client connection active: the client connection processes, GNU screen (which I use), the shell, the systemctl command (reboot is a symlink to systemctl). But then our kill service terminates the SSH connection processes before network is teared down. It would be however cleaner if our kill service runs after the SSH server services stopped, so it kills only the remaining child connection processes.
However, if in your case networking.service stops before our kill service runs, our service cannot have any effect anymore.
If ordering is not the issue, try to enable logind instead:
systemctl disable dietpi-kill_ssh
systemctl unmask systemd-logind
apt install dbus
systemctl start dbus systemd-logind
Would be also interesting the compare the shutdown logs in that case, whether the SSH client connection processes are terminated explicitly as well (by logind/PAM/whatever). Or maybe there is even another signal involved that causes a more graceful SSH connection stop. If so, we could use that signal in our service as well.