IT博客汇
  • 首页
  • 精华
  • 技术
  • 设计
  • 资讯
  • 扯淡
  • 权利声明
  • 登录 注册

    Linux下配置双向HTTPS证书认证

    chancel发表于 2024-06-17 00:00:00
    love 0
    <![CDATA[

    HTTPS双向认证,也称为客户端认证、双向SSL认证或双向身份验证,是一种增强的HTTPS安全协议,用于确保Web服务器和客户端之间的双向身份验证和通信加密

    在传统的 HTTPS 连接中,只有服务器需要提供数字证书来验证其身份,并启用加密通信。而HTTPS双向认证要求不仅服务器要验证其身份,客户端也需要提供数字证书进行身份验证

    https(Hypertext Transfer Protocol Secure)是在 http 的基础上增加 SSL 加密

    通过双向认证,HTTPS确保了服务器和客户端之间的互相验证,防止中间人攻击和身份伪装

    这种安全机制常用于需要更高安全性和身份验证的环境,如在线银行、电子商务和企业内部网络等

    1. 单向认证 VS 双向认证

    传统的 HTTPS 访问过程如下

    双向认证是在上面的基础上增加多一次认证,如下

    2. 实践

    2.1. Nginx启用HTTPS

    Nginx启用HTTPS流程:

    • 向CA证书商家申请证书
    • 下载证书,并更改NGINX配置指向证书
    • 重新读取NGINX配置即可完成HTTPS配置

    先手动生产一个测试用的CA证书

    自行产生的证书,浏览器会提示证书不安全

    先创建并切换到存放HTTPS证书的文件夹

    Bash
    mkdir /etc/nginx/ssl_certs
    cd /etc/nginx/ssl_certs
    

    制作CA私钥和证书,全部配置填"."

    Bash
    openssl genrsa -out ca.key 2048
    openssl req -new -x509 -days 3650 -key ca.key -out ca.crt
    

    制作服务器证书签发文件,除了Common Name填入域名,其他全部填入"."以便和CA根证书对应

    Bash
    openssl genrsa -out server.pem 1024
    openssl rsa -in server.pem -out server.key
    openssl req -new -key server.pem -out server.csr
    

    使用CA证书进行签发

    Bash
    openssl x509 -req -sha256 -in server.csr -CA ca.crt -CAkey ca.key -CAcreateserial -days 3650 -out server.crt
    

    签发后,产生了我们需要的 crt 和 key 文件

    编辑:/etc/nginx/conf.d/default.conf

    TEXT
    server {
        listen       443 ssl;
        server_name  www.example.com;
        #charset koi8-r;
        #access_log  /var/log/nginx/host.access.log  main;
        ssl on;
        ssl_certificate /etc/nginx/ssl/server.crt;      # 服务端HTTPS的证书,不能自己产生,否则会提示证书不安全,该配置与客户端证书无关
        ssl_certificate_key /etc/nginx/ssl/server.key;  # 服务端HTTPS的证书,不能自己产生,否则会提示证书不安全,该配置与客户端证书无关
        location / {
            proxy_pass_header Server;
            proxy_pass_header X-Scheme;
            proxy_set_header Host $http_host;
            proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;
            proxy_set_header X-SSL-CERT-DN $ssl_client_s_dn;
            proxy_set_header X-SSL-CERT-VERIFY $ssl_client_verify;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_pass http://192.168.10.100:5000/;
        }
    }
    

    验证使用HTTPS访问

    Bash
    # 因证书自签必须使用insecure忽略证书风险,提示否则curl会返回证书不安全测试失败的结果
    curl --insecure 'https://www.example.com' -v
    

    2.2. 客户端启用证书验证

    客户端证书一般就采用自己配置根证书来签发自己的客户端证书,签发客户端证书会包含几个重要的属性,分别是

    • 地区信息(国家、省份、城市)
    • 公司信息(公司名称、该证书拥有者的部门信息)
    • Common Name信息(也叫CN信息,可把一些信息存储在这里,如有效信息/客户端信息等)
    • 邮箱信息
    • 证书有效期、证书导入/导出密码

    制作客户端证书的流程一般为

    1. 制作自己的CA私钥(ca.key)
    2. 使用CA私钥制造CA根证书(cacert.crt)
    3. 制作客户端私钥,并合成待签发csr文件(client.key,client.csr)
    4. 使用CA证书对客户端待签发文件进行签发产生客户端的crt证书(client.crt)
    5. 转换客户端证书为适合浏览器的证书格式(client.pfx,client.p12)

    首先要编辑默认CA创建规则,根据需要自行修改一下默认的参数

    编辑/etc/pki/tls/openssl.cnf

    Bash
    /etc/pki/CA/            # 所有资料全存放在此目录下
    /etc/pki/CA/certs/      # 存放CA证书
    /etc/pki/CA/crl/        # 存放证书吊销列表
    /etc/pki/CA/index.txt   # 存放可用、不可用证书的数据库
    /etc/pki/CA/newcerts    # 存放CA的新目录
    /etc/pki/CA/cacert.pem  # 生成的自签名证书
    /etc/pki/CA/serial      # 下个证书的编号,16进制,多从00或01开始
    /etc/pki/CA/crlnum      # 下一个吊销证书的编号
    /etc/pki/CA/crl.pem     # 下一个吊销列表
    /etc/pki/CA/private/cakey.pem  # 默认密钥
    
    # 匹配策略的可选值
    match                   # 必须匹配,默认是国家、州(省)、组织名称
    supplied                # 必填,为哪个主机申请证书,一般对应域名
    optional                # 可选
    

    根据具体的环境调整好上述的参数之后,我们就可以开始制作客户端证书

    文件夹位置根据实际情况自行调整

    生成创建证书所必须的基本文件

    Bash
    # 生成数据库文件,记录证书信息(包含序列号、序号、证书自定义CN信息等)
    touch /etc/pki/CA/index.txt
    # 生成存放证书编号的文件(一般存储即将颁发的下一个证书序号)
    echo 00 > /etc/pki/CA/serial
    

    切换到/etc/pki/CA,开始生成签证客户端的根证书

    Bash
    openssl  req -new -x509  -key private/cakey.pem  -days 3650 -out cacert.pem
    

    接下来签发客户端的证书(此处有提供一键脚本执行)

    Bash
    # 创建存放客户端证书的文件夹
    mkdir /etc/nginx/client_ssl
    # 切换到存放客户端证书的目录
    cd /etc/nginx/client_ssl
    # 创建客户端证书私钥
    (umask 066; openssl genrsa -out client_01.key 1024)
    # 创建请求根证书签证的文件             
    openssl  req -new -key client_01.key  -out client_01.csr
    # 创建客户端证书        
    openssl  ca -in client_01.csr  -out client_01.crt -days 730
    

    client_01.crt 就是客户端证书

    编辑:/etc/nginx/conf.d/default.conf

    TEXT
    server {
        listen       443 ssl;
        server_name  www.example.com;
        #charset koi8-r;
        #access_log  /var/log/nginx/host.access.log  main;
        ssl on;
        ssl_certificate /etc/nginx/ssl/server.crt;      # 服务端HTTPS的证书,不能自己产生,否则会提示证书不安全,该配置与客户端证书无关
        ssl_certificate_key /etc/nginx/ssl/server.key;  # 服务端HTTPS的证书,不能自己产生,否则会提示证书不安全,该配置与客户端证书无关
        ssl_client_certificate /etc/nginx/ssl/ca.crt;   # 客户端的CA根证书,由自己的机器OPENSSL生成
        ssl_verify_client optional;                     # 是否启用客户端验证,ON为启用,OFF为不启用,如需自定义验证结果处理则填入optional
        if ($ssl_client_verify = NONE) {
            return 303 http://www.example.com/error;
        }
            location / {
                proxy_pass_header Server;
                proxy_pass_header X-Scheme;
                proxy_set_header Host $http_host;
                proxy_set_header X-SSL-CERT $ssl_client_escaped_cert;   # 转发证书信息
                proxy_set_header X-SSL-CERT-DN $ssl_client_s_dn;        # 转发证书的CN信息
                proxy_set_header X-SSL-CERT-VERIFY $ssl_client_verify;  # 转发证书的验证结果,成功为success
                proxy_set_header X-Real-IP $remote_addr;
                proxy_pass http://192.168.10.100:5000/;
        }
    }
    

    测试客户端证书能否正常访问网页

    Bash
    # -v参数可以打印详细信息以便我们核查证书的详细信息
    curl --insecure --key ./client.key --cert ./client.crt 'https://www.example.com' -v
    

    以上步骤我整理为一个简易的客户端证书脚本,如下

    Bash
    #!/bin/bash -e
    # 运行脚本前请记得设置好openssl.cnf配置文件
    # 运行成功返回0,运行失败(缺少参数)返回-1
    show_help() {
        echo "$0 [-h|-?|--help] [--ou ou] [--cn cn] [--email email]"
        echo "-h|-?|--help    显示帮助"
        echo "--ou            设置组织或部门名"
        echo "--cn            设置证书的DN信息"
        echo "--email         设置证书的邮箱信息"
        echo "--days          设置证书的有效时间"
        echo "--out           设置证书的输出目录(含文件名)"
    }
    while [[ $# -gt 0 ]]; do
        case $1 in
        -h | -\? | --help)
            show_help
            exit 0
            ;;
        --ou)
            OU="${2}"
            shift
            ;;
        --cn)
            CN="${2}"
            shift
            ;;
        --email)
            emailAddress="${2}"
            shift
            ;;
        --days)
            days="${2}"
            shift
            ;;
        --out)
            out="${2}"
            shift
            ;;
        --)
            shift
            break
            ;;
        *)
            echo -e "Error: $0 invalid option '$1'\nTry '$0 --help' for more information.\n" >&2
            exit -1
            ;;
        esac
        shift
    done
    # 创建客户端证书
    # 非交互式方式创建以下内容:
    # 国家名(2个字母的代号)
    C=CN
    # 省
    ST=GuangDong
    # 市
    L=GuangDong
    # 公司名
    O=TY
    # 部门名
    OU=${OU:-未知}
    # DN信息
    CN=${CN:-未知}
    # 邮箱地址
    emailAddress=${emailAddress:-virtual@example.com}
    # 创建私钥
    openssl req -utf8 -nodes -newkey rsa:2048 -keyout "${out}.key" -new -days "${days}" -out "${out}.csr" -subj "/C=${C}/ST=${ST}/L=${L}/O=${O}/OU=${OU}/CN=${CN}/emailAddress=${emailAddress}"
    # 使用根证书进行进行签证
    openssl ca -utf8 -batch -days 36500 -in "${out}.csr" -out "${out}.crt"
    # 转换客户端证书的类型为浏览器支持的模式
    openssl pkcs12 -export -inkey "${out}.key" -in "${out}.crt" -passout pass: -out "${out}.pfx"
    exit 0
    

    3. 尾语

    SSL证书常用格式转换方法

    Bash
    # crt转pfx(p12)
    openssl pkcs12 -export -inkey server.key -in server.crt -out server.pfx
    
    # csr转pfx(p12)
    openssl pkcs12 -export -inkey server.key -in server.csr -out server.pfx
    
    # pfx转jks
    keytool -importkeystore -v  -srckeystore client.pfx -srcstoretype pkcs12  -destkeystore client.keystore -deststoretype jks 
    
    # jks转p12(pfx)
    keytool -importkeystore -srckeystore client_pri.keystore -destkeystore client_pri.p12 -srcstoretype JKS -deststoretype PKCS12 -srcalias imgo.tv -destalias imgo.tv -noprompt
    
    # pfx转x509
    openssl pkcs12 -in onovps.com.pfx -nodes -out onovps.com.pem 
    openssl rsa -in onovps.com.pem -out onovps.com.key
    openssl x509 -in onovps.com.pem -out onovps.com.crt
    

    资料参考

    • 使用OpenSSL构建私有CA - linux
    • Nginx SSL快速双向认证配置(脚本) - Dteam



沪ICP备19023445号-2号
友情链接