17

首先,请注意我是配置 SSL 的新手。过去,我一直很幸运有一个 IT 部门提前为我设置。因此,请做好准备,我可能需要对您的一些答案进行澄清。=)

我想要做什么

我正在为员工建立一个公司内部网站。例如,将有一个浏览器起始页,显示为每个员工定制的内容。因此,我需要能够在不需要任何用户名/密码或其他提示的情况下识别所述员工(尽管一次性设置是可以的;我只是不希望他们每次都被提示)。当然,SSL 似乎是最好的方法。

我将有一个 MySQL 数据库设置来将“用户”帐户与 SSL_CLIENT_M_SERIAL 和 SSL_CLIENT_I_DN 相关联,我假设每个客户端证书都是唯一的(?)。我从这篇文章中得到了这个想法:http: //cweiske.de/tagebuch/ssl-client-certificates.htm

用户第一次访问内部网站时,他们将没有证书(我不想为客户端手动生成它们!),在这种情况下 $_SERVER["SSL_CLIENT_VERIFY"] == "NONE"。如果发生这种情况,它将转到用户帐户设置页面,其中包括 PHP 生成 SSL 客户端证书并将其发送到浏览器以供用户安装的步骤。很好很简单。然后用户安装证书,建立关联,并在重新启动浏览器后(为了好的措施),用户返回内部网站。

此时,Apache 应该请求客户端证书,然后浏览器发送该证书。然后 PHP 脚本解析必要的 $_SERVER 变量,与 MySQL 数据库进行比较,所有人都度过了美好的时光。再一次,又好又简单。

到目前为止的工作

我安装了服务器端证书。是的,它们是自签名的(原因很明显)。Apache 安装了 mod_ssl,一切似乎都运行良好。我创建了一个 PHP 脚本,它只转储 $_SERVER 数组,并且所有 SSL_SERVER_* 键值都与我为它创建的证书匹配。

问题

我无法让客户端证书工作!在同一个 PHP 脚本中,无论我做什么,都缺少 SSL_CLIENT_VERIFY == "NONE" 和其他 SSL_CLIENT_* 键。如果我在 ssl.conf 中将 SSLVerifyClient 设置为可选,就会发生这种情况。根据我读过的每个教程,他们都说网络服务器应该向浏览器请求客户端证书。问题是,我不能让它这样做!它直接进入 PHP 脚本并假设我根本没有客户端证书。这发生在 Firefox、Chrome 和 IE 中。

所以我尝试将 SSLVerifyClient 设置为 required 并重新启动网络服务器。有了这个选项,我什至无法建立 SSL 连接。Firefox 只是说连接已被重置(其他浏览器也会显示他们自己的错误版本)。奇怪的是日志没有显示这些连接尝试的任何活动!即 access_log、error_log、ssl_access_log、ssl_error_log 和 ssl_request_log 都没有显示任何内容;就好像这种尝试从未发生过。这令人沮丧,因为这意味着我什至没有错误消息可供使用。只是一个网络服务器被动地告诉我下地狱。

我尝试使用 PHP 的 OpenSSL 扩展手动生成/安装我自己的客户端证书。证书安装得很好,虽然我找不到任何关于如何将该证书与服务器相关联的信息(假设我什至需要?)。此外,这似乎并不重要,因为如果设置了 optional,Apache 甚至不会请求客户端证书。如果设置了require,它只会在没有解释的情况下爆炸。无论如何,我都需要将其设置为可选,以使该模式正常工作。

环境

操作系统:CentOS 5.7 64 位(虚拟机)

阿帕奇:2.2.3

PHP: 5.3.10

我猜您可能需要更多信息来帮助我,所以请询问!我会为你提供你需要的任何东西。

总而言之,在上述条件下,我需要知道如何让 Apache 请求 SSL 客户端证书。此外,如果必须执行任何特殊的签名/等操作以使客户端证书与服务器证书“兼容”(同样,无需通过 shell 手动为每个客户端证书执行此操作!),我需要知道这一点出色地。

到目前为止,我 100% 坚持这一点。在 Google 上什至找不到任何有帮助的东西。非常感谢您对此提供的任何帮助!谢谢!=)

4

3 回答 3

5

首先,您需要配置 Apache Httpd 以请求客户端证书。为此,您至少需要在要使用SSLVerifyClient optional此方法进行身份验证的位置/目录上使用。

其次,客户端发送的证书也需要被 Apache Httpd 信任。(您原则上可以使用SSLVerifyClient optional_no_ca,让任何客户端证书通过 Apache Httpd SSL/TLS 堆栈,然后才在 PHP 中验证证书,但这是一项相当多的工作,您需要更加小心,因为这不是必须是简单的代码;更重要的是,在这种情况下这将毫无用处,因为您处于控制 CA 的场景中。)

据我了解,SSL_CLIENT_VERIFY(我自己并没有使用太多的变量)似乎只对SSLVerifyClient optional_no_ca. 它可能适用于SSLVerifyClient optional,但我对此表示怀疑。SSLVerifyClient require将拒绝使用不受信任的客户端证书(由SSLCACertificateFile/中的 CA 之一SSLCACertificatePath)或没有证书的连接。据我所知,SSLVerifyClient optional将让客户端在没有证书或受信任证书的情况下通过,但如果证书不受信任,也会拒绝连接。

在这里,通过拒绝连接,我的意思是突然关闭 SSL/TLS 连接并发出警报。没有机会产生 HTTP(S) 错误页面。所有你会得到标准浏览器错误,类似于ssl_error_unknown_certificate_.... (您应该从可用性的角度考虑这一点。)

