使用nginx进行双向认证,可以实现吊销客户端证书。

 在k8s中用ingress配置tls可以实现客户端认证,但吊销功能是不正常的,反复测试未能实现(k8s1.14.8版本)


1 nginx实现Https双向认证


    双向认证可自主实现,与机构签发的服务器server证书无关,即只需要自己创建ca和client证书即可。

    如果没有机构签发的证书,也可以用自建的ca签发自己本地的server证书,然后再签发client,实现本地环境的双向认证,常用于测试中。


1.1 准备nginx环境

  安装nginx
  yum -y install gcc gcc-c++ make libtool zlib zlib-devel openssl openssl-devel pcre pcre-devel
  rpm -ivh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
  yum install nginx -y 
  nginx -v
  systemctl start nginx


1.2 配置nginx

    修改nginx配置文件,已规划好证书路径名称等

    vi  /etc/nginx/conf.d/443.conf 

    其中ca.crl是吊销文件,在执行吊销后再启用该配置

server {
       listen 443 ssl;
       server_name www.younihao.com;
     
       ssl_certificate           /etc/nginx/ca/server/server.crt;
       ssl_certificate_key       /etc/nginx/ca/server/server.key;
       ssl_client_certificate    /etc/nginx/ca/private/ca.crt;
      
       ssl_session_timeout 5m;
       ssl_verify_client on;
       
       ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
       ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
       ssl_prefer_server_ciphers on;
#      ssl_crl /etc/nginx/ca/private/ca.crl;
 
       charset utf-8;
       access_log logs/host.access.log main;
       error_page 500 502 503 504 /50x.html;
       location = /50x.html {
           root html;
       }
 
       location = /favicon.ico {
           log_not_found off;
           access_log off;
           expires 90d;
       }
       location / {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }

    }


1.3 创建自签CA,server,client证书

    1.3.1 创建证书目录

cd /etc/nginx/
mkdir ca
cd ca/
mkdir newcerts private conf server users

    1.3.2 创建openssl配置文件

vi /etc/nginx/ca/conf/openssl.conf
[ ca ]
default_ca = myserver
 
[ myserver ]
dir = /etc/nginx/ca
database = /etc/nginx/ca/index.txt
new_certs_dir = /etc/nginx/ca/newcerts
certificate = /etc/nginx/ca/private/ca.crt
serial = /etc/nginx/ca/serial
private_key = /etc/nginx/ca/private/ca.key
RANDFILE = /etc/nginx/ca/private/.rand
 
default_days = 3650
default_crl_days = 3650
default_md = sha256
unique_subject = no
 
policy = policy_any
 
[ policy_any ]
countryName = match
stateOrProvinceName = match
organizationName = match
localityName = optional
commonName = supplied
emailAddress = optional

    1.3.3 生成ca,server,client证书

 生成ca
 openssl genrsa -out /etc/nginx/ca/private/ca.key 
 openssl req -new -key /etc/nginx/ca/private/ca.key -out private/ca.csr
 openssl x509 -req -days 3650 -in /etc/nginx/ca/private/ca.csr -signkey /etc/nginx/ca/private/ca.key -out /etc/nginx/ca/private/ca.crt
 
 设置起始序列号
 echo FACE > /etc/nginx/ca/serial
 创建CA键库
 touch /etc/nginx/ca/index.txt
 创建一个证书撤销列表
 openssl ca -gencrl -out /etc/nginx/ca/private/ca.crl -crldays 3670 -config "/etc/nginx/ca/conf/openssl.conf"
 
 生成自签server证书
 openssl genrsa -out /etc/nginx/ca/server/server.key 2048
 openssl req -new -key /etc/nginx/ca/server/server.key -out /etc/nginx/ca/server/server.csr
 openssl ca -in /etc/nginx/ca/server/server.csr -cert /etc/nginx/ca/private/ca.crt -keyfile /etc/nginx/ca/private/ca.key -out /etc/nginx/ca/server/server.crt -config "/etc/nginx/ca/conf/openssl.conf"
 
 生成client证书
 openssl genrsa -out /etc/nginx/ca/users/client.key 2048
 openssl req -new -key /etc/nginx/ca/users/client.key -out /etc/nginx/ca/users/client.csr
 openssl ca -in /etc/nginx/ca/users/client.csr -cert /etc/nginx/ca/private/ca.crt -keyfile /etc/nginx/ca/private/ca.key -out /etc/nginx/ca/users/client.crt -config "/etc/nginx/ca/conf/openssl.conf"
上面req在创建证书请求文件的时候,需要输入一系列的参数可参看下图
其中Common Name项,server证书请求时需要填域名,ca与client不做要求;其他项保持一致。

image.png

image.png

