RAND_bytes() failed é unha afirmación sobre unha primitiva local, non sobre a conta, a chave precompartida ou o porto remoto. Dous fallos moi distintos producen esa mesma liña e deixan probas diferentes. Un é un motor criptográfico que se nega a emitir bytes; o outro é un proceso que non chega á fonte de entropía para a que se compilou o seu código. Sepalalos esixe unha lectura da cola de erros e unha ollada á vista do sistema de ficheiros do propio proceso encaixado, e esa comprobación vai antes de crear calquera cousa baixo /dev.

Que distingue o valor de retorno

O contrato documentado separa tres resultados, non dous: 1 para o éxito, -1 cando o método RAND cargado non admite a petición, e 0 para os demais fallos, coa explicación reservada á cola de erros. A referencia de RAND_bytes engade un punto fácil de pasar por alto: o xerador predeterminado ségaa desde o sistema operativo nas plataformas compatibles, e cando esa semente falla queda nun estado de erro en vez de devolver bytes previsibles.

Só un deses números describe a contorna. Un -1 é unha cuestión de compilación, de provedor ou de funcionalidade, porque o código pediu algo que a implementación activa non ofrece. Un 0 cunha queixa de semente é unha cuestión de contorna, porque o xerador non puido obter entropía de ningún xeito. O número por si só nunca di cal dos dous, e o nome da función tampouco.

Cando un nodo de dispositivo oculto é a causa real

Un servizo confinado ve unha árbore distinta da do shell no que está a escribir. As jaulas chroot, as imaxes de contedor e as unidades endurecidas presentan habitualmente un /dev con menos nodos có do anfitrión. Se a implementación que falla abre /dev/urandom pola ruta, esa diferenza abonda para romper o arranque mentres o anfitrión parece perfectamente san. Un dispositivo que existe fóra da jaula non demostra nada sobre o que o proceso encaixado ten permiso de abrir.

Non toda interface aleatoria necesita unha ruta, con todo. A chamada ao sistema getrandom de Linux non acepta ningún nome de ficheiro nin descriptor de ficheiro, e a súa páxina de manual sinala que esa propiedade é útil precisamente onde un chroot oculta as rutas dos dispositivos.

Así que a explicación do nodo ausente é unha hipótese sobre unha rama do código, non unha regra sobre os números aleatorios en xeral. Mantense cando as probas nomean unha ruta, e é conxectura cando as probas nomean outra cousa.

Le a cola de erros e despois a vista do proceso

A forma máis rápida de resolver a cuestión é ler o que a biblioteca xa rexistrou e logo mirar directamente a vista encaixada. Comeza por a compilación de OpenSSL que o servizo cargou realmente, porque as pilas de provedores difiren entre versións maiores e entre distribucións. Pregunta despois a systemd que proceso se está executando e que restricións se lle aplican. Só cando ambos os feitos están sobre a mesa paga a pena listar os nodos que ese proceso pode ver.

openssl version -a
systemctl show openvpn-server@lab -p MainPID -p PrivateDevices -p DevicePolicy
pid=$(systemctl show -p MainPID --value openvpn-server@lab)
sudo ls -l /proc/"$pid"/root/dev/urandom /proc/"$pid"/root/dev/random

Executa esas lecturas contra o mesmo proceso, non contra o shell que resulte estar aberto. Comparar o /dev do anfitrión coa vista dun proceso alleo é como se repara dúas veces a dependencia equivocada.

Engade a dependencia só cando poidas nomeala

Cando as probas si nomean unha ruta, a reparación é pequena: deixa dispoñible esa única ruta dentro da jaula e non toques nada máis. Unha montaxe bind do nodo único adoita abondar, e mknod cos números maior e menor estándar do nodo produce o mesmo resultado en instalacións onde a montaxe non é unha opción. Ampliar a caixa de area, conceder acceso a todos os dispositivos de caracteres ou desactivar PrivateDevices cambia unha corrección puntual por unha regresión de seguridade permanente.

Un daemon de entropía non substitúe esa reparación. Paquetes como haveged cambian como se alimenta o pool do núcleo; non poden crear unha ruta que un proceso encaixado teña permiso de abrir. Instalar un pode facer que un gráfico de saúde se vexa mellor mentres a chamada de apertura segue fallando. Mantén os dous problemas separados, ou o seguinte fallo volverá atribuírse á capa equivocada.

Verifica o xerador e o túnel por separado

Un reinicio é a única proba que reutiliza a mesma configuración, o mesmo ficheiro de unidade e o mesmo confinamento que produciron o fallo. Execútao e logo le as entradas máis recentes do diario en lugar dunha mostra dun arranque anterior.

sudo systemctl restart openvpn-server@lab
sudo journalctl -u openvpn-server@lab --since -5min --no-pager | grep -iE 'rand|entropy|Initialization Sequence'

Busca dúas cousas separadas nesa saída: a mensaxe sobre a fonte aleatoria que desaparece e o túnel que acada o seu fito habitual de arranque. Un xerador que volve funcionar elimina un fallo local e non di nada sobre a identidade do servidor, as credenciais ou o encamiñamento. Proba iso coa mesma configuración de cliente que fallaba antes, para que o resultado sexa comparable e non só mellor.

Artigos relacionados