从那时起,您需要建立自己的 CA,可能是基于 Web 的,具有浏览器内密钥生成功能,并且位于同一网站内。您不希望SSLVerifyClient require这样做,因为您需要让还没有证书的用户进入(使用optional)。话虽如此,这些指令不必适用于整个主机,但可以特定于某些位置/目录。

如果您不熟悉这一切,那么集成您自己的基于 Web 的 CA(或更一般地说,创建您自己的 CA)并不一定容易。存在现成的工具(例如OpenCA ),或者您可以使用各种JavaScript/ActiveX构建自己的工具,并且您需要服务器端代码来处理 SPKAC 或 PKCS#10 请求(并颁发实际证书) . (为了使这样的 CA 有用,您希望申请新证书的用户在申请时提供一些身份证明,也许是密码。)

设置好后,您应该配置SSLCACertificateFile(或...Path)指向您的内部 CA 的 CA 证书(无论它是否是基于 Web 的 CA,是否在同一站点上)。(当然,保持 CA 的私钥是私有的,可能在基于 Web 的 CA 应用程序中配置,但 Apache Httpd 本身不需要知道它。)浏览器只会建议由这些 CA 或中间机构颁发的证书(除非您还配置SSLCADNRequestFile了 ,它将用于发送接受的 CA 列表)。

请注意,这两个步骤(设置您的 CA 和设置您的网站以使用客户端证书)实际上是独立的。两者都可以是同一站点的一部分这一事实可能很方便,但不是必需的。您可以在不首先在站点上部署整个 CA 的情况下尝试 Apache Httpd 设置(我建议您这样做,即使它只是为了看看您要进入的内容)。有许多工具可以创建您自己的小型 CA,只需少量证书即可管理:例如OpenSSL 的 CA.plTinyCA。您也可以使用这些测试证书(如果您想使用 CRL localhost,则testclient,testclient_r将被撤销,一开始可能不需要):所有密码都是testtest.

正如您已经预料到的(使用您的 MySQL 数据库),您需要管理您颁发的证书并将它们映射到用户。SSL_CLIENT_M_SERIAL并且SSL_CLIENT_I_DN不是正确使用的变量。SSL_CLIENT_I_DN是颁发者 DN(即 CA 的主题 DN)。您要查找的是SSL_CLIENT_S_DN:客户端证书主题 DN。SSL_CLIENT_M_SERIAL是证书序列号:不要使用它,因为它对每个证书都是唯一的:一个用户可以拥有多个具有相同主题 DN 的证书(例如,如果一个过期或被撤销)。


尽管如此,我不确定客户证书是否是实现您目标的最佳方式(让您公司的员工无需密码即可登录)。

  • 首先,用户无论如何都应该使用密码保护自己的证书。我猜你真正想要的是某种形式的单点登录 (SSO)。

  • 其次,根据用户的计算机知识程度,证书实际上可能很难管理。

    严格来说,“证书”一词根本不包括私钥,但有时暗示私钥的使用可能会让某些人感到困惑。一方面,您有时会听到“将您的证书导入浏览器”和“使用您的证书登录”;另一方面,您也可以听到“将您的证书发送给我”。前者意味着私钥的使用和可用性(“证书”可能只是.p12在这些表达中的意思)。后者绝对不应该涉及私钥。

    浏览器用户界面对于管理证书或注销来说往往很差或令人困惑。同样,如果证书未被识别,SSL/TLS 连接将不会建立,因此 Web 服务器没有机会显示任何类型的 HTML 错误页面。

也许您还可以考虑其他形式的 SSO(例如 CAS、基于 SAML 的东西或 Kerberos/SPNEGO。)

于 2012-04-21T01:34:30.513 回答
0

我有一个类似的问题:

  • CentOS 6.3
  • 阿帕奇 2.2.15

经过一些尝试,我认识到我的问题。

如果我设置SSLVerifyClient optionalorSSLVerifyClient optional_no_ca并且我还指定SSLCACertificateFileor SSLCACertificatePath,则 Apache 仅当它从配置中指定的 CA 参考文件/路径中的 CA 释放时才会获取客户端证书。

于 2013-01-25T08:45:05.397 回答
-2

如果尚未完成 ,您可以查看apache 文档。

一般原则是您创建自签名证书并在尝试使用它之前对其进行检查。

然后看起来客户端通过http连接到您的Intranet站点。从那里,有许多不同的方法可以使用您的 ssl 证书切换到 https。最简单的方法是使用 apache rewrite 模块。但是在您的情况下,当您进行 php/mysql 检查时,您可能会将客户端从 http 重定向到 https,这不是简单的方法。

在这两种情况下(通过 mod_rewrite 的 apache 自动重定向,或通过级联测试(php/javascript/html)进行重定向),您需要以正确的方式设置 2 个虚拟主机(一个用于 http,一个用于 https),但这假设一些假设。

例如(debian - apache 2.2),这是一个自动重定向,由 Apache 完成(例如上述第一种情况):

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>

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>

您的情况可能与此略有不同,例如,您不会在第一个虚拟主机中拥有重定向部分,而只有一个简单的虚拟主机和第二个用于 https (ssl) 的虚拟主机。完成 mysql 检查后,重定向将由 php/javascript 完成。

这是一个来自 php 类的示例摘要,用于将切换从 http 级联到 https,使用 php,然后是 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) */

希望它可以帮助您更好地了解如何继续并根据您的具体情况调整这种方法。

于 2012-04-20T21:18:07.563 回答