image.png

    1.3.4 将客户端证书转换成PKCS12文件

    生成该文件时候需要设置一个密码,浏览器添加该证书时候会用到。

openssl pkcs12 -export -clcerts -in /etc/nginx/ca/users/client.crt -inkey /etc/nginx/ca/users/client.key -out /etc/nginx/ca/users/client.p12


1.4 验证测试双向认证

   1.4.1 修改好了nginx配置,证书路径名称都准确无误

        nginx -t   #检查配置语法格式

        nginx -s reload  ##加载新配置


    1.4.2 下载client.p12文件

        sz /etc/nginx/ca/users/client.p12


    1.4.3 浏览器添加客户端证书

            每个浏览器方法不一样,自行百度p12证书文件导入,导入证书后重启浏览器。

            浏览器访问https://www.younihao.com 会跳出证书选择页面,选定myclient证书,就可以正常访问啦

            没有证书访问会得到400 Bad Request(No required SSL certificate was sent)错误


 1.5 吊销客户端证书

    1.5.1 查看serial号

openssl x509 -in /etc/nginx/ca/users/client.crt -noout -serial -subject

[root@loaclhost ]# openssl x509 -in /etc/nginx/ca/users/client.crt -noout -serial -subject
serial=FACF   ##查到serial号是FACF
subject= /C=cn/ST=henan/O=supercom/L=zhengzhou/CN=myclient

    1.5.2 创建crlnumber

echo 01 > crlnumber	##第一次增加这个

    1.5.3 ssl增加吊销配置

vi /etc/nginx/ca/conf/openssl.conf  ##增加下面配置
crlnumber= /etc/nginx/ca/crlnumber

    1.5.4 执行吊销client证书

openssl ca -revoke /etc/nginx/ca/newcerts/FACF.pem -config "/etc/nginx/ca/conf/openssl.conf"

    1.5.5 重新乘车crl吊销列表

openssl ca -gencrl -out /etc/nginx/ca/private/ca.crl -config "/etc/nginx/ca/conf/openssl.conf"

查看吊销是否成功
openssl crl -in /etc/nginx/ca/private/ca.crl -noout -text

    1.5.6 调整nginx参数

vi /etc/nginx/conf.d/443.conf ##增加启用crl配置
ssl_crl /etc/nginx/ca/private/ca.crl;
nginx -t  #验证重启
nginx -s reload

    1.5.7 验证吊销结果

    登录浏览器再次访问,选择对应证书,依旧被拒绝访问即为成功。


1.6 nginx认证参考

https://blog.csdn.net/rexueqingchun/article/details/82251563
https://help.aliyun.com/document_detail/54508.html?spm=5176.2020520152.0.0.61bb16ddEk6YWC


2 ingress实现Https双向认证(无吊销功能)


 2.1这里是ingress示例

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/auth-tls-verify-client: "on"
    nginx.ingress.kubernetes.io/auth-tls-secret: "default/ca-secret"
    nginx.ingress.kubernetes.io/auth-tls-verify-depth: "1"
    nginx.ingress.kubernetes.io/auth-tls-error-page: "http://www.mysite.com/error-cert.html"
    nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream: "true"
  name: nginx-test
  namespace: default
spec:
  rules:
  - host: mydomain.com
    http:
      paths:
      - backend:
          serviceName: http-svc
          servicePort: 80
        path: /
  tls:
  - hosts:
    - mydomain.com
    secretName: tls-secret

   

 2.2 创建tls-secret和ca-secret

tls-secret可以使用自建的,也可以使用机构签发的服务器证书
kubectl create secret generic tls-secret --from-file=tls.crt=server.crt --from-file=tls.key=server.key

ca-secret到自己的ca目录创建
cd /etc/nginx/ca/private
kubectl create secret generic ca-secret --from-file=ca.crt=ca.crt

然后创建ingress
kubectl create -f ingress.yaml


 2.3 添加其他annotations

ingress 跨域问题 需要在ingress中添加配置下面annotations
   nginx.ingress.kubernetes.io/cors-allow-headers: >-
      DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization
    nginx.ingress.kubernetes.io/cors-allow-methods: 'PUT, GET, POST, OPTIONS'
    nginx.ingress.kubernetes.io/cors-allow-origin: '*'
    nginx.ingress.kubernetes.io/enable-cors: 'true'
    
ingress  强制443 
    nginx.ingress.kubernetes.io/ssl-redirect: 'true'

ingress 白名单访问
    nginx.ingress.kubernetes.io/whitelist-source-range: '192.168.5.3'

   

 2.4 ingress 可参考

https://kubernetes.github.io/ingress-nginx/examples/auth/client-certs/
https://kubernetes.github.io/ingress-nginx/examples/PREREQUISITES/#client-certificate-authentication
https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/