2012-04-20 48 views
13

En primer lugar, tenga en cuenta que soy nuevo en la configuración de SSL. En el pasado, siempre tuve la suerte de contar con un departamento de TI que me lo preparó con anticipación. Así que prepárate para la posibilidad de que necesite pedir una aclaración sobre algunas de tus respuestas. =)Apache no solicitará mi certificado de cliente SSL

Lo que estoy tratando de hacer

Soy la creación de una página web en intranet de la compañía para los empleados. Por ejemplo, habrá una página de inicio del navegador que muestra contenido personalizado para cada empleado. Como tal, debo ser capaz de identificar a dicho empleado sin necesidad de ningún nombre de usuario/contraseña u otra sugerencia (la configuración de una sola vez está bien, simplemente no quiero que se me solicite cada vez). Naturalmente, SSL parece ser la mejor manera de hacerlo.

Voy a tener una configuración de base de datos MySQL para asociar cuentas de "usuario" con SSL_CLIENT_M_SERIAL y SSL_CLIENT_I_DN, que asumo será único para cada certificado de cliente (?). Obtuve esa idea de este artículo: http://cweiske.de/tagebuch/ssl-client-certificates.htm

La primera vez que el usuario va al sitio web interno, no tendrá un certificado (¡NO quiero generarlos manualmente para los clientes!), En cuyo caso $ _SERVER ["SSL_CLIENT_VERIFY"] == "NINGUNO". Si eso sucede, irá a la página de configuración de la cuenta del usuario, que incluirá un paso donde PHP genera un certificado de cliente SSL y lo envía al navegador para que el usuario lo instale. Agradable y simple. Luego, el usuario instala el certificado, se establece la asociación y luego de reiniciar el navegador (como medida), el usuario regresa al sitio web interno.

En este punto, Apache debe solicitar el certificado del cliente, que luego el navegador envía. El script PHP analiza las variables $ _SERVER necesarias, se compara con la base de datos MySQL, y todos disfrutan de buenos momentos. De nuevo, agradable y simple.

lo que está funcionando hasta ahora

que tienen los certificados de servidor instalados. Y sí, son autofirmados (por razones obvias). Apache tiene instalado mod_ssl y todo eso parece estar funcionando bien. Creé un script PHP que simplemente volca el array $ _SERVER, y todos los valores de la clave SSL_SERVER_ * coinciden con el certificado que creé para él.

El problema

no puedo obtener los certificados de cliente para trabajar! En ese mismo script PHP, no importa lo que haga, SSL_CLIENT_VERIFY == "NONE" y las otras claves SSL_CLIENT_ * faltan. Esto es lo que sucede si SSLVerifyClient se establece como opcional en ssl.conf. De acuerdo con cada tutorial que he leído, todos dicen que el servidor web debería pedirle al navegador un certificado de cliente. La cosa es que no puedo hacer que haga eso. Simplemente va directo al script PHP y asume que no tengo ningún certificado de cliente. Esto sucede en Firefox, Chrome e IE.

Intenté configurar SSLVerifyClient como requerido y reinicié el servidor web. Con esa opción en su lugar, ni siquiera puedo establecer una conexión SSL. Firefox solo dice que la conexión se ha restablecido (otros navegadores también muestran sus propias versiones de ese error). ¡Lo extraño es que los registros no muestran CUALQUIER actividad en estos intentos de conexión! Es decir. access_log, error_log, ssl_access_log, ssl_error_log, Y ssl_request_log no muestran NADA; es como si el intento nunca hubiera ocurrido. Esto es frustrante porque significa que ni siquiera tengo un mensaje de error para trabajar. Solo un servidor web pasivo-agresivo diciéndome que vaya al infierno.

Intenté generar/instalar mi propio certificado de cliente manualmente utilizando la extensión OpenSSL de PHP. El certificado se instaló muy bien, aunque no puedo encontrar ninguna información sobre cómo asociar ese certificado con el del servidor (suponiendo que incluso tenga que hacerlo). Además, no parece importar de todos modos, ya que Apache aún no solicitará un certificado de cliente si se configura opcional. Y si se establece require, simplemente explota sin explicación. Necesito que se configure de manera opcional para que este esquema funcione.

El Medio Ambiente

OS: CentOS 5.7 de 64 bits (VirtualBox)

Apache: 2.2.3

PHP: 5.3.10

Te estoy adivinando podría Necesito más información para ayudarme, así que por favor pregunte. Te proporcionaré lo que necesites.

Para resumir, necesito saber cómo lograr que Apache solicite un certificado de cliente SSL dadas las condiciones descritas anteriormente. Además, si hay alguna firma/etc especial que deba hacerse para que el certificado del cliente sea "compatible" con el certificado del servidor (¡nuevamente, SIN hacerlo manualmente a través del intérprete de comandos para cada certificado de cliente!), Tendré que saberlo como bien.

