Hook client-connect de OpenVPN: onde vai realmente o teu enderezo
Un script client-connect non pode devolver un enderezo imprimíndoo. Vexa como o ficheiro temporal do hook, o estado de saída e a topoloxía deciden o IP do cliente.
Devolver un enderezo desde un script client-connect parece que debería establecer o IP do cliente. Non o fai: a única canle do hook cara ao servidor é un ficheiro temporal cuxa ruta chega como último argumento do script, e o enderezo debe escribirse alí coa sintaxe de ifconfig-push. Un script que imprime o enderezo ou sae con cero sen escribir nada produce un cliente conectado cun enderezo do pool, e o rexistro do servidor parece perfectamente san.
A confusión é razoable, porque varios outros hooks si responden mediante códigos de saída ou variables de contorno. Este ten o seu propio contrato, e o contrato comeza cun nome de ficheiro.
O hook escribe un ficheiro, non un valor de retorno
A declaración son dúas liñas: script-security 2 para permitir a chamada, e despois client-connect /etc/openvpn/server/assign-address.sh. Cando un cliente se autentica, o servidor executa ese script coa ruta do ficheiro xerado engadida como último argumento, que é $1 só se a declaración non pasa argumentos adicionais propios. Todo o que se aplica a ese cliente vai nese ficheiro como directivas ordinarias, unha por liña, exactamente como aparecerían nunha configuración. Un envoltorio que engade os seus propios parámetros despraza a posición, e o síntoma clásico é un script que escribe nunha ruta que parece --verbose.
O estado de saída é a outra metade do contrato. Cero significa aceptar e ler o ficheiro; calquera outra cousa rexeita a conexión, e así é como unha identidade non asignada se denega en lugar de volver silenciosamente ao pool. Escribe a directiva completa antes de devolver éxito, para que un ficheiro a medio escribir nunca se converta na configuración dun cliente.
Dúas directivas merecen atención porque interactúan con todo o demais. ifconfig-push fixa o enderezo, mentres que unha route enviada indica ao cliente que é alcanzable a través do túnel; devolve a primeira e esquece a segunda e obtés un cliente con enderezo e sen sitio a onde ir. A orde dentro do ficheiro non importa, pero a integridade si. Un hook que envía unha ruta para un prefixo ao que ningún par pode chegar é o mesmo erro visto desde o outro extremo.
As entradas chegan por variables de contorno: common_name, trusted_ip, ifconfig_pool_remote_ip e o resto. Trátaas todas como cadeas de fóra do servidor, nunca como fragmentos de shell.
O mapeo de enderezos é unha política, non aritmética
Un atallo tentador é analizar o nome do certificado e usar os seus díxitos como último octeto. Iso non é un asignador, e falla de formas correntes: dous nomes co mesmo sufixo colisionan, un nome que acaba en 300 non é un enderezo, e un certificado renomeado por un administrador move un dispositivo en silencio. Valida a pertenza á subrede, o rango de hosts utilizábel, os enderezos reservados e a unicidade en cada chamada, e mantén o mapeo nunha táboa que unha persoa poida ler.
Quen controla o nome controla o enderezo, así que decide que representa realmente common_name neste despregamento. Con username-as-common-name activado, a identidade é o inicio de sesión e non o suxeito do certificado. Nunca pases ese valor á avaliación do shell, e nunca deixes que o cliente inflúa nunha ruta de ficheiro.
Un asignador apoiado nun rexistro debe sobrevivir á concorrencia. Reserva o enderezo de forma atómica, xestiona unha escritura fallida sen admitir un cliente a medio configurar, e etiqueta cada asignación coa conexión que a posúe, para que unha desconexión tardía dunha sesión antiga non poida liberar un enderezo que unha máis nova xa ten. Varias instancias de servidor que comparten un pool fan ese requisito máis agudo, non opcional.
A topoloxía decide que significa ifconfig-push
Con topology subnet en 10.77.0.0/24, ifconfig-push 10.77.0.20 255.255.255.0 é un enderezo máis a súa máscara de rede. Baixo topology net30 o segundo argumento non é ningunha máscara senón o enderezo do par, así que copiar a forma de subrede nun servidor net30 dálle un cliente que se asocia e non pode pasar tráfico. Cambia a topoloxía a propósito, nunca para que un exemplo pareza coherente. Un servidor que xa funciona con net30 ten clientes vivos no enderezamento antigo, así que o cambio é unha migración cunha ventá de mantemento, non unha edición dunha liña.
Os enderezos estáticos deben quedar fóra do pool dinámico e fóra de calquera outra asignación estática, incluídas as que reparten os ficheiros client-config-dir ordinarios. Se dous mecanismos poden producir o mesmo enderezo para clientes distintos, un deles acabará facéndoo.
Proba catro casos antes de confiar nel
Executa as mesmas comprobacións contra unha identidade asignada, unha non asignada, unha reconexión e un fallo de rexistro simulado. openvpn --config client.ovpn --verb 4 mostra o enderezo asignado na resposta push, e no servidor grep -A2 PUSH_REPLY /var/log/openvpn/openvpn.log confirma o que se enviou realmente. Para a identidade non asignada o resultado esperado é unha conexión rexeitada, non un enderezo do pool.
Despois inspecciona o directorio no que o demo escribe eses ficheiros temporais. O script execútase no contexto de servizo degradado, así que unha ruta escribíbel por root pero non polo demo converte cada conexión nun rexeitamento cun erro de permisos enterrado varias liñas máis abaixo no rexistro.
Asignar non é autorizar: un enderezo fixado segue sen dar acceso a cada destino detrás do servidor. Mantén a política de encamiñamento e devasa na súa propia capa, e verifícaa contra o enderezo que acabas de fixar.