Descrição da condição
Encontrei uma condição estranha com systemd e ssh no Ubuntu 18.04.3 LTS
Verifiquei o status da ssh.socket
unidade:
$ systemctl status ssh.socket
● ssh.socket - OpenBSD Secure Shell server socket
Loaded: loaded (/lib/systemd/system/ssh.socket; disabled; vendor preset: enabled)
Active: inactive (dead)
Listen: [::]:22 (Stream)
Accepted: 0; Connected: 0
E estava inativo, porém eu estava logado com ssh ao mesmo tempo e o serviço em si estava rodando, e o soquete do SSH e a porta correspondente estavam abertos:
$ lsof -P -i -n | grep sshd
sshd 26785 root 3u IPv4 14858764 0t0 TCP 10.200.130.28:22->10.100.40.141:42188 (ESTABLISHED)
sshd 26875 xxx_root 3u IPv4 14858764 0t0 TCP 10.200.130.28:22->10.100.40.141:42188 (ESTABLISHED)
sshd 63859 root 3u IPv4 238437 0t0 TCP *:22 (LISTEN)
sshd 63859 root 4u IPv6 238439 0t0 TCP *:22 (LISTEN)
Então olhei para o arquivo da unidade ssh.socket em /lib/systemd/system/ssh.socket
:
[Unit]
Description=OpenBSD Secure Shell server socket
Before=ssh.service
Conflicts=ssh.service
ConditionPathExists=!/etc/ssh/sshd_not_to_be_run
[Socket]
ListenStream=22
Accept=yes
[Install]
WantedBy=sockets.target
Por causa da Before=ssh.service
diretiva, ele deve ser iniciado antes do serviço ssh, e a Conflicts=ssh.service
diretiva fará com que ele pare quando o serviço ssh for iniciado.
O que explica por que isso acontece no aspecto dos arquivos unitários, mas levanta outras questões.
Questões
Por que o estado inativo da unidade ssh.socket não afeta o soquete ssh real?
Por que os mantenedores adicionaram a Conflict
diretiva? Por exemplo, se você verificar o arquivo da unidade, docker.socket
ele não está configurado para entrar em conflito com o arquivo docker.service
. Como o caso do sshd difere?
informação adicional
Também verifiquei isso em uma antiga estação de trabalho Fedora 30. Possui a mesma condição, com pequenas diferenças: utiliza sshd.service
e sshd.socket
como nomes de unidades e não há Before
diretiva no sshd.socket
arquivo da unidade.
Em ambos os sistemas não notei nenhum problema resultante desta condição e suspeito que tenha algum propósito, mas não consigo encontrar um.
Responder1
Um soquete systemd é um tipo especial de unidade que faz com que o systemd se ligue à porta (ou outro recurso, como um caminho de arquivo de soquete de domínio unix) e gere uma nova instância de um serviço para qualquer conexão. Com o ssh.service habilitado, seu sshd é executado continuamente e se liga ao soquete, como mostra seu lsof. Ter ssh.socket ativado significaria que o sshd não é executado continuamente, mas sim uma instância dele é invocada apenas para lidar com um cliente. E, em contraste, mostraria o systemd escutando na porta 22. Como o systemd e o sshd não podem escutar na mesma porta, ssh.socket especifica ssh.service como conflitante.
Responder2
O importante a entender é que o que você está vendo é um uso específico de unidades de "soquete", no total, existemtrês:http://0pointer.de/blog/projects/inetd.html
Portanto, no caso específico de ssh.socket
, isso é equivalente ao estilo antigoinvocação tipo inetd(configuração da unidade de soquete principal:) Accept=yes
, onde cada solicitação recebida na porta 22 (gerenciada pelo systemd) causa o início de um separado[email protected]
instância.
Consulte também a página de manual systemd.socket:https://www.freedesktop.org/software/systemd/man/systemd.socket.html
Se Accept=yes estiver definido, um modelo de serviço[e-mail protegido]deve existir a partir dos quais os serviços são instanciados para cada conexão de entrada
Portanto, existem no total duas maneiras diferentes de iniciar o sshd:
ssh.service
(sshd.service
é apenas um alias) inicia o processo sshd principal e a partir daí o processo lida com todas as conexões de entrada, gera processos filhos, etc.ssh.socket
+[email protected]
, aqui o systemd conecta todas as conexões de entrada da porta gerenciada por soquete a uma nova instância de[e-mail protegido], estilo inetd. É por isso que no serviço de modelo,StandardInput=socket
eExecStart=/usr/sbin/sshd
tem a-i
opção.
Obviamente, apenas uma abordagem pode ser usada por vez, Conflicts=
garantindo assim que ambas não estejam sendo executadas simultaneamente. (aliás: o posicionamento real da Conflicts=
estrofe não é importante, uma estrofe equivalente poderia ter sido escrita em ssh.service, mas uma é suficiente)