在另一篇关于配置Apache反向代理的文章中,介绍了通过https + IP + 端口转发到源服务器,当时是通过关闭后端服务器https证书验证实现的,这样不安全也不规范。本文就来介绍如何使用openssl命令制作自签名证书,使用bash脚本一键生成自签名SSL证书(CA+服务端+客户端),运行脚本即可生成,无需繁琐的配置和一步步的操作;并详细介绍如何配置源服务器服务器自签名证书,配置反向代理和源服务器的双向认证。
使用openssl命令制作自签名证书
查找openssl命令
Linux 使用命令 find / -name openssl
查找 openssl
命令位置,如果Linux系统自身安装了,会找到 /usr/bin/openssl
,我们可以直接使用openssl命令;若系统没有装openssl,但是Apache安装了openssl模块,可以找到 /opt/lampp/bin/openssl
,我们可以使用apache的openssl生成证书。
Windows 安装Apache的,可在Apache/bin目录下找到openssl.exe,也是可以使用openssl生成证书的。
生成CA根证书 + 服务端证书(源服务器) + 客户端证书(反向代理服务器)
生成证书的配置文件和bash脚本已打包,可直接下载运行gen.sh。下载地址:生成证书的配置文件和bash脚本
下载解压后在新建文件夹中执行命令 ./gen.sh
或者 bash gen.sh
。使用该脚本前需要确认有 openssl 命令。该脚本会生成一张 CA 自签发证书,然后使用该CA证书签发一张服务端证书(通用的PKCS#8格式)、一张客户端证书(PKCS#1格式用于反向代理服务器Apache)和另一张客户端证书(通用的PKCS#8格式)。
对生成证书命令感兴趣的朋友,和windows环境生成证书的,请看本文后半段生成CA根证书 + 服务端证书(源服务器) + 客户端证书(反向代理服务器)的详细介绍和实现方法

配置apache ssl证书
服务器端(即网站源服务器)配置ssl证书(含根证书)
- 修改 httpd-conf 在
Listen 80
后加上Listen 8001
- 修改 httpd-ssl.conf
<VirtualHost _default_:8001>
ServerName 115.155.2.10
#此处省略其他配置,请自己添加
SSLEngine on
SSLCertificateFile "/opt/lampp/etc/ssl.crt/server.pem" #server公钥证书
SSLCertificateKeyFile "/opt/lampp/etc/ssl.key/server.key" #server私钥文件
SSLVerifyClient require #开启客户端证书验证
SSLCACertificateFile "/opt/lampp/etc/ssl.crt/ca.pem" #根证书,可以验证所有它颁发的客户端证书
</VirtualHost>
代理服务器(即客户端)配置
修改 httpd-ssl.conf ,参考设置如下
<VirtualHost _default_:443>
ServerName www.bluepost.cn
ServerAlias bluepost.cn
SSLEngine on
SSLCertificateFile "conf/ssl.crt/bluepost.cn_public.crt"
SSLCertificateKeyFile "conf/ssl.key/bluepost.cn.key"
SSLCertificateChainFile "conf/ssl.crt/bluepost.cn_chain.crt"
SSLProxyEngine on
SSLProxyCACertificateFile "conf/ssl.crt/ca.pem" #自签名根证书,用于验证所有它颁发的自签名服务端和客户端证书
SSLProxyMachineCertificateFile "conf/ssl.crt/client_key_crt.pem" #开启客户端证书验证时需要
#设置代理通过IP和端口
ProxyPreserveHost on #打开host域名请求地址,如果使用代理,获取的请求地址是对外域名,如果off关闭,则获取的是ip地址请求
ProxyPass / https://115.155.2.10:8001/ #将IP地址改为国外服务器的IP
ProxyPassReverse / https://115.155.2.10:8001/
</VirtualHost>
浏览器访问自签名网站
直接用浏览器访问 https://115.155.2.10:8001/
,会报错 此网站出具的安全证书不是由受信任的证书颁发机构颁发的。
这时我们需要将生成的 ca.pem
证书导入到【受信任的根证书颁发机构】,如果开启了客户端证书验证,还需要将 proxy_client.p12
证书文件导入到 【个人】->【证书】中。
遇到的问题1 – 自签名证书报错ERR_CERT_COMMON_NAME_INVALID
使用自签名的证书后,chrome报错此服务器无法证实它就是 115.155.2.10
它的安全证书没有指定主题备用名称。这可能是因为某项配置有误或某个攻击者拦截了您的连接。
错误码是 NET::ERR_CERT_COMMON_NAME_INVALID:
问题原因
生成证书的时候没有加上备用名称字段,目前的浏览器校验证书都需要这个字段。
解决方法
生成证书的时候需要添加上备用名称(subjectAltName)扩展字段。使用 openssl
生成crt证书时,需要配置 subjectAltName
参数,详细介绍见修改配置文件server-openssl.cnf文件 alt_names
。
遇到的问题2 – 配置反向代理后,访问网站报错Reason: Error during SSL Handshake with remote server
浏览器直接通过端口访问正常,但是通过域名访问报错如下:
Proxy Error
The proxy server could not handle the request
Reason: Error during SSL Handshake with remote server
Additionally, a 500 Internal Server Error error was encountered while trying to use an ErrorDocument to handle the request.
解决方法
请检查生成源服务器证书时,有没有将域名和IP都加入备用名称(subjectAltName)扩展字段中,修改方法见修改配置文件server-openssl.cnf文件 alt_names
。
生成CA根证书 + 服务端证书(源服务器) + 客户端证书(反向代理服务器)的详细介绍和实现方法
生成CA根证书
创建ca-openssl.cnf文件
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = CN
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Some-State
organizationName = Organization Name (eg, company)
organizationName_default = Internet Widgits Pty Ltd
commonName = Common Name (eg, YOUR name)
commonName_default = AbelCA
[v3_req]
basicConstraints = CA:true
keyUsage = critical, keyCertSign
生成CA根证书
openssl req -x509 -new -newkey rsa:2048 -nodes -keyout ca.key -out ca.pem -config ca-openssl.cnf -days 3650 -extensions v3_req
生成服务端证书(源服务器)
创建server-openssl.cnf文件
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
[req_distinguished_name]
countryName = Country Name (2 letter code)
countryName_default = CN
stateOrProvinceName = State or Province Name (full name)
stateOrProvinceName_default = Shanghai
localityName = Locality Name (eg, city)
localityName_default = Shanghai
organizationName = Organization Name (eg, company)
organizationName_default = Example, Co.
commonName = Common Name (eg, YOUR name)
commonName_max = 64
####################################################################
[ ca ]
default_ca = CA_default # The default ca section
####################################################################
[ CA_default ]
dir = . # Where everything is kept
certs = $dir # Where the issued certs are kept
crl_dir = $dir # Where the issued crl are kept
database = $dir/index.txt # database index file.
new_certs_dir = $dir # default place for new certs.
certificate = $dir/ca.pem # The CA certificate
serial = $dir/serial # The current serial number
crlnumber = $dir/crlnumber # the current crl number
crl = $dir/crl.pem # The current CRL
private_key = $dir/private/cakey.pem# The private key
RANDFILE = $dir/private/.rand # private random number file
[v3_req]
basicConstraints = CA:FALSE
keyUsage = nonRepudiation, digitalSignature, keyEncipherment
subjectAltName = @alt_names
[alt_names]
DNS.1 = bluepost.cn
DNS.2 = *.bluepost.cn
IP.1 = 115.155.2.10
记得修改上述配置文件中的 alt_names
,将域名和IP改为自己的域名和IP,如果多个域名,可以按DNS.1/DNS.2/…来添加,同时还支持IP地址的形式,填入IP.1 = x.x.x.x就可以了。
一定要将需要签名的域名都加入,通过IP访问的需要将服务器公网IP和域名加上,否则会报错安全证书没有指定主题备用名称
生成服务端证书
# 创建服务端私钥
openssl genrsa -out server.key.rsa 2048
# 将私钥转换成更通用的 pkcs#8 格式
openssl pkcs8 -topk8 -in server.key.rsa -out server.key -nocrypt
# 根据私钥生成请求文件
openssl req -new -key server.key -out server.csr -config server-openssl.cnf
# 结合私钥和请求文件创建服务端证书,有效期10年
openssl x509 -req -CA ca.pem -CAkey ca.key -CAcreateserial -in server.csr -out server.pem -extensions v3_req -extfile server-openssl.cnf -days 3650
生成客户端证书(反向代理服务器)
反向代理服务器httpd-ssl.cnf需要配置SSLProxyMachineCertificateFile
# 创建客户端私钥
openssl genrsa -out proxy_client.key 2048
# 根据私钥生成请求文件
openssl req -new -key proxy_client.key -out proxy_client.csr
# 结合私钥和请求文件创建服务端证书,有效期10年
openssl x509 -req -CA ca.pem -CAkey ca.key -CAcreateserial -in proxy_client.csr -out proxy_client.pem -days 3650
# 将私钥和对应的证书链合成 PKCS#12 格式,KeyStore 密码和私钥密码均为 123456
openssl pkcs12 -export -CAfile ca.pem -in proxy_client.pem -inkey proxy_client.key -out proxy_client.p12 -passout pass:123456
# 把客户端证书和密钥合成一个文件,用于 **反向代理服务器作为客户端证书配置**
# 注意秘钥必需是pkcs1格式,如果不是,需要用命令 openssl rsa -in private-pkcs8.key -outform private.key
cat proxy_client.key proxy_client.pem > client_key_crt.pem
转载请注明:半亩方塘 » 使用bash脚本一键生成自签名SSL证书(CA+服务端+客户端),实现反向代理和源服务器双向认证