zoukankan      html  css  js  c++  java
  • 搭建私有CA并基于OpenSSL实现双向身份认证

    0x00 前言

    互联网上的Web应用由于用户数目广泛,都是采用单向身份认证的,只需要客户端验证服务端的身份。但如果是企业内部的应用对接,客户端数量有限,可能就会要求对客户端也做身份验证,这时就需要一个双向认证方案。本文通过搭建私有CA,利用OpenSSL工具,实现服务端与客户端的双向身份认证。安全协议采用HTTPS,这里用到的HTTPS除了能够进行身份认证以外,还能保证通信的保密性和完整性。

    0x01 组建方案

    组建方案如下图所示:

    • 整个方案包括一个私有CA、一个服务端、一个客户端,用于验证HTTPS双向身份认证的可行性。
    • 服务端的系统环境为CentOS7,Web服务器采用Tomcat7。客户端的系统环境为Windows,浏览器采用Firefox。
    • 由私有CA负责生成所有的私钥、证书等文件,并通过线下安全途径分发到服务端和客户端。
    • 其中,CA的私钥最为重要需加密后离线保管;服务端持有CA证书、服务器私钥、服务器证书3个文件;客户端持有CA证书、客户端私钥、客户端证书3个文件。
    • 客户端与服务端通过HTTPS安全协议进行双向身份认证、加密传输。另外,需要注意的是,HTTPS实现的是传输层的身份认证,不含应用层鉴权功能。

    0x02 私有CA的设置

    安装与配置OpenSSL

    安装OpenSSL

    yum install openssl
    yum install openssl-devel

    OpenSSL默认安装完后,另外需要创建以下几个文件: 

    touch /etc/pki/CA/index.txt       #index文件用于记录已经签发的证书
    touch /etc/pki/CA/serial
    echo 00 > /etc/pki/CA/serial      #serial文件用于存放证书的序列号,自动递增

    完成该实验后index.txt中的信息为下面两条,即签发了两个证书分别是服务端证书和客户端证书

    因为,服务器证书请求文件的国家、省、市要和CA证书一致,这个在openssl.cnf默认配置中指定了。
    可以通过修改/etc/pki/tls/openssl.cnf文件,调整为非强制一致。
    将下面的几个match 修改为 optional

    # For the CA policy  
    [ policy_match ]
    countryName             = match
    stateOrProvinceName     = match
    organizationName        = match

    自签CA证书

    生成根证书私钥 cakey.pem

    openssl genrsa  -des3 -out cakey.pem  2048 这一步需要输入密码,密码用于加密私钥,使私钥非明文存于磁盘  

    生成根证书签发申请文件 ca.csr

    openssl req -new -key cakey.pem -out ca.csr -subj "/C=CN/O=CAorganization/CN=myCA"

    自签发根证书 cacert.pem

    openssl x509 -req -days 3650 -sha256 -extensions v3_ca -signkey cakey.pem -in ca.csr -out  cacert.pem  

    服务端的私钥与证书

    生成服务端私钥 serverkey.pem

    openssl genrsa -out serverkey.pem 2048  

    生成证书请求文件 server.csr

    openssl req -new 
    -sha256 
    -key serverkey.pem 
    -subj "/C=CN/ST=myprovince/L=mycity/O=myorganization/OU=mygroup/CN=myserver.test.com" 
    -reqexts SAN 
    -config <(cat /etc/pki/tls/openssl.cnf 
        <(printf "[SAN]
    subjectAltName=DNS:myserver.test.com,DNS:myserver2.test.com")) 
    -out server.csr  

    使用根证书签发服务端证书 servercert.pem

    openssl ca -in server.csr 
    -md sha256 
    -days 3650 
    -keyfile cakey.pem 
    -cert cacert.pem 
    -extensions SAN 
    -config <(cat /etc/pki/tls/openssl.cnf 
        <(printf "[SAN]
    subjectAltName=DNS:myserver.test.com,DNS:myserver2.test.com")) 
    -out servercert.pem  

    客户端的私钥与证书

    生成客户端私钥 clientkey.pem

    openssl genrsa -out  clientkey.pem 2048  

    生成证书请求文件 client.csr 

    openssl req -new 
    -sha256 
    -key clientkey.pem 
    -subj "/C=CN/ST=myprovince/L=mycity/O=myorganization/OU=mygroup/CN=myclient.test.com" 
    -reqexts SAN 
    -config <(cat /etc/pki/tls/openssl.cnf 
        <(printf "[SAN]
    subjectAltName=DNS:myclient.test.com,DNS:myclient2.test.com")) 
    -out client.csr  

    使用根证书签发客户端证书 clientcert.pem

    openssl ca -in client.csr 
    -md sha256 
    -days 3650 
    -keyfile cakey.pem 
    -cert cacert.pem 
    -extensions SAN 
    -config <(cat /etc/pki/tls/openssl.cnf 
    <(printf "[SAN]
    subjectAltName=DNS:myclient.test.com,DNS:myclient2.test.com")) 
    -out clientcert.pem  

    0x03 服务器端的设置

    安装Java、Tomcat、创建JKS存放目录

    Java、Tomcat安装完后 https://www.cnblogs.com/xdyixia/p/11653694.html

    创建存放JKS文件的目录,服务端的Tomcat将用到的JKS格式的私钥和证书

    mkdir -p  /data/live  #此目录之后用于存放JKS文件

    把服务端私钥和证书制作成JKS文件

    #得到 fullchain_and_key.p12
    openssl pkcs12 -export -in  servercert.pem -inkey serverkey.pem  -out fullchain_and_key.p12 -name ssl

    这一步需要输入密码,假设此处输入密码为: mypassword

    #得到ssl.jks
    keytool -importkeystore -deststorepass myJKSpassasdf -destkeypass myJKSpassasdf -destkeystore ssl.jks -srckeystore fullchain_and_key.p12 -srcstoretype PKCS12 -srcstorepass mypassword -alias ssl

    #移位文件到/data/live
    mv  ssl.jks  /data/live

    把信任根证书制作成JKS文件

    #得到ssl2.jks
    keytool -import -alias cacert -file  cacert.pem  -keystore ssl2.jks  -deststorepass myJKSpassasdf2  -destkeypass myJKSpassasdf2

    #移位文件到/data/live
    mv  ssl2.jks  /data/live

    配置Tomcat

    修改Tomcat的server.xml,配置HTTPS功能

     <Connector port="443" protocol="org.apache.coyote.http11.Http11Protocol"
               URIEncoding="UTF-8"  maxThreads="500" SSLEnabled="true" scheme="https" secure="true" clientAuth="true" sslProtocol="TLS"  
               keystoreFile="/data/live/ssl.jks" keystorePass="myJKSpassasdf" 
               truststoreFile="/data/live/ssl2.jks" truststorePass="myJKSpassasdf2"                
    sslEnabledProtocols="TLSv1,TLSv1.1,TLSv1.2,SSLv2Hello"
    ciphers="TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,   
    TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,  
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,  
    TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,  
    TLS_ECDHE_RSA_WITH_RC4_128_SHA,  
    TLS_RSA_WITH_AES_128_CBC_SHA256,  
    TLS_RSA_WITH_AES_128_CBC_SHA,  
    TLS_RSA_WITH_AES_256_CBC_SHA256,  
    TLS_RSA_WITH_AES_256_CBC_SHA,  
    SSL_RSA_WITH_RC4_128_SHA" />

    一些参数说明:

    • port该设置为HTTPS端口号。
    • 如果clientAuth该设置为“false”,则为单向SSL验证,不需要验证客户端证书。
    • 如果clientAuth设置为“true”,表示强制双向SSL验证。
    • 如果clientAuth设置为“want”,则表示可以验证客户端证书,但如果客户端没有有效证书,也不强制验证。
    • keystore就是用来存服务端自身的私钥和证书。
    • truststore就是用来存根证书文件的。

     

    在服务端强制HTTP访问跳转为HTTPS

    在server.xml文件,将redirectPort的8443端口,一律改为443(因为我们之前已经设置了443端口作为HTTPS端口)
    在web.xml文件,插入这样一段:

    <login-config>  
        <!-- Authorization setting for SSL -->  
        <auth-method>CLIENT-CERT</auth-method>  
        <realm-name>Client Cert Users-only Area</realm-name>  
    </login-config>  
    <security-constraint>  
    <!-- Authorization setting for SSL -->  
        <web-resource-collection >  
            <web-resource-name >SSL</web-resource-name>  
            <url-pattern>/*</url-pattern>  
        </web-resource-collection>  
        <user-data-constraint>  
            <transport-guarantee>CONFIDENTIAL</transport-guarantee>  
        </user-data-constraint>  
    </security-constraint> 

    重启tomcat生效

    #关闭
    cd /usr/local/tomcat/tomcat8/bin ./shutdown.sh
    #查看是否关闭
    ps -ef|grep java

    此信息说明还没关

    #如果关不了,使用kill命令,直接杀死Tomcat进程
    kill -9 12265

    此信息说明关了

    #启动Tomcat
    ./startup.sh

    查看tomcat日志

    0x04 客户端的设置

    修改客户端hosts文件

    hosts中加入一行 192.168.91.166  myserver.test.com
    其中,假设192.168.91.166 是服务端的IP,根据实际情况改写。
    注意:这里hosts文件作用是代替DNS域名解析,仅为测试使用。

    客户端浏览器导入CA根证书

    Firefox浏览器导入cacert.pem文件 即CA根证书

    客户端浏览器导入自己的私钥和证书

    X509格式转化为pkcs12格式的文件

    openssl pkcs12 -export -in  clientcert.pem -inkey clientkey.pem    -out  client.p12 -name client_ssl  

    这一步需要输入密码,假设此处输入密码为: mypassword

    将client.p12导入到浏览器

    0x05 双向身份验证与效果

    浏览器打开URL: https://myserver.test.com
    选择客户端证书

     成功打开网站

    该实验主要根据以下博客实现 

    https://gamedun.github.io/-----https://runner-china.github.io/blog/2018/07/10/ca

    其他参考

    https://blog.csdn.net/cuofucsdn/article/details/78851673

    https://blog.csdn.net/Ningdaxing1994/article/details/78790493

    https://www.cnblogs.com/Anker/p/6018032.html (该博文包含单向验证和双向验证)

  • 相关阅读:
    Python正课132 —— Vue 进阶5
    Python正课131 —— Vue 进阶4
    Python正课130 —— Vue 进阶3
    logging模块
    作业20
    suprocess模块
    configparser模块
    hashlib模块
    shutil模块
    序列化模块
  • 原文地址:https://www.cnblogs.com/xdyixia/p/11642854.html
Copyright © 2011-2022 走看看