OpenVPN auth-user-pass: ficheiro, stdin ou pedido? Como escolher
Escolha entre o pedido na consola, um ficheiro de credenciais, um fluxo e a interface de gestão, e depois corrija os erros que só parecem uma palavra-passe errada.
Três coisas decidem que fonte de credenciais deve usar: se há uma pessoa sentada na consola, se o segredo pode viver no disco e se outro processo tem de responder ao pedido. Se escolher mal, o cliente relata um problema com stdin enquanto a palavra-passe está perfeitamente válida, o que manda a maioria das pessoas para o servidor sem motivo. Escolha primeiro o caminho; as mensagens de erro só fazem sentido depois de saber que caminho as produziu.
As três condições que o decidem
O pedido na consola é o único caminho que precisa de uma pessoa, por isso é o único que falha em silêncio numa unidade systemd ou num contentor. Se uma pessoa inicia o cliente e escreve a palavra-passe, não intervém nenhum ficheiro e nada de sensível acaba no disco. Se o cliente arranca no boot, esse mesmo pedido torna-se um bloqueio, e o tempo limite aparece geralmente como uma falha de ligação genérica em vez de um erro de credenciais.
Um ficheiro de credenciais é a resposta certa quando o processo arranca sem supervisão e o segredo pode sobreviver no disco sob um conjunto de permissões controlado. Quando o segredo não deve ser escrito de todo - uma política só de cofre, um token de curta duração - precisa de um fluxo que o cliente possa abrir, o que na prática significa substituição de processo ou um auxiliar que escreve num descritor de ficheiro. A interface de gestão cobre o quarto caso: um controlador que já gere o ciclo de vida do túnel e pode responder a perguntas por um socket.
- Pessoa na consola, sem automatização: pedido interativo.
- Arranque sem supervisão, o segredo pode ser guardado: ficheiro de credenciais com modo 0600.
- Arranque sem supervisão, o segredo não pode ser guardado: substituição de processo ou um fd escrito por um agente de segredos.
- Outro processo é dono do cliente: interface de gestão.
Quando duas respostas servem, prefira a que mantém o segredo fora de argv e fora do histórico da shell. Uma palavra-passe passada como argumento do programa é legível por qualquer utilizador local através da lista de processos, e essa exposição é difícil de desfazer.
O que cada caminho de entrada faz realmente
--auth-user-pass sozinho pede um nome de utilizador e uma palavra-passe na consola. Com um nome de ficheiro, o cliente toma a primeira linha como nome de utilizador e a segunda como palavra-passe; nada suporta aspas, comentários ou sintaxe chave-valor. É todo o formato, por isso quem o edita à espera de um ficheiro INI estraga-o. Um bloco <auth-user-pass> em linha contém essas mesmas duas linhas dentro do perfil, o que torna o próprio perfil um segredo e o coloca na mesma classe de manuseamento de uma chave privada.
Os outros dois caminhos são um fluxo e um socket. O OpenVPN só precisa de um descritor de ficheiro legível, por isso aceita uma substituição de processo, uma entrada /dev/fd suportada por um pipe ou um nome de ficheiro que na realidade é um FIFO. A interface de gestão é diferente por natureza: o cliente pede os valores a um processo supervisor em vez de os ler sozinho. Essa diferença importa na reconexão: um ficheiro de credenciais, um FIFO no qual um auxiliar de segredos pode voltar a escrever e a interface de gestão podem fornecer de novo sem uma pessoa; a substituição de processo não, porque o descritor é consumido na primeira leitura.
O ficheiro tem de ter exatamente duas linhas
Dois modos de falha cobrem a maioria dos ficheiros de credenciais quebrados. Um editor do Windows deixa finais CRLF, o retorno de carro passa a fazer parte da palavra-passe, e o servidor rejeita um valor que parece correto no ecrã. Uma segunda linha vazia - uma linha vazia onde a palavra-passe deveria estar - deixa o cliente com uma palavra-passe vazia, que o servidor rejeita mesmo que o valor no ecrã pareça correto. Uma nova linha extra depois da palavra-passe é inofensiva. Escreva o ficheiro a partir da shell, não de um editor, e verifique os bytes:
install -m 600 /dev/null /etc/openvpn/client.creds
printf '%s\n%s\n' "$VPN_USER" "$VPN_PASS" > /etc/openvpn/client.creds
od -c /etc/openvpn/client.creds | head -3O caminho importa tanto como o conteúdo. Um caminho relativo é resolvido em relação ao diretório de trabalho do processo, que para um serviço raramente é o diretório onde testou. Use um caminho absoluto, faça o ficheiro pertencer à conta que executa o cliente e mantenha o modo 0600 para que o grupo e os outros não o possam ler. O manual do OpenVPN 2.6 enumera as formas aceites da diretiva; consulte-o antes de inventar uma terceira.
Teste o ficheiro antes de culpar o servidor. Executar openvpn --config client.ovpn --auth-user-pass /etc/openvpn/client.creds --verb 4 imprime se o ficheiro foi aberto e, mais tarde, se as credenciais foram aceites, o que lhe diz que camada alterar a seguir.
Fluxos, stdin e os erros que produzem
Passar a palavra-passe por um pipe é a primeira coisa que a maioria tenta e o caminho com mais surpresas. A substituição de processo funciona porque o cliente só precisa de um descritor legível: openvpn --config client.ovpn --verb 3 --auth-user-pass <(printf '%s\n%s\n' "$VPN_USER" "$VPN_PASS"). Passar /dev/stdin só funciona quando o stdin ainda está aberto e legível no momento em que o cliente pergunta, o que não é verdade num pipeline que já o consumiu.
ERROR: could not read Auth username from stdin tem duas causas distintas. Nalguns clientes 2.3.x a mensagem vinha de um defeito de tratamento de stdin que as versões 2.3 posteriores corrigiram, por isso um cliente tão antigo só melhora ao atualizar. Num cliente atual a mesma formulação significa que o cliente pediu entrada de consola e que o stdin não era um terminal - exatamente a situação numa unidade systemd, numa tarefa cron ou num contentor iniciado sem -t.
auth-nocache acrescenta um terceiro ciclo que parece uma palavra-passe quebrada. Descarta as credenciais da memória após o uso, por isso uma reconexão provocada por uma mudança de rede não tem nada para reproduzir e o pedido regressa. É a diretiva a funcionar como concebida. auth-nocache altera o que o cliente guarda em memória, não o que o servidor ou o fornecedor de identidade pensa da conta, por isso toda a correção é fornecer de novo o mesmo ficheiro, relido no arranque - e para uma ligação gerida esse fornecimento deve vir do armazém de segredos aprovado, não de uma palavra-passe num script.
A interface de gestão quando outro processo é dono do pedido
Um controlador que já supervisiona o túnel também pode responder às suas perguntas. Inicie o cliente com --management 127.0.0.1 7505, leia as linhas de estado e vigie >PASSWORD:Need 'Auth' username/password. O controlador responde com username "Auth" alice seguido de password "Auth" ... em linhas de comando separadas. O token 'Auth' repete o identificador do pedido e tem de coincidir, senão a resposta é ignorada e o cliente espera.
O custo é uma máquina de estados que agora possui: ordem das ligações, reinícios do cliente e um socket local que os outros utilizadores do anfitrião não devem alcançar. O que compra é uma credencial fornecida em tempo de execução, sem ficheiro no disco e sem um pedido que se possa bloquear. Se nada mais na sua pilha já fala o protocolo, este caminho acrescenta um componente para manter.
Falhas que parecem problemas de credenciais
Um aperto de mão TLS que nunca termina, ou um VERIFY ERROR: depth=0, error=certificate signature failure, é um problema de confiança e acontece antes de qualquer nome de utilizador ser lido. Um cliente proto tcp apontado a um ouvinte UDP falha no mesmo ponto: os pacotes nunca chegam à fase de autenticação, por isso todas as palavras-passe parecem erradas por associação. Mantenha a verificação de certificados ligada antes de a credencial ser enviada; um pedido familiar não diz nada sobre quem recebe a palavra-passe. Verifique a cadeia de certificados, o nome comum e o transporte antes de tocar na credencial.
Os erros de shell no script que monta o perfil são o outro rasto falso. Um espaço em falta dentro de [ ! -f "$file" ] produz command not found, o script pára cedo, o perfil nunca é reconstruído e o cliente arranca com o anterior. Esse erro pertence à shell, não à autenticação, e por muito que reescreva a palavra-passe não o apaga.
Nem todo o pedido neste fluxo é esta credencial. Uma frase de acesso de chave privada, um início de sessão de proxy HTTP e a palavra-passe do serviço são três segredos diferentes pedidos em fases diferentes, e uma frase de acesso de chave é normalmente tratada pelo cliente ou por um agente em vez de auth-user-pass. Se o pedido aparece antes de a sessão TLS estar de pé, está a responder à pergunta errada e nenhum reinício de conta ajudará. Uma vez excluído o pedido errado, as verificações restantes começam pela camada mais precoce:
- Leia o primeiro erro de protocolo, não a última linha de credenciais: TLS, depois autenticação, depois push.
- Confirme que o ficheiro tem duas linhas, não contém retornos de carro e é referido por um caminho absoluto.
- Confirme que o perfil e a linha de comando não discordam sobre a diretiva.
- Separe "credenciais aceites" de "o tráfego flui" - o encaminhamento e o DNS são uma camada posterior.
Quando o cliente chega à fase push, deixe de olhar para as credenciais e comece a ler as rotas e os servidores DNS que o servidor enviou. Esse é o próximo problema, e não tem nada a ver com a palavra-passe que acabou de corrigir.