• docker项目ssl 安全证书的种种


    一,证书挂着宿主的nginx上

    这个很简单,只需要修改宿主nginx的配置文件即可

    server {
            listen 443 ssl default;
            server_name www.abc.com; #项目域名
            ssl_certificate "cert/ssl_certificate.pem"; #证书文件
            ssl_certificate_key "cert/ssl_certificate.key"; #秘钥文件
            ssl_session_cache shared:SSL:1m;
            ssl_session_timeout  10m;
            ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE:ECDH:AES:HIGH:!NULL:!aNULL:!MD5:!ADH:!RC4; #SSL算法加密选项
            ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
            ssl_prefer_server_ciphers on;
            location / {
                proxy_redirect off;
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
                proxy_pass http://127.0.0.1:9001; #指向本机docker 容器端口
            }
            error_page 404 /404.html;
                location = /40x.html {
            }
            error_page 500 502 503 504 /50x.html;
                location = /50x.html {
            }
        }

    二,证书挂载到容器项目上

    这里以nginx为例,docker文件如下:

    FROM alpine
    #安装nginx服务器
    RUN apk add --update bash nginx
    #拷贝证书
    COPY ./cert /usr/nginx/cert
    #拷贝项目文件
    COPY ./www /usr/share/nginx/html
    #拷贝项目配置文件
    COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
    COPY ./nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf
    #切换目录设置权限
    WORKDIR /usr/share/nginx/html
    RUN chown -R daemon:daemon * && chmod -R 755 *
    EXPOSE 80
    EXPOSE 443
    #切换到nginx目录,启动nginx
    WORKDIR /run/nginx  
    ENTRYPOINT nginx -g "daemon off;"

    或直接 from nginx

    #这里我们用alpine简版就可以
    FROM nginx:alpine 
    #拷贝证书
    COPY ./cert /usr/nginx/cert
    #拷贝项目配置文件,配置文件主要是挂载证书开启443监听
    COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
    COPY ./nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf
    COPY ./www /usr/share/nginx/html/
    WORKDIR /usr/share/nginx/html/
    RUN chown -R daemon:daemon * && chmod -R 755 *
    EXPOSE 80
    EXPOSE 443

    nginx 配置文件

    1) nginx.conf

    user nginx;
    worker_processes  1;
    
    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;
    
    
    events {
        worker_connections  1024;
    }
    
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /var/log/nginx/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        keepalive_timeout  65;
    
        #gzip  on;
    
        include /etc/nginx/conf.d/*.conf;
    }

    2) conf.d/default.conf

    server {
        listen 80;
        listen 443 ssl; 开启443 ssl
        server_name www.abc.com;  #你的域名
        ssl_certificate "/usr/nginx/cert/cn.pem";  #证书文件
        ssl_certificate_key "/usr/nginx/cert/cn.key"; #证书秘钥
    
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }
    }

     三,spingboot项目内部挂在证书

    项目目录结构如下:

    即我们在项目根目录创建一个cert目录里面存放证书,然后我们修改项目配置文件application.yml挂上证书

    server:
      ssl:
        key-store: classpath:cert/ssl_certificate.pfx #证书文件
        key-store-password: 123456 #证书密码

    打包成docker image

     docker build -t springio/demo-docker .

    运行 

     docker run -t -p 8433:8080 springio/demo-docker

    本地输入http://www.abc.com:8433 会提示

    Bad Request
    This combination of host and port requires TLS.

    直接改为 https://www.abc.com:8433 访问正常

    四,使用openssl生成不受信任的证书

    上面两种方法都是在我们有证书的情况,如果你没有证书,可以使用openssl生产一个测试证书,在我们的Dokcerfile中加入证书生成

    FROM openjdk
    VOLUME /tmp
    ADD demo-docker-0.0.1-SNAPSHOT.war app.war
    RUN sh -c 'touch /app.war'
    RUN echo "Asia/Shanghai" > /etc/timezone
    ENV JAVA_OPTS=""
    ENV spring.profiles.active="prod"
    
    #以下是生成证书
    #定义签名密码
    ENV certPassword 123456 
    RUN openssl genrsa -des3 -passout pass:${certPassword} -out server.key 2048
    RUN openssl rsa -passin pass:${certPassword} -in server.key -out server.key
    RUN openssl req -sha256 -new -key server.key -out server.csr -subj '/CN=www.abc.com' #这里是证书绑定的域名
    RUN openssl x509 -req -sha256 -days 365 -in server.csr -signkey server.key -out server.crt
    RUN openssl pkcs12 -export -out server.pfx -inkey server.key -in server.crt -certfile server.crt -passout pass:${certPassword}
    #将证书文件绑定到项目中
    ENV key-store="server.pfx"
    #将证书密码传递给项目
    ENV key-password=${certPassword}
    #编译选项
    ENTRYPOINT ["java", "-jar", "/app.war"]

    这里有两点要注意,dockerfile文件中FROM 不能来源于简化版即不是“FROM openjdk:8-jdk-alpine” ,因为alpine版本的jdk中不包含openssl,关于openssl详细使用可以参考这里 https://www.cnblogs.com/yangxiaolan/p/6256838.html

    对应的项目配置文件application.yml内容如下

    server:
      ssl:
        key-store: ${key-store} #接收证书文件
        key-store-password: ${key-password} #接收证书密码

     启动docker项目,浏览器输入 https://www.abc.com,会提示证书不受信任

    登录到docker bash 会看到对应的证书文件

    五,使用Let's Encrypt 生成受信任的证书

     Let's Encrypt生成证书有多种方式: 

    Plugin

    认证

    安装

    备注

    认证方式 (端口)

    apache

    Y

    Y

    自动获取和安装证书,适用于Apache2.4 on OSes with libaugeas0 1.0+。

    tls-sni-01 (443)

    webroot

    Y

    N

    通过webserver的root目录认证来获取证书,适用于处于运行状态的webserver。

    http-01 (80)

    nginx

    Y

    Y

    自动获取和安装证书,适用于Nginx。

    tls-sni-01 (443)

    standalone

    Y

    N

    通过letsencrypt自带的standalone服务来获取证书,standalone服务将占用服务器的80或443端口,这就意味着服务器本身的webserver需要处于关闭状态,除非它使用特殊端口。

    http-01 (80) or tls-sni-01 (443)

    DNS plugins

    Y

    N

    通过修改DNS记录来认证域名所有者以获取证书,这是使用letsencrypt为通配符域名获取证书的唯一方式。

    dns-01 (53)

    manual

    Y

    N

    以用户自定义的方式获取证书,根据提示指令,用户自己来完成域名认证。即使用交互式或脚本钩子的方式获取证书。

    http-01 (80), dns-01 (53) or tls-sni-01 (443)

    使用,Let's Encrypt生成证书必须在你的服务器上完成,而且必须确认你的域名已经解析到服务器上,否者无法完成验证,会提示没有权限“ urn:ietf:params:acme:error:unauthorized” ,这里介绍两种比较常用方式

    必须保证你在网站在运行,可以通过域名的80端口正常访问,需要在你的服务器上安装 certbot,最好不要使用yum install certbot 安装 这里会有依赖问题,因为Certbot是Python程序,最好先创建一个Python虚拟环境,然后再安装Certbot,具体步骤如下:    

    sudo yum install python-virtualenv #安装虚拟环境软件包(针对于Python2.7)
    sudo virtualenv /usr/local/python-certbot #创建虚拟环境
    source /usr/local/python-certbot/bin/activate #激活虚拟环境
    pip install certbot #安装Certbot
    pip install certbot-nginx #安装nginx插件,如果不使用 nginx模式生成证书可不需要
    

     也可以不安装certbot,使用“quay.io/letsencrypt/letsencrypt”镜像完成只需要在你的服务器上 docker pull quay.io/letsencrypt/letsencrypt 然后通过下面命令启动

    1,webroot方式:

    执行证书生成命令

    certbot certonly --webroot -w /usr/share/nginx/html -d www.abc.com -m ejiyuan@163.com --agree-tos

    docker 镜像方式

    docker run --rm -p 8770:80 -v /etc/letsencrypt:/etc/letsencrypt -v /usr/share/nginx/html:/usr/share/nginx/html quay.io/letsencrypt/letsencrypt auth --webroot -w /usr/share/nginx/html -d q.meylink.cn -m ejiyuan@263.com --agree-tos 

      -w 指定网站项目目录,这个项目必须是可用的,而且是通过你的域名80端口能正常访问的

      -d 指定生成蒸鱼的域名 这个域名必须已经解析到执行命令的本服务器上

      -m 指定一个email 最好是真实的电邮地址

     webroot方式,必须你的服务的 80 端口上运行一个能处理静态文件的 web 服务,我这里 nginx 为例 (注意,webroot + nginx 与 nginx 是完全不同的两种方式)

        server {
            listen       80 default_server;  # 必须是80端口
            server_name  www.abc.com;  # 必须能够解析到本机
            root         /usr/share/nginx/html; #项目所在目录
            location / {
               index index.html;
            }
        }
    

    在执行命令后,certbot 会向指定的 webroot 目录中添加一个随机文件,随后 letsencrypt 会通过 http 访问那个文件,比如 http://www.abc.com/.well-known/acme-challenge/gdEMr7ZXOiZE51he9QwuvnbrrTnkwlpFhNAcArBt2uE, 如果能返回正确的数据则通过认证,否则认证失败,执行结果如下:

     2,standalone方式:

        这个方式不需要先部署项目,但是必须保证你的域名能解析到服务器上

    certbot certonly --standalone -n --agree-tos --email you@gmail.com --preferred-challenges http -d you.domain.com

     docker 镜像方式

    docker run --rm -p 80:80 -p 443:443 -v /etc/letsencrypt:/etc/letsencrypt  quay.io/letsencrypt/letsencrypt auth --standalone -m ejiyuan@email.com --agree-tos -d you.domain.com

    -n 非交互式
    --email 指定账户
    --agree-tos 同意服务协议
    --preferred-challenges http 使用http模式 必须保证80端口没有被占用
    --preferred-challenges tls-sni:使用443端口必须保证80端口没有被占用

    默认 standalone 是使用 443 端口,也就是说要停止服务器现在占用 443 端口的进程,我们也可以将其改为使用 80 端口,同样道理,这时需要停止 80 端口的占用,执行结果

     3,apache与nginx模式,可是非常简单的生成并挂在证书这里以nginx为例

      保证你的域名可以解析到本机,并且nginx已安装,设置nginx配置文件  

    server {
            server_name you.domain.com;
    }

    然后执行

    certbot --nginx -d a.abc.com

    执行结果如下:

    nginx配置文件修改如下:

    server {
      server_name a.abc.com;
      ....
      #一下内容是 Certbot 加入
      listen 443 ssl; # managed by Certbot
      ssl_certificate /etc/letsencrypt/live/a.abc.com/fullchain.pem; # managed by Certbot
      ssl_certificate_key /etc/letsencrypt/live/a.abc.com/privkey.pem; # managed by Certbot
      include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
      ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
    }

    4,生成证书部署docker image

    FROM alpine
    #安装证书生成工具
    RUN apk add --update bash certbot
    RUN apk add --no-cache libressl
    #安装nginx服务器
    RUN apk add --update bash nginx
    #拷贝项目文件
    COPY ./www /usr/share/nginx/html
    #拷贝项目配置文件
    COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
    COPY ./nginx/conf.d/default.conf /etc/nginx/conf.d/default.conf
    #挂在外部路径方便查看生产的证书与容器内部nginx配置
    VOLUME ["/etc/letsencrypt","etc/nginx"]
    #切换目录设置权限
    WORKDIR /usr/share/nginx/html
    RUN chown -R daemon:daemon * && chmod -R 755 *
    EXPOSE 80
    EXPOSE 443
    #切换到nginx目录,启动nginx
    WORKDIR /run/nginx
    ENTRYPOINT certbot certonly --standalone -n --agree-tos --email ejiyuan@gmail.com --preferred-challenges http -d you.domain.com && nginx -g "daemon off;"

    因一个Dockerfile不能同时FROM certbot又FROM nginx,所以这里使用alpine(它一个小型的 linux发型版本,想了解他看这里:Alpine Linux 使用简介)然后安装 certbot和nginx

     对应的nginx配置文件nginx.conf如下:

    user nginx;
    worker_processes  1;
    
    error_log  /var/log/nginx/error.log warn;
    pid        /var/run/nginx.pid;
    
    
    events {
        worker_connections  1024;
    }
    
    
    http {
        include       /etc/nginx/mime.types;
        default_type  application/octet-stream;
    
        log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                          '$status $body_bytes_sent "$http_referer" '
                          '"$http_user_agent" "$http_x_forwarded_for"';
    
        access_log  /var/log/nginx/access.log  main;
    
        sendfile        on;
        #tcp_nopush     on;
    
        keepalive_timeout  65;
    
        #gzip  on;
    
        include /etc/nginx/conf.d/*.conf;
    }

    conf.d/default.conf

    server {
        listen 80;
        listen 443 ssl;
        server_name www.abc.cn; #配置的域名
         ssl_certificate "/etc/letsencrypt/live/www.abc.cn/fullchain.pem";  #letsencrypt证书路径,证书会自动生成在这个路径下面
        ssl_certificate_key "/etc/letsencrypt/live/www.abc.cn/privkey.pem"; #letsencrypt秘钥路径,证书秘钥会自动生成在这个路径下面
        location / {
            root   /usr/share/nginx/html;
            index  index.html index.htm;
        }
    }

    六,参考文档

    全民https时代,Let's Encrypt免费SSL证书的申请及使用(Tomcat版)

    https 证书工具 Letsencrypt 简单教程

    Certbot 自动化生成 https 证书

    Letsencrypt SSL免费证书申请(Docker)

    CentOS7运行Certbot提示:ImportError: 'pyOpenSSL' module missing required functionality. Try upgrading to v0.14 or newer.

    Docker:使用Dockerfile构建Nginx镜像 

    通过Laradock学Docker-HTTPS

    给Docker中的Nginx搭建HTTPS环境

  • 相关阅读:
    NOIP知识点&&模板整理【更新中】
    qbxt DAY7 T4
    qbxt DAY7 T2
    qbxt DAY 6 T3 柯西不等式和拉格朗日不等式
    qbxt DAY4 T4
    qbxt DAY4 T3
    #98. 表达式计算 杂想
    扫描线入门学习笔记 (主要讲解代码实现)
    学OI要知道的基础知识(咕咕咕)
    主定理学习笔记(总结向)
  • 原文地址:https://www.cnblogs.com/ejiyuan/p/10335396.html
Copyright © 2020-2023  润新知