Estoy 100% atrapado en esto a partir de ahora. No se puede encontrar nada remotamente útil en Google. ¡Cualquier ayuda que pueda brindarle será TESTIMONIALMENTE apreciada! ¡Gracias! =)

+0

¿Cada certificado de cliente generado es autofirmado? ¿O creaste tu propia CA para firmar las solicitudes generadas? El cliente solo le solicitará un certificado si tiene uno instalado que está firmado por una autoridad de confianza (que está determinado por el almacén de confianza del servidor). Si cada certificado de cliente es autofirmado, necesitaría que cada uno de esos certificados generados esté en el almacén de confianza del servidor, lo que no sería factible. – bobz32

+0

Intenté crear un certificado de cliente en el servidor usando openssl, exportando como p12, luego instalándolo en Firefox, pero ahora obtengo un error "no se puede obtener el certificado de emisor local" de Apache. Firmé el certificado del cliente usando el certificado del servidor, entonces, ¿por qué no funciona? Intenté descomentar la línea SSLCACertificateFile en ssl.conf, pero eso me devolvió al primer problema, que era la página cargada, pero sin reconocer el certificado del cliente. Así que una vez más vuelvo al punto de partida ... –

Respuesta

0

Puede echarle un vistazo al apache doc si no lo ha hecho ya.

El principio general es que cree su certificado autofirmado y lo verifique antes de intentar usarlo.

Parece que el cliente se conecta a su sitio de intranet a través de http. A partir de ahí, hay muchas maneras diferentes de cambiar a https usando su certificado ssl. La forma más fácil es usar el módulo de reescritura de apache. Pero en su caso, mientras realiza comprobaciones de php/mysql, puede redirigir a su cliente de http a https, que no es la manera más simple.

