linux下nginx+ssl实现https访问

linux下nginx+ssl实现https访问

目前只尝试了在linux下进行实现。

一 、 环境准备

要编译nginx源码和生成ssl证书,需要linux环境下安装依赖模块:

yum -y install gcc gcc-c++ automake pcre pcre-devel zlip zlib-devel openssl openssl-devel 

二 、 下载nginx源码,编译nginx并添加ssl模块

目前nginx默认版本中没有http_ssl_module模块,所以需要在nginx官网下载最新的nginx源码,然后编译nginx并添加SSL模块。

这里我选择最新的稳定版本:nginx-1.16.0,下载源码包nginx-1.16.0.tar.gz;然后将下载的nginx源码拷贝到linux服务器上一个自定义目录中,进入该目录,然后解压nginx源码sudo tar -xzvf nginx-1.16.0.tar.gz。 进入解压后的目录cd nginx-1.16.0

  • 执行以下命令进行nginx源码编译配置:
    ./configure --prefix=./nginx --with-http_stub_status_module --with-http_ssl_module --with-pcre
    

    注意:–prefix配置的是nginx的安装目录,这里配置安装到当前目录,–with配置是编译nginx时额外添加的模块,这里主要添加了http_ssl_module,其他模块可以选择安装。

  • 执行以下命令编译并安装nginx
    make && make install
    

    安装完成后,在–prefix指定的目录下会有刚编译好的nginx文件夹,进入文件夹,目录结构如下:

    nginx
    ├── conf
    ├── html
    ├── logs
    └── sbin
    

    看到编译后的目录结构,正是我们日常使用的nginx,到此nginx就安装成功。

三 、 配置并启动nginx,用http来访问web

将准备好的网页拷贝到linux服务器中,配置conf/nginx.conf:

server {
    listen       89;
    server_name  localhost;

    root /home/web/https/site/index.html;
}

启动nginx,通过127.0.0.1:89访问刚部署好的网页:

alt

由于nginx上没有配置SSL证书相关的内容,网页的访问仍然是http1.0的协议,高版本浏览器会标记该网页不安全。 如果我们强行使用https访问,则得到如下结果:

alt

四 、 生成自签名SSL证书

由于https需要SSL证书,一般来说,SSL证书需要购买才能真正使用,这里我们只是为了验证可以通过nginx配置来使用https访问网页,因为是本地环境,直接用OpenSSL给自己颁发一个CA根证书用于后面给服务器做CA签署。

1. 生成CA密钥
openssl genrsa -des3 -out ca.key 2048

2. 生成CA根证书
openssl req -sha256 -new -x509 -days 365 -key ca.key -out ca.crt
以上命令生成时候要填很多东西 一个个看着写吧【最好同第4步的信息保持一致,特别是Common Name,对应-subj的CN字段】
如果怕输入错误,可以在上述命令后面直接添加以下命令,显示指定相关信息
 -subj "/C=CN/ST=GD/L=SZ/O=lee/OU=study/CN=172.16.129.89"
 CN(Common Name)代表要授权签发证书的服务器IP

3. 生成服务器秘钥
openssl genrsa -des3 -out server.key 2048
然后他会要求你输入这个key文件的密码。不推荐输入。因为以后要给nginx使用。每次reload nginx配置时候都要你验证这个PAM密码的。
由于生成时候必须输入密码。你可以通过以下命令删除密码。
openssl rsa -in server.key -out server.key

4.生成服务器证书请求文件
openssl req -new -sha256 -key server.key  -out server.csr
以上命令生成时候要填很多东西 一个个看着写吧【最好同第2步的信息保持一致,特别是Common Name对应-subj的CN字段】
如果怕输入错误,可以在上述命令后面直接添加以下命令,显示指定相关信息
 -subj "/C=CN/ST=GD/L=SZ/O=lee/OU=study/CN=172.16.129.89"
 CN(Common Name)代表要授权签发证书的服务器IP
 
5. CA签署服务器证书
openssl ca -in server.csr -md sha256 -keyfile ca.key -cert ca.crt -out server.crt

执行完毕后,会在输出目录里面生成ca.key 、 ca.crt 、 server.key 、 server.crt四个证书文件。

使用时将ca.crt根证书添加到浏览器的“管理证书”中: alt

五 、 配置并启动nginx,用https来访问web

最后一步,我们已经生成了自己的sll证书,接下来就可以配置nginx.conf:

server {
    listen       443 ssl;

    ssl_certificate server.crt; #根据具体的路径配置即可
    ssl_certificate_key server.key; #根据具体的路径配置即可

    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout 5m;

    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;

    location / {
        root /home/web/https/site/;
        index  index.html index.htm;
    }
}

其中443是https的默认端口(http的默认端口是80),现在,你可以通过https://172.16.129.89来访问你的网页了。

但是结果并不是我们想的那样,在chrome30版本下,我的网页顺利打开,也被标记为安全了: alt

但是在最新的chrome74版本下,我们得到的是另外一种结果: alt

我们的网页仍然被标记为不安全,并在打开前给出了安全提示,如果我们忽略,可以点击高级->继续访问,也能打开网页,但这样并不是我们想要的。

原因在于:Chrome58以后对https的证书认证较为严格,证书里必须带有正确的Common Name,也就是必须有DNS Name=ajax.googleapis.com, IP Address=127.0.0.1这样的信息,浏览器才认为真正安全。

打开cosole中Security选项,我们看到一些错误提示:缺少了Subject Alternative Name扩展 alt

接下来我们需要改造生成证书的脚本,主要是针对第4、5两项,添加SAN扩展:


4.生成服务器证书请求文件
openssl req -new \
    -sha256 \
    -key server.key \
    -subj "/C=CN/ST=GD/L=SZ/O=lee/OU=study/CN=172.16.129.89" \
    -reqexts SAN \
    -config <(cat /etc/pki/tls/openssl.cnf \
        <(printf "[SAN]\nsubjectAltName=IP:172.16.129.89")) \
    -out server.csr

5. CA签署服务器证书
openssl ca -in server.csr \
        -md sha256 \
        -keyfile ca.key \
    -cert ca.crt \
    -extensions SAN \
    -config <(cat /etc/pki/tls/openssl.cnf \
        <(printf "[SAN]\nsubjectAltName=IP:172.16.129.89")) \
    -out server.crt

其中/etc/pki/tls/openssl.cnf是openssl的配置文件地址,路径根据具体位置而定;
SAN扩展这里我们用的是IP地址,如果用的DNS,上述对应部分修改为"[SAN]\nsubjectAltName=DNS:172.16.129.89",用“,”号隔开,可以DNS和IP同时使用。
注意:IP指定的地址一定要和CN(Common Name)指定的相同。

接下来重启nginx服务器,清楚浏览器缓存,打开chrome74版本,访问我们的网页https://172.16.129.89: alt

这样,我们整个针对https的调试工作就完成了。