现如今,即便是一个简单的个人博客,如果不想让来访的朋友被浏览器地址栏上那个「不安全」的提醒所困惑,给域名配上一个 SSL(Secure Sockets Layer) 证书就是很顺理成章的事。有需求自然就有服务,各种签发 SSL 证书的 CA(Certificate Authority) 也顺应潮流,提供各种收费和免费的 SSL 服务。不过今天不提它们,来说说如何自己当 CA,给自己颁发一个 SSL 证书。
起因
平日没事时会关注一下自己这个小站的访问数据,最近时常会发现其中有几条不是通过域名,而是以服务器 IP 访问的记录。但我记得之前配置 Nginx 服务时,专门设置了通过 IP 访问时只显示一个欢迎字样的页面。
通过 IP 访问本站显示的页面
登上服务器再次确认了下,发现只配置了 HTTP 协议,HTTPS 协议的访问是没有配置的,难怪如此。这感觉就像是本来开了个大门(域名)供游客进出,却忘了有个侧门(IP)没关上。所以我想把这个以 HTTPS 协议通过 IP 访问网站的路子给堵上,
选择
配置 HTTPS 就离不开 SSL 证书。最简单的方案就是找主机商申请一个免费的,或者是用 Let's Encrypt 这种三个月一签,自动续期的。问题是他们都需要提供一个可以正常访问的域名。我的需求是给 IP 颁发一个 SSL 证书,所以没得选,只能走自签名证书这一条路。
创建和配置
网上搜索了一下,发现创建一个自签名证书并不复杂,主要就是安装好 OpenSSL 软件。以我使用的 Linux 系统来说,这是系统本身就依赖的软件,默认就自带了,可以直接开始。
首先使用 openssl
命令创建一个私钥:
openssl genrsa -out server.key 2048
- server.key 是要生成的私钥文件,随便自己定义或命名。按照约定保留后面的 .key 后缀就可以了。
- 2048 是私钥的长度。网上一些文章中会用 1024,这是个坑。用了这个值等下在 Nginx 中使用证书时就会碰到
SSL routines:SSL_CTX_use_certificate:ee key too small
的错误。所以下限就是 2048,不能再低了。
上面的命令执行完成后,会生成一个 .key 后缀的文件,这就是生成好的私钥。有了这个私钥后,接下来就是用它生成一个证书:
openssl req -new -key server.key -out server.csr
- -new 顾名思义,表示创建新的证书。
- server.key 指定私钥文件名。
- server.csr 要生成的证书文件,跟私钥文件一样,只要保留后面的 .csr 后缀,文件名随意。不过为了方便和私钥配对识别,建议和私钥的命名保持一致。
生成证书的命令是以交互的方式执行,上面的命令按回车后,会逐行显示如下内容:
[deploy@blog-server cert]$ sudo openssl req -new -key server.key -out server.csr
Enter pass phrase for server.key:
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
+Country Name (2 letter code) [XX]:CN
+State or Province Name (full name) []:Hubei
+Locality Name (eg, city) [Default City]:Wuhan
+Organization Name (eg, company) [Default Company Ltd]:zzxworld
+Organizational Unit Name (eg, section) []:zzxworld
+Common Name (eg, your name or your server's hostname) []:192.168.0.1
+Email Address []:me@zzxworld.com
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
注意我用颜色标识出来的行,冒号后面都是需要自己来输入的内容,以上是我的示例,按照这个模子来就行了。注意 Common Name 这部分,输入内容和要颁发的 IP 地址保持一致,域名同理。
这样就有了一个以 .csr 为后缀的证书文件。最后一步就是自己当 CA,给自己签署一下这个证书就可以了。
openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt
这个命令不多解释,里面的唯一值得一提的参数就是 -days
,表示证书的有效期,单位是天,看着设置就行。最大值我查了一下是 11499。设置成这个最大值那就意味着签一次可以管 31 年。一个证书可以用这么久,想想就开心。
后记
上面生成了三个文件,拿着 .key 和 .crt 后缀的两个文件,传到服务器上,使用 Nginx 的 SSL 配置使用它们即可。
完成配置后,使用 HTTPS 协议访问时,浏览器对这个来路不明的证书表示了怀疑。
不要在意这个提示,大胆的选择「接受风险并继续浏览」,就可以正常浏览网站内容了。只是地址栏域名前的那个小锁图标上会有个感叹号。这就是自签名证书的尴尬之处:没有公信力,所以无法被浏览器所认可。这对于用来解决一些个人需求的项目来说,无伤大雅,用用无妨。