iptables serviço falha com systemd porque bind9 não está realmente pronto

1

Estou tentando invocar o iptables-restore em um script systemd.service. Eu tenho várias regras que exigem pesquisa de DNS. Eu incluí After = bind9.service na seção Unit do firewall. No entanto, o systemd acha que o bind9 é iniciado quando ele é forjado, não quando o nome está pronto para atender a solicitações. Ele inicia a restauração do iptables antes de poder resolver o nome do host e, portanto, falha. Aqui está a seção pertinente do syslog:

Dec 13 21:29:02 fw systemd[1]: Started BIND Domain Name Server.
Dec 13 21:29:02 fw systemd[1]: Reached target Host and Network Name Lookups.
Dec 13 21:29:02 fw systemd[1]: Starting Load iptables Rules...
Dec 13 21:29:02 fw systemd[1]: Started Homebridge HomeKit bridge.
Dec 13 21:29:02 fw systemd[1]: Starting OpenBSD Secure Shell server...
Dec 13 21:29:02 fw sh[1841]: iptables-restore v1.6.0: host/network 'example.com' not found
Dec 13 21:29:02 fw sh[1841]: Error occurred at line: 24
Dec 13 21:29:02 fw sh[1841]: Try 'iptables-restore -h' or 'iptables-restore --help' for more information.
Dec 13 21:29:02 fw named[1838]: starting BIND 9.10.3-P4-Ubuntu <id:ebd72b3> -f -4 -u bind

Aqui está o arquivo de serviço:

[Unit]
Description=Load iptables Rules
After=bind9.service

[Install]
WantedBy=multi-user.target
WantedBy=network-online.target

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/sh -c "/sbin/iptables-restore < /etc/iptables.up.rules"

Qual é a melhor maneira de executar o comando iptables-restore na inicialização, mas esperar que o named esteja ativo?

    
por user2102964 14.12.2016 / 05:00

1 resposta

2

However, systemd thinks that bind9 is started when it forks, not when named is ready to serve requests

O Systemd não tem outra forma de saber quando o nome está "pronto para atender pedidos". O protocolo comumente aceito, voltando aos dias do SysVinit, é que um daemon bifurca, configura tudo e, uma vez pronto, avisa ao pai que pode sair (geralmente através de um tubo ou sinal). Isto é simples e funciona mesmo que o seu "init" seja um mero script de shell: named; echo Ready!

(Em outras palavras, o systemd não se importa com o processo inicial bifurcando seu filho, mas sobre quando ele sai ).

Existem também outros protocolos possíveis - por ex. se Type = notify for usado, então o daemon deverá enviar uma mensagem READY = 1; com Type = dbus tem que reivindicar um nome no barramento do sistema; etc.

Mas se o named não implementar este protocolo corretamente - ou seja, se o processo inicial sair muito cedo depois de forking - então não há nada que o init possa fazer sobre isso. Não é tarefa do init lidar com daemons que estão mentindo para ele (por incompetência ou de outra forma).

Dito isto, a primeira coisa a fazer seria verificar como o bind9.service realmente funciona. Pode ainda ser que ele não seja executado diretamente, mas através de camadas de scripts init.d, que tendem a causar problemas semelhantes. (Mesmo que os logs não mostrem o prefixo típico "LSB:…" eu verificaria assim mesmo.)

Poderia também ser que bind9.service fosse alterado para Type = simple, que não suporta qualquer notificação de tipo 'ready'! Isso também acontece com frequência quando um mantenedor pega cegamente "systemd diz que o forking é mau" de algum site.

Certifique-se de que bind9.service, na verdade, seja Type = forking (não Type = simple) e que seja executado diretamente (e com as opções necessárias "daemonize").

Se isso não funcionar (ou seja, o nome ainda daemoniza muito cedo), sua única outra opção é ter um serviço segundo que continue verificando a disponibilidade do DNS.

    
por 14.12.2016 / 07:04