Um tempo de atividade longo prova apenas que o arranque teve sucesso com os privilégios que o daemon tinha nesse momento. As falhas que aqui importam chegam mais tarde: um novo cliente liga-se, uma lista de revogação é substituída, um script auxiliar precisa de escrever um ficheiro. Cada uma é uma abertura nova feita pela conta sem privilégios, com a sua própria pergunta de permissões e a sua própria mensagem de erro. Três decisões separam uma configuração que continua a funcionar de outra que falha no evento seguinte.

Separe o que foi carregado cedo do que é aberto mais tarde

Um descritor é uma pega sobre uma descrição de ficheiro aberta, e o modo de acesso ficou fixado quando essa descrição foi criada. Mudar o utilizador do processo mais tarde não fecha a pega, e é por isso que um ficheiro de chave lido como root continua a funcionar após a queda. O modo também não muda: uma pega aberta para leitura não passa a ser escritível, e uma pega escritível não é revogada só porque a conta perdeu os direitos sobre o caminho. Estes dois factos explicam a maior parte do comportamento surpreendente nestes relatórios.

A outra metade é memória. O daemon pode analisar um certificado, guardar o material analisado e fechar o ficheiro; o que permanece em uso são dados, não um ficheiro aberto. Por isso o tráfego contínuo não prova nem que um descritor está aberto nem que o nome do caminho é alcançável. Prova apenas que o material necessário à sessão atual foi obtido antes.

Uma abertura posterior é outra transação. Corre sob as credenciais atuais, o contexto de segurança atual e a vista de montagem atual, pelo que um caminho legível no arranque pode ser recusado na ligação seguinte. A rotação acrescenta uma armadilha: escrever um ficheiro novo sobre o mesmo nome de caminho deixa um descritor existente preso ao objeto antigo, pelo que uma recarga pode parecer bem-sucedida enquanto o daemon ainda usa o conteúdo anterior. Compare o inode mantido pelo processo com o que está no disco antes de acreditar numa rotação.

Nomeie as três leituras de execução e quando cada uma ocorre

Três recursos são normalmente abertos muito depois da inicialização, e falham em momentos diferentes. Um ficheiro de configuração específico de um cliente é lido quando esse cliente se liga, pelo que pode quebrar para um utilizador enquanto os restantes continuam. Os dados de revogação são consultados durante a autenticação do par e novamente quando o ficheiro é substituído. Um diretório temporário só é tocado quando um script ou extensão escreve algo.

Nenhum dos três pertence ao caminho de arranque, e é por isso que um servidor saudável durante semanas pode falhar na ligação seguinte. A categoria também nomeia o dono da correção: os dois primeiros são permissões de leitura na configuração sob a conta do daemon, e o terceiro é um local escritível com um propósito estreito.

Path reopened laterWhat triggers the openFirst sign when it fails
Client configuration fileA connection for that client identityOne client rejected while others connect
Revocation dataPeer authentication, including after replacementRevoked and valid peers both refused
Script or plugin temporary directoryA helper needs to create a fileThe helper exits with a path error

persist-key responde a uma pergunta mais estreita do que a maioria supõe. Mantém o ficheiro de chave aberto durante os reinícios documentados SIGUSR1 e ping-restart, e não faz nada pelos ficheiros CCD, pelos dados de revogação, pelos executáveis auxiliares ou por um reinício completo do processo. Esses seguem ainda os seus próprios caminhos de abertura, sob a conta que estiver a correr nesse momento.

Confirme a conta e a vista que ela tem realmente

Pergunte ao daemon em execução que conta usa em vez de confiar no ficheiro de unidade, e depois compare a resposta com o que a unidade define. Uma discrepância é a primeira coisa a resolver, porque cada verificação de permissões posterior corre como quem o processo é de facto. Depois percorra o caminho componente a componente; a travessia é avaliada em cada nível, pelo que um ficheiro legível dentro de um diretório que não se atravessa continua ilegível. O modo final do ficheiro é a última pergunta, não a primeira.

Os espaços de nomes e as caixas de areia de serviço acrescentam fronteiras que a propriedade e os bits de modo não descrevem. Um caminho visível na sua shell pode faltar ou ser só de leitura dentro de um chroot, de um espaço de nomes de montagem ou de uma unidade que esconde os diretórios pessoais. Os módulos de segurança acrescentam mais uma camada, pelo que um ficheiro que parece legível pode ainda ser negado ao ser aberto.

ps -o user:12,pid,args -C openvpn
systemctl show -p User -p Group -p ProtectHome -p RootDirectory [email protected]
sudo -u openvpn namei -l /etc/openvpn/ccd/alice

Uma leitura bem-sucedida na shell do administrador não testa nenhuma dessas condições combinadas. Execute a verificação como a conta do daemon, com o mesmo espaço de nomes e a mesma caixa de areia, ou aceite que o resultado descreve a sua shell e não o servidor. O terceiro comando é a versão barata desse teste: imprime o modo de cada componente e falha no primeiro que a conta do daemon não consegue atravessar.

Dê à escrita de execução um diretório próprio

A leitura é apenas metade do inventário. Um script auxiliar pode precisar de criar um ficheiro de estado, uma extensão pode precisar de escrever estado ao lado da sua configuração, e essas escritas não são cobertas por tornar a árvore de configuração escritível. Dê ao diretório concreto a permissão de escrita de que a sua função precisa, com um dono e um modo que consiga explicar. Prefira o acesso só de leitura para tudo o que apenas é lido.

Mantenha as permissões da chave privada separadas dos ficheiros de política. Uma chave que tem de ser relida após um reinício tem um requisito diferente de um ficheiro de cliente lido em cada ligação, e um único modo permissivo para ambos dá mais acesso do que o problema pede. Uma conta de daemon dedicada com propriedade estreita é mais fácil de auditar do que um grupo largo. Quando a chave tem de sobreviver aos reinícios, persist-key elimina a releitura em vez de alargar o diretório.

Decida a partir do evento que consegue reproduzir

Um túnel ativo prova um único caminho pelo código. O evento que precisa do ficheiro é o único teste que cobre a abertura que lhe interessa, seja uma nova ligação de cliente, um ficheiro de revogação substituído, um reinício suave permitido ou um reinício planeado. Escolha o evento, execute-o e guarde o primeiro erro em vez do último.

Para um reinício suave, um sinal e o registo da unidade mostram se a chave foi relida. Envie o sinal e depois leia as últimas linhas que a unidade escreveu:

systemctl kill -s SIGUSR1 [email protected]
journalctl -u [email protected] -n 40 --no-pager

Não conclua que um daemon comprometido já não pode alterar ficheiros só porque os privilégios foram reduzidos. O que ainda pode depende das credenciais restantes, das suas capacidades, dos diretórios em que pode escrever e de qualquer descritor escritível que ainda detenha. A redução de privilégios estreita a autoridade, e o inventário das aberturas de execução mostra até onde. Escreva essa fronteira ao lado da configuração para que a próxima pessoa não tenha de a redescobrir.

Artigos relacionados