En cualquiera de los dos casos (apache automático de redirección a través de mod_rewrite, o redirección mediante pruebas en cascada (php/javascript/html), debe configurar sus 2 fantasmas (uno para http y uno para https) de la manera correcta , pero esto supone alguna hipótesis

por ejemplo (debian - Apache 2.2), aquí es una redirección automática, hecho por Apache (por ejemplo, primero caso descrito anteriormente):.

cat/etc/apache2/sites-available/test

# VHOST test 

<VirtualHost *:80> 

    DocumentRoot /home/www/test 
    ServerName www.test.dev 

    # ###################### 
    # Redirect commons 
    # ###################### 
    RewriteEngine on 
    # Case of vhosts 
    RewriteOptions Inherit 

    # ###################### 
    # Redirect (empty index) 
    # ###################### 

    # Condition 1 to redirect : request matching with the server 
    RewriteCond %{HTTP_HOST} ^www\.test\.dev [NC] 

    # Condition 2 to redirect : non empty HOST 
    RewriteCond %{HTTP_HOST} !^$ 

    # Automatic Empty requests Redirect 
    RewriteRule ^(.*)/$ /index.php 


    # ###################### 
    # Redirect to SSL 
    # ###################### 
    RewriteCond %{HTTP_HOST} ^www\.test\.dev [NC] 
    RewriteCond %{HTTP_HOST} !^$ 
    RewriteCond %{SERVER_PORT} ^80$ 
    RewriteCond %{REQUEST_URI}/

    # Redirection 
    RewriteRule ^/(.*)$ https://%{SERVER_NAME}%{REQUEST_URI} [L,R] 

</VirtualHost> 

El segundo host virtual fo r SSL: cat/etc/apache2/sites-available/test-ssl

# VHOST for ssl 

DocumentRoot "/home/www/test" 
ServerName www.test.dev 

    # SSL 
    SSLEngine on 
    SSLCACertificateFile /etc/apache2/ssl/cur_cert/ca.pem 
    SSLCertificateFile /etc/apache2/ssl/cur_cert/serveur.pem 
    SSLCertificateKeyFile /etc/apache2/ssl/cur_cert/serveur.key 


    <Directory "/home/www/test"> 
     Options FollowSymLinks MultiViews 
     AllowOverride None 
     Order allow,deny 
     Allow from 127.0.0.1 192.168.0.0/16 
    </Directory> 


    <Directory "/home/www/test/cgi-bin"> 
     Options FollowSymLinks MultiViews 
     AllowOverride None 
     Order allow,deny 
     Allow from 127.0.0.1 192.168.0.0/16 
     Options +ExecCGI 
     AddHandler cgi-script .cgi 
    </Directory> 

</VirtualHost> 

Su caso podrían diferir ligeramente de esto, por ejemplo, que no tendrá la porción redirigida en el primer vhost, pero solo un vhost simple y el segundo para https (ssl).La redirección se realizará mediante php/javascript una vez que haya logrado sus comprobaciones de mysql.

Aquí es un ejemplo abstracto de una clase PHP para la manera de conectar en cascada el interruptor de http a https, utilizando php, a continuación, JavaScript, HTML:

public function Redirect($url){ 

    if (TRUE !== Validator::isValidURL($url)) 
     die ("FATAL ERR: url not valid"); 

    // PHP ABSOLUTE URL REDIRECT (HTTP1.1) 
    if (!headers_sent()) { 

     header("Status: 200"); 
     header("Cache-Control: no-cache, must-revalidate"); // required for HTTP/1.1 
     header("Expires: Sat, 26 Jul 1997 05:00:00 GMT"); // past Date 
     header("Pragma: no-cache"); 
     header('Location: '.$url); // note: 302 code return by default with "Location" 
     flush(); 
     exit(); 

     // if headers are already sent... do javascript redirect... if javascript is disabled, do html redirect. 
    } else { 

     // Js redirect 
     echo '<script type="text/javascript">'; 
     //echo "<!--"; 
     echo 'document.location="'. $url .'";'; 
     //echo "//-->"; 
     echo '</script>'; 

     // HTML redirect if js disabled 
     echo '<noscript>'; 
     echo '<meta http-equiv="refresh" content="0;url="'.$url.'" />'; 
     echo '</noscript>'; 

     exit(); 
    } 

    return FALSE; 

} /* end of method (redirect) */ 

espero que le ayuda a comprender mejor la forma de proceda y adapte este enfoque a su caso específico.

+0

Pero el problema que estoy teniendo no es con respecto a la redirección. Estoy accediendo a la página directamente a través de https. Es decir. en el navegador, estoy usando https: //. Entonces el puerto 80 no está en cuestión. –

+0

Intenté crear un certificado de cliente en el servidor usando openssl, exportando como p12, luego instalándolo en Firefox, pero ahora obtengo un error "no se puede obtener el certificado de emisor local" de Apache. Firmé el certificado del cliente usando el certificado del servidor, entonces, ¿por qué no funciona? Intenté descomentar la línea SSLCACertificateFile en ssl.conf, pero eso me devolvió al primer problema, que era la página cargada, pero sin reconocer el certificado del cliente. –

+0

Lo siento, entiendo mejor su punto ahora y no tengo otra solución simple que conectar http y conmutar https una vez que se hayan hecho las comprobaciones de mysql después del inicio de sesión, lo que parece un enfoque más seguro para mí pero un gran consumidor de código por experiencia. – hornetbzz

4

En primer lugar, debe configurar Apache Httpd para solicitar un certificado de cliente. Para esto, necesita al menos usar SSLVerifyClient optional en la ubicación/directorio que desea autenticar con este método.

En segundo lugar, los certificados enviados por el cliente tiene que ser de confianza por Apache Httpd también. (Se podría en uso principio SSLVerifyClient optional_no_ca, dejar que ningún certificado de cliente a través de la pila de Apache Httpd SSL/TLS, y sólo entonces verificar el certificado dentro de PHP, pero eso es un poco de trabajo, para el que necesita ser un poco más cuidadoso ya que es código no necesariamente fácil, más importante, esto sería bastante inútil en este contexto, ya que estás en un escenario donde tienes el control de tu CA.)

Por lo que tengo entendido, SSL_CLIENT_VERIFY (una variable que No he usado mucho) parece realmente útil con el SSLVerifyClient optional_no_ca. Podría funcionar con SSLVerifyClient optional, pero lo dudo. SSLVerifyClient require rechazarán las conexiones que utilizan un certificado de cliente que no es de confianza (por una de las entidades emisoras de SSLCACertificateFile/SSLCACertificatePath), o si no hay ningún certificado. Por lo que sé, SSLVerifyClient optional dejará pasar al cliente sin un certificado o con un certificado de confianza, pero también rechazará la conexión si el certificado no es de confianza.

Aquí, rechazando la conexión, me refiero a cerrar la conexión SSL/TLS abruptamente con una alerta. No hay posibilidad de generar una página de error HTTP (S). Todo lo que obtendrá en el error estándar del navegador, algo similar a ssl_error_unknown_certificate_.... (Debe considerar esto en términos de usabilidad).

A partir de ese momento, lo que necesita es configurar su propia CA, posiblemente basada en la web con generación de claves dentro del navegador y dentro del mismo sitio web. No querría SSLVerifyClient require para eso, porque tendría que permitir que los usuarios que todavía no tienen un certificado (en su lugar, usen optional). Dicho esto, estas directivas no necesitan aplicarse a todo el host, pero pueden ser específicas para ciertas ubicaciones/directorios.

La integración de su propia CA basada en la web (o más en general, la creación de su propia CA) no es necesariamente fácil si eres nuevo en todo esto. Existen herramientas ya preparadas (por ejemplo OpenCA), o usted puede construir su propio uso de varios bits de JavaScript/ActiveX, y podría necesitar el código del lado del servidor para manejar el SPKAC o PKCS # 10 solicitudes (y para emitir el certificado real). (Para que una CA sea útil, querría que los usuarios que solicitan un nuevo certificado proporcionen alguna prueba de identificación en el momento de la solicitud, tal vez una contraseña).

Cuando se configura esto, debe configure SSLCACertificateFile (o ...Path) para apuntar al certificado CA de su CA interna (ya sea una CA basada en web o no, en el mismo sitio o no). (Por supuesto, mantener la clave privada de la entidad de certificación privada, tal vez configurado dentro de la aplicación basada en Web de CA, pero sí Apache Httpd no necesita saber acerca de ella.) Los navegadores sólo se sugerirá certificados emitidos por dichas entidades emisoras o intermedios (a menos también ha configurado SSLCADNRequestFile, que se usaría para enviar la lista de CA aceptadas en su lugar).

Tenga en cuenta que estos dos pasos (la configuración de la CA y la creación de su sitio web para uso de los clientes certificados) realmente son independientes de hecho.El hecho de que ambos puedan ser parte del mismo sitio puede ser conveniente, pero no es necesario. Puede probar la configuración de Apache Httpd sin implementar primero una CA completa en el sitio (lo recomendaría, incluso si solo fuera para ver en qué se está metiendo). Hay una serie de herramientas para crear su propia pequeña CA que son manejables con un puñado de certificados: OpenSSL's CA.pl o TinyCA por ejemplo. También puede utilizar estos test certificates (localhost y testclient, testclient_r se revocó si desea utilizar la CRL, probablemente no necesaria al principio): todas las contraseñas son testtest.

Como ya lo anticipó (con su base de datos MySQL), necesitará administrar los certificados que emite y asignarlos a los usuarios. SSL_CLIENT_M_SERIAL y SSL_CLIENT_I_DN no son las variables correctas para usar, sin embargo. SSL_CLIENT_I_DN es el DN del emisor (es decir, el DN del sujeto de la CA). Lo que usted estaría buscando es SSL_CLIENT_S_DN: el certificado del cliente Asunto DN. SSL_CLIENT_M_SERIAL es el número de serie del certificado: no lo use, ya que es único por certificado: un usuario podría tener varios certificados con el mismo DN de sujeto (por ejemplo, si uno caduca o es revocado).


A pesar de todo esto, no estoy seguro de si los clientes certificados son la mejor manera de lograr su objetivo (dejando que los empleados en su empresa iniciar sesión sin contraseña).

  • En primer lugar, el usuario debe proteger sus propios certificados con una contraseña de todos modos. Lo que realmente buscas es algún tipo de inicio de sesión único (SSO), supongo.

  • En segundo lugar, dependiendo del grado de alfabetización informática de los usuarios, los certificados pueden ser bastante difíciles de administrar.

    El hecho de que la palabra "certificado", estrictamente hablando, no incluya la clave privada en absoluto, pero a veces implica el uso de la clave privada puede ser confusa para algunos. Por un lado, a veces escuchas "Importar tu certificado en tu navegador" y "Usa tu certificado para iniciar sesión"; por otro lado, también puede escuchar "envíeme su certificado". El primero implica el uso y la disponibilidad de la clave privada ("certificado" podría significar .p12 en estas expresiones). El último definitivamente no debería involucrar la clave privada.

    Las interfaces de usuario del navegador tienden a ser bastante pobres o confusas para gestionar los certificados o cerrar la sesión. De nuevo, si no se reconoce el certificado, no se establecerá la conexión SSL/TLS, por lo que el servidor web no tendrá la oportunidad de mostrar una página de error HTML de ningún tipo.

Tal vez usted también podría considerar otras formas de SSO (Kerberos/SPNEGO por ejemplo, CAS, algo SAML basado en o.)

0

Tengo un problema similar con:

  • CentOS 6.3
  • Apache 2.2.15

Después de algunos intentos reconozco mi problema.

Si fijo o SSLVerifyClient optionalSSLVerifyClient optional_no_ca y especifico también SSLCACertificateFile o SSLCACertificatePath, Apache adquiere el certificado de cliente sólo si se libera de CA CA encuentra en la referencia de archivo/ruta especificada en la configuración.

Cuestiones relacionadas