前言
在当今互联网时代,安全性成为越来越重要的议题。随着网络攻击日益猖獗,保护数据和通信的安全性变得至关重要。在这种背景下,对于在 Docker 中运行 Nginx 是否需要使用 HTTPS 这一问题,我们需要考虑到网络安全的重要性以及 HTTPS 协议所提供的加密和认证功能。接下来,让我们深入探讨为什么在 Docker 中运行 Nginx 时使用 HTTPS 是至关重要的。
目录
一、实现 https
1. Docker中的Nginx服务为什么要启用HTTPS
2. HTTPS 单向认证过程
3. 如何获取证书
3.1 通过阿里云获取证书
2. 通过 openssl 获取证书
二、nginx 镜像构建
1. 安装docker-20.10.17
2. 进入 nginx 工作目录
3. 编写 Dockerfile 文件
4. 准备 nginx.conf 文件
5. 生成镜像
6. 启动镜像容器
7. 验证 nginx
一、实现 https
1. Docker中的Nginx服务为什么要启用HTTPS
在生产环境中,使用 HTTPS(HTTP over SSL/TLS)对 Docker 中的 Nginx 进行加密和安全传输是非常重要的,原因如下:
- 数据加密:HTTPS 使用 SSL/TLS 协议对数据进行加密传输,可以保护数据在传输过程中不被窃取或篡改,确保数据的机密性和完整性。
- 身份验证:HTTPS 可以验证服务器的身份,防止中间人攻击,确保用户连接的是正确的服务器,同时也可以通过客户端证书对客户端进行身份验证。
- 信任与安全:HTTPS 使用数字证书来验证服务器的身份,建立信任关系,减少恶意攻击的可能性,提高通信的安全性。
- 符合标准:现代网络安全标准和实践推荐使用 HTTPS 来保护 Web 应用程序,确保数据的安全性。
- SEO 和用户信任:搜索引擎(如 Google)更倾向于将采用 HTTPS 的网站排名更靠前,同时用户也更倾向于信任使用 HTTPS 的网站,提升用户体验和信任度。
2. HTTPS 单向认证过程
HTTPS证书认证的过程涉及以下步骤:
- 客户端发起连接:用户在浏览器中输入HTTPS网址,客户端(通常是浏览器)向服务器发起连接请求。
- 服务器返回证书:服务器收到连接请求后,会将自己的数字证书发送给客户端。证书包含了服务器的公钥、证书颁发机构(CA)的数字签名、有效期等信息。
- 客户端验证证书:客户端收到服务器的证书后,会验证证书的有效性。验证包括检查证书是否由受信任的证书颁发机构签发,证书是否在有效期内,以及证书中的域名是否与访问的域名匹配等。
- 客户端生成会话密钥:如果证书验证通过,客户端会生成一个随机的对称密钥(会话密钥)用于加密通信。
- 客户端用公钥加密会话密钥:客户端使用服务器的公钥(证书中包含的公钥)对会话密钥进行加密,然后发送给服务器。
- 服务器用私钥解密会话密钥:服务器收到客户端发送的加密的会话密钥后,使用自己的私钥(与证书中的公钥对应)进行解密。
- 建立安全连接:服务器和客户端现在都有了会话密钥,它们可以使用这个密钥来加密和解密通信内容,建立安全的加密连接。
- 安全通信:双方之间的通信现在是加密的,数据在传输过程中会被加密保护,确保安全性和隐私性。
通过这个过程,HTTPS证书认证确保了通信的安全性和数据的保密性,防止了中间人攻击和窃听等安全威胁。
3. 如何获取证书
- 在阿里云、华为云、腾讯云等云服务商那里申请一年有效期的免费证书或者购买证书
- 在本地使用 openssl、mkcert、cfssl、certbot(Let's Encrypt)的工具生成本地私钥证书
3.1 通过阿里云获取证书
https://www.aliyun.com/product/cas?userCode=r3yteowb
2. 通过 openssl 获取证书
生成ca证书:
(1)创建ca私钥
[root@localhost ~]# mkdir -p /lnmp/nginx/cert
[root@localhost ~]# cd /lnmp/nginx/cert/
[root@localhost cert]# openssl genrsa -aes256 -out ca-key.pem 4096
Generating RSA private key, 4096 bit long modulus
...........++
................................++
e is 65537 (0x10001)
Enter pass phrase for ca-key.pem: # 输入123456
Verifying - Enter pass phrase for ca-key.pem: # 输入123456
# openssl: OpenSSL 是一个开放源代码的加密工具包,提供了一系列加密算法和工具,用于安全通信、数据加密等操作。
# genrsa: 这个命令告诉 OpenSSL 生成一个 RSA 密钥对,包括公钥和私钥。
# -aes256: 这个选项指定生成的私钥要使用 AES 256 位加密算法进行加密。这样生成的私钥文件会被加密存储,需要输入密码才能解密使用。
# -out ca-key.pem: 这个选项指定生成的私钥保存到名为 ca-key.pem 的文件中。
# 4096: 这个参数指定生成的 RSA 密钥长度为 4096 位,这是一个比较安全的密钥长度。
使用 OpenSSL 生成一个带有 AES 256 位加密的 4096 位 RSA 私钥,并将其保存到名为 ca-key.pem 的文件中。生成的私钥文件将会被加密存储,需要输入密码才能解密和使用。
(2)创建ca证书
[root@localhost cert]# openssl req -new -x509 -days 1000 -key ca-key.pem -sha256 -subj "/CN=*" -out ca.pem
Enter pass phrase for ca-key.pem: # 输入123456
# openssl req: 这个命令告诉 OpenSSL 工具执行证书请求操作。
# -new: 这个选项表示生成一个新的证书请求。
# -x509: 这个选项指示生成自签名的 X.509 格式证书,而不是生成证书请求。
# -days 1000: 这个选项指定证书的有效期为 1000 天,即证书在签发后的有效期限。
# -key ca-key.pem: 这个选项指定使用之前生成的 ca-key.pem 文件中的私钥来签署证书。
# -sha256: 这个选项指定使用 SHA-256 算法来生成证书的摘要。
# -subj "/CN=*": 这个选项指定了证书的主题字段,其中 /CN=* 表示通用名称(Common Name)为通配符 *,表示这是一个通用的证书,而不是针对特定域名的。
# -out ca.pem: 这个选项指定生成的证书将保存到名为 ca.pem 的文件中。
使用 OpenSSL 工具生成一个自签名的 X.509 格式的数字证书,该证书的有效期为 1000 天,使用之前生成的私钥文件 ca-key.pem 进行签名,主题字段为通配符 *,并将生成的证书保存到名为 ca.pem 的文件中。
用 ca 证书签发 server 端证书:
(3)创建服务器私钥
[root@localhost cert]# openssl genrsa -out server-key.pem 4096
Generating RSA private key, 4096 bit long modulus
..............++
................................................................................................................................................++
e is 65537 (0x10001)
# openssl genrsa: 这个命令告诉 OpenSSL 工具生成一个 RSA 私钥。
# -out server-key.pem: 这个选项指定生成的私钥将保存到名为 server-key.pem 的文件中。
# 4096: 这个参数指定生成的 RSA 私钥的位数为 4096 位,这是一种常见的安全密钥长度,提供了较高的安全性。
使用 OpenSSL 工具生成一个 4096 位的 RSA 私钥,并将生成的私钥保存到名为 server-key.pem 的文件中。生成的私钥文件通常用于安全通信中,例如用于 HTTPS 连接中的服务器端认证。
(4)生成证书签名请求文件(csr文件)
[root@localhost cert]# openssl req -new -key server-key.pem -sha256 -subj "/CN=*" -out server.csr
# openssl req: 这个命令告诉 OpenSSL 工具执行证书请求操作。
# -new: 这个选项指示 OpenSSL 创建一个新的 CSR。
# -key server-key.pem: 这个选项指定要用于生成 CSR 的私钥文件,这里是 server-key.pem。
# -sha256: 这个选项指定要使用 SHA-256 算法进行摘要计算。
# -subj "/CN=*": 这个选项指定了 CSR 的主题信息,其中 /CN=* 表示 Common Name (通用名称)字段为通配符 *,通常用于生成通配符证书。
# -out server.csr: 这个选项指定生成的 CSR 将保存到名为 server.csr 的文件中。
使用 OpenSSL 工具基于指定的私钥文件 server-key.pem 创建一个新的 CSR,其中的 Common Name 字段为通配符 *,并使用 SHA-256 算法进行摘要计算,最后将生成的 CSR 保存到名为 server.csr 的文件中。CSR 通常用于向证书颁发机构(CA)申请数字证书。
(5)使用ca 证书与私钥证书签发服务端签名证书,输入 123456,(需要签名请求文件,ca 证书,ca 密钥)
[root@localhost cert]# openssl x509 -req -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -days 1000 -out server-cert.pem
Signature ok
subject=/CN=*
Getting CA Private Key
Enter pass phrase for ca-key.pem:
# openssl x509: 这个命令告诉 OpenSSL 工具执行证书相关的操作。
# -req: 这个选项表示输入的文件是一个证书请求 (CSR)。
# -sha256: 这个选项指定使用 SHA-256 算法进行摘要计算。
# -in server.csr: 这个选项指定要签署的证书请求文件为 server.csr。
# -CA ca.pem: 这个选项指定要用来签署证书的 CA (Certificate Authority) 的证书文件为 ca.pem。
# -CAkey ca-key.pem: 这个选项指定用于签署证书的 CA 的私钥文件为 ca-key.pem。
# -CAcreateserial: 这个选项告诉 OpenSSL 生成一个序列号文件,用于跟踪已签署证书的序列号。
# -days 1000: 这个选项指定生成的证书有效期为 1000 天。
# -out server-cert.pem: 这个选项指定生成的证书将保存到名为 server-cert.pem 的文件中。
在执行过程中的输出含义如下:
# Signature ok: 表示签名验证成功,证书签名操作正常。
# subject=/CN=*: 表示证书的主题信息为 Common Name (CN) 字段为通配符 *。
# Getting CA Private Key: 表示正在获取 CA 的私钥用于签署证书。
# Enter pass phrase for ca-key.pem: 提示输入 ca-key.pem 文件的密码短语,以便获取 CA 的私钥进行签署操作。
使用指定的 CA 证书和私钥对给定的证书请求进行签署,生成一个新的证书,并将该证书保存到名为 server-cert.pem 的文件中。
[root@localhost cert]# ls
ca-key.pem ca.pem ca.srl server-cert.pem server.csr server-key.pem
# ca-key.pem: 这是 CA (Certificate Authority) 的私钥文件,用于对证书请求进行签署以生成数字证书。
# ca.pem: 这是 CA 的证书文件,包含了 CA 的公钥和其他相关信息。
# ca.srl: 这是用于跟踪已签署证书的序列号文件,用于生成唯一的证书序列号。
# server-cert.pem: 这是使用 CA 签署后生成的服务器数字证书文件,用于在安全通信中进行身份验证。
# server.csr: 这是服务器证书签名请求 (CSR) 文件,包含了服务器的公钥和相关信息,用于向 CA 请求签发数字证书。
# server-key.pem: 这是服务器的私钥文件,用于与服务器证书一起进行安全通信和加密解密操作
二、nginx 镜像构建
1. 安装docker-20.10.17
systemctl stop firewalld.service
setenforce 0
sudo yum install -y yum-utils device-mapper-persistent-data lvm2
# 安装所需的依赖
sudo yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
# 添加Docker官方仓库
# [root@localhost ~]#yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 正常后面还是用国内阿里源更合适
sudo yum makecache fast
# 更新Yum缓存
sudo yum install docker-ce-20.10.17 docker-ce-cli-20.10.17 containerd.io
# 安装Docker CE 20.10.17
systemctl enable --now docker
# 启动并开机自启Docker服务
docker --version
# 验证安装
2. 进入 nginx 工作目录
[root@localhost cert]# cd ..
[root@localhost nginx]# ls
cert
[root@localhost nginx]# docker pull nginx
[root@localhost nginx]# docker pull centos:7
[root@localhost nginx]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx latest 7383c266ef25 8 days ago 188MB
centos 7 eeb6ee3f44bd 2 years ago 204MB
[root@localhost nginx]# ls
cert Dockerfile html nginx-1.24.0.tar.gz nginx.conf wordpress-4.9.4-zh_CN.tar.gz
[root@localhost nginx]# ls html/wordpress/
index.php wp-admin wp-content wp-load.php wp-signup.php
license.txt wp-blog-header.php wp-cron.php wp-login.php wp-trackback.php
readme.html wp-comments-post.php wp-includes wp-mail.php xmlrpc.php
wp-activate.php wp-config-sample.php wp-links-opml.php wp-settings.php
3. 编写 Dockerfile 文件
[root@localhost nginx]# vim Dockerfile
FROM centos:7 # 基于centOS:7镜像作为基础镜像
MAINTAINER nginx image <fql> # 指定镜像的维护者信息
RUN yum -y install pcre-devel zlib-devel gcc gcc-c++ make openssl openssl-devel
# yum安装必要的软件包至镜像;
RUN useradd -M -s /sbin/nologin nginx # 创建nginx的系统用户,且无法登录系统
ADD nginx-1.24.0.tar.gz /usr/local/src/ # 将nginx文件解压到/usr/local/src/目录下
WORKDIR /usr/local/src/nginx-1.24.0 # 工作目录切换
RUN ./configure \ # 配置、编译并安装Nginx,指定安装路径、用户、用户组以及使用了 with-http_sub_status_module 模块
--prefix=/usr/local/nginx \
--user=nginx \
--group=nginx \
--with-http_ssl_module \ # 加载nginx_http_ssl_module模块,该模块是处理SSL/TLS连接所必需的
--with-http_stub_status_module && make -j 8 && make instal
ENV PATH /usr/local/nginx/sbin:$PATH # 将Nginx可执行文件路径添加到环境变量中
COPY cert/ /usr/local/nginx/cert/ # 将证书文件和相关的密钥文件复制镜像目录中
ADD nginx.conf /usr/local/nginx/conf/ # 将宿主机当前目录nginx.conf配置文件复制到镜像指定目录
#ADD wordpress-4.9.4-zh_CN.tar.gz /usr/local/nginx/html/
ADD html/ /usr/local/nginx/html/ # 将本地的html目录添加到镜像中的/usr/local/nginx/html/目录下
RUN chmod 777 -R /usr/local/nginx/html/ # 授权
EXPOSE 80 # 暴露容器的80端口,http
EXPOSE 443 # 暴露容器的443端口,https
VOLUME [ "/usr/local/nginx/html/" ] # 在Docker内创建挂载点
ENTRYPOINT [ "/usr/local/nginx/sbin/nginx", "-g", "daemon off;" ]
# 启动Nginx并以非守护进程方式运行
4. 准备 nginx.conf 文件
[root@localhost nginx]# egrep -v "^(.)*#(.)*$" nginx.conf | grep -v "^$"
# 从文件nginx.conf中过滤掉以#开头的注释行和空行,然后输出剩余的非注释非空行内容
worker_processes 1;
events {
worker_connections 1024;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
charset utf-8;
location / {
root html;
index index.html index.php;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
location ~ \.php$ {
# 指定了匹配请求URI以.php结尾的条件,~表示使用正则表达式匹配
root html; # 查找文件的根目录为html
fastcgi_pass 172.19.0.30:9000;
# Nginx将把.php文件发送到172.19.0.30上的FastCGI服务器的9000端口
fastcgi_index index.php; # 当请求URI以/结尾时,Nginx应该使用的默认文件
fastcgi_param SCRIPT_FILENAME /usr/local/nginx/html$fastcgi_script_name;
# 这个参数告诉FastCGI服务器要执行的PHP脚本的路径。$fastcgi_script_name是一个FastCGI变量,代表请求的文件路径
include fastcgi_params; # 包含了一个外部文件fastcgi_params
}
}
# 根据请求的URI找到对应的PHP文件,将请求发送给FastCGI服务器进行处理,并设置一些FastCGI参数。这样可以实现在Nginx服务器上运行PHP脚本的功能。
server {
listen 443 ssl; # 指定Nginx监听443端口,并启用SSL/TLS加密
server_name www.fql.com; # 只有当请求的域名是www.fql.com时,这个服务器块才会生效
ssl_certificate /usr/local/nginx/cert/server-cert.pem;
#指定SSL证书文件的路径,用于加密传输中的证书验证。
ssl_certificate_key /usr/local/nginx/cert/server-key.pem;
# 指定SSL证书对应的私钥文件的路径,用于解密传输中的数据
ssl_session_timeout 5m; # 设置 SSL 会话超时时间为5分钟
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_prefer_server_ciphers on;
location ~ \.html$ {
root html;
index index.html index.htm;
}
}
}
# ssl_ciphers:指定可用的加密套件,这里设置了一组安全的加密套件,以确保安全的通信。
# ssl_protocols:指定支持的 SSL/TLS 协议版本,这里设置了支持 TLSv1、TLSv1.1 和 TLSv1.2。
# ssl_prefer_server_ciphers on;:指定是否优先使用服务器端的加密套件。
# location ~ \.html$ { ... }:这是一个 Nginx 的 location 块,用于匹配以 .html 结尾的请求。在这个块中,设置了请求的根目录为 html,并指定了默认的索引文件为 index.html 或 index.htm。
5. 生成镜像
[root@localhost nginx]# docker build -t nginx:centos .
[root@localhost nginx]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
nginx centos 661cbccabf64 19 seconds ago 595MB
nginx latest 7383c266ef25 8 days ago 188MB
centos 7 eeb6ee3f44bd 2 years ago 204MB
6. 启动镜像容器
[root@localhost nginx]# docker run -itd --name n1 -v /lnmp/nginx/html/:/usr/local/nginx/html/ -p 80:80 -p 443:443 nginx:centos
33427c34e854811db1969a2d62e021b1e092387b5a3dcf3b4211589a942c16b9
[root@localhost nginx]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
33427c34e854 nginx:centos "/usr/local/nginx/sb…" 3 seconds ago Up 1 second 0.0.0.0:80->80/tcp, :::80->80/tcp, 0.0.0.0:443->443/tcp, :::443->443/tcp n1
7. 验证 nginx
查看目录:
[root@localhost nginx]# echo "welcom to nginx" > /lnmp/nginx/html/index.html
[root@localhost nginx]# tree /lnmp/nginx/ -L 2
/lnmp/nginx/
├── cert
│ ├── ca-key.pem
│ ├── ca.pem
│ ├── ca.srl
│ ├── server-cert.pem
│ ├── server.csr
│ └── server-key.pem
├── Dockerfile
├── html
│ ├── index.html
│ └── wordpress
├── nginx-1.24.0.tar.gz
├── nginx.conf
└── wordpress-4.9.4-zh_CN.tar.gz
访问https://192.168.190.108/ :