Como abordar isso
Um serviço que deve ser executado em um gerenciador de serviços não deve tentar se auto-daemonizar, não deve usar o mecanismo de arquivo PID instável e perigoso e não deve (no caso muito comum) descartar privilégios em si. Tudo isso será feito pelo sistema de gerenciamento de serviços, adequadamente.
Então, quando você executou o stunnel
na linha de comando, deveria ter feito o shell esperar até você terminar / parar o processo.
Toda a execução sob a égide de uma conta de usuário sem privilégios, configurando acesso reduzido ao sistema de arquivos e, na verdade (para aqueles programas capazes de herdar e usar descritores de arquivo de soquete aberto) abrindo o soquete de escuta é o domínio do gerenciamento de serviços .
É isso que as pessoas do sistema chamam ingenuamente de "estilo novo" de executar daemons. De fato, é exatamente assim que os usuários do daemontools vêm dizendo para administrar daemons nas últimas duas décadas, e que a IBM vem dizendo há um quarto de século.
Essa conta de usuário não privilegiada não deve ser nobody
, que pode ser listada como proprietária dos arquivos. O serviço em questão não precisa de permissão de propriedade em qualquer arquivos ou diretórios , , então a conta de usuário sem privilégios deve ser criada expressamente para esse propósito, com algo como:
useradd --shell /usr/bin/true mysql-stunnel-d
Um ambiente chroot()
para isso é realmente não-trivial para configurar no systemd, porque /bin/stunnel
e todos os arquivos que ele lê (que, de acordo com seu doco, além do arquivo de certificado e arquivo de configuração também inclui bastante material do sistema, com coisas como /dev/zero
, o sistema de configuração NSS e o banco de dados de fuso horário) precisam ser configurados com BindReadOnlyPaths
. Uma abordagem mais simples é o mecanismo Protect…
.
Arquivos de configuração
O soquete é descrito por uma unidade de soquete. stunnel
não entende o protocolo LISTEN_FDS
, mas é compatível com UCSPI-TCP. Portanto, a unidade de soquete tem que descrever um soquete de aceitação:
; /etc/systemd/service/mysql-stunnel.socket
[Unit]
Description=SSL wrapper for MySQL
Documentation=
[Socket]
ListenStream=127.0.0.1:mysql
ListenStream=[::1]:mysql
Accept=yes
NoDelay=yes
[Install]
WantedBy=multi-user.target
Observe que é o soquete que é ativado / desativado / iniciado / interrompido aqui, com systemctl
.
O serviço , descrito por uma unidade de serviço, é iniciado automaticamente sob demanda pelo soquete . Porque é uma tomada de aceitação, é uma unidade de serviço de modelo. Ele descreve todo o privilégio de descartar e configurar o gerenciamento de serviços:
; /etc/systemd/service/[email protected]
[Unit]
Description=SSL wrapper for MySQL
Documentation=
[Service]
Type=simple
User=mysql-stunnel-d
ProtectHome=yes
ProtectSystem=strict
PrivateTmp=yes
StandardInput=socket
StandardOutput=socket
StandardError=journal
ExecStart=/bin/stunnel /etc/stunnel/mysql-stunnel.conf
O arquivo de configuração stunnel
não lida com qualquer das coisas que o gerenciamento de serviços faz por ele :
# /etc/stunnel/mysql-stunnel.conf
cert = /etc/pki/tls/certs/stunnel.pem
client = yes
foreground = yes
connect = 10.0.0.3:3307
Conteúdo de bônus
Sim, esta é a maneira dos daemontools. Passe esses dois arquivos de unidade por meio do convert-systemd-units
do conjunto de ferramentas de dados e receba um programa run
e service
(entre vários outros) que exemplificam como isso é feito da maneira do daemontools, com um conjunto adequado de UCSPI de carregamento de corrente e outras ferramentas:
% system-control convert-systemd-units ./mysql-stunnel.socket
convert-systemd-units: WARNING: ./[email protected]: Forcing setting: [Service] StandardError = log
convert-systemd-units: WARNING: ./mysql-stunnel.socket: Unused setting: [unit] documentation =
convert-systemd-units: WARNING: ./[email protected]: Unused setting: [service] standarderror = journal
convert-systemd-units: WARNING: ./[email protected]: Unused setting: [unit] documentation =
% system-control cat ./mysql-stunnel
start:#!/bin/nosh
start:#Start file generated from ./mysql-stunnel.socket
start:true
stop:#!/bin/nosh
stop:#Stop file generated from ./mysql-stunnel.socket
stop:true
run:#!/bin/nosh
run:#Run file generated from ./mysql-stunnel.socket
run:#SSL wrapper for MySQL
run:tcp-socket-listen 127.0.0.1 mysql
run:tcp-socket-listen "::1" mysql
run:move-to-control-group ../mysql-stunnel.service
run:envuidgid --supplementary -- mysql-stunnel-d
run:userenv-fromenv
run:unshare --mount
run:set-mount-object --recursive slave /
run:make-private-fs --temp --homes
run:make-read-only-fs --os --etc
run:set-mount-object --recursive shared /
run:setuidgid --supplementary -- mysql-stunnel-d
run:tcp-socket-accept --no-delay
run:./service
service:#!/bin/nosh
service:#Service file generated from ./[email protected]
service:#SSL wrapper for MySQL
service:/bin/stunnel /etc/stunnel/mysql-stunnel.conf
restart:#!/bin/sh
restart:#Restart file generated from ./[email protected]
restart:exec false # ignore script arguments
%
Leitura adicional