濮阳杆衣贸易有限公司

主頁(yè) > 知識(shí)庫(kù) > 詳解Nginx SSL快速雙向認(rèn)證配置(腳本)

詳解Nginx SSL快速雙向認(rèn)證配置(腳本)

熱門(mén)標(biāo)簽:德州外呼系統(tǒng)排名 貴州全自動(dòng)外呼系統(tǒng)廠家 機(jī)器人電銷(xiāo)有什么用 福州外呼系統(tǒng)中間件 好看的地圖標(biāo)注圖標(biāo)下載 地圖標(biāo)注員怎么去做 上海電銷(xiāo)卡外呼系統(tǒng)廠家 威海人工智能電銷(xiāo)機(jī)器人系統(tǒng) 百度地圖標(biāo)注備注

目前遇到一個(gè)項(xiàng)目有安全性要求,要求只有個(gè)別用戶有權(quán)限訪問(wèn)。本著能用配置解決就絕不用代碼解決的原則,在Nginx上做一下限制和修改即可。

這種需求其實(shí)實(shí)現(xiàn)方式很多,經(jīng)過(guò)綜合評(píng)估考慮,覺(jué)得SSL雙向認(rèn)證方案對(duì)用戶使用最簡(jiǎn)單,遂決定用此方案。

注: 本方案在Ubuntu Server 16.04 LTS實(shí)施,其他操作系統(tǒng)請(qǐng)酌情修改

SSL雙向認(rèn)證

絕大多數(shù)SSL應(yīng)用都以單向認(rèn)證為主,即客戶端只要信任服務(wù)端,就可以使用服務(wù)端的公鑰加密后向服務(wù)端發(fā)起請(qǐng)求,由服務(wù)端的私鑰解密之后獲得請(qǐng)求數(shù)據(jù)。

如果這個(gè)過(guò)程反過(guò)來(lái),讓服務(wù)端信任客戶端,服務(wù)端使用客戶端的公鑰加密之后將數(shù)據(jù)返回給客戶端,其實(shí)也是可以做到的,原理和實(shí)現(xiàn)跟單向認(rèn)證都差不多。

服務(wù)端信任客戶端的操作往往也會(huì)伴隨著客戶端認(rèn)證服務(wù)端的過(guò)程,所以讓服務(wù)端信任客戶端的SSL認(rèn)證方式往往也被稱為SSL雙向認(rèn)證,并且要配置SSL雙向認(rèn)證必須先開(kāi)啟服務(wù)端SSL,先配置客戶端信任服務(wù)端。

Nginx的SSL雙向認(rèn)證配置

第一步 開(kāi)啟https訪問(wèn)

根據(jù)理論知識(shí),我們必須先開(kāi)啟Nginx的SSL配置,即啟用https。這個(gè)過(guò)程較為簡(jiǎn)單,目前有l(wèi)et's encrypt這種免費(fèi)的證書(shū)方案,再也不用發(fā)愁自己搭建CA自簽了。申請(qǐng)免費(fèi)證書(shū)的過(guò)程略過(guò),直接貼啟用https的配置:

server {
 listen 80;
 listen 443 ssl http2;
 server_name example.com;

 ssl_certificate /etc/letsencrypt/live/example.com/fullchain.pem;
 ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
 # 只有Nginx >= 1.13.0 版本才支持TLSv1.3協(xié)議
 # ssl_protocols TLSv1.3;
 # Nginx低于1.13.0版本用這個(gè)配置
 ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
 ssl_prefer_server_ciphers on; 
 ssl_dhparam dhparam.pem; # openssl dhparam -out /etc/nginx/dhparam.pem 4096
 ssl_ciphers 'EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH';
 ssl_ecdh_curve secp384r1; # Requires nginx >= 1.1.0
 ssl_session_timeout 10m;
 ssl_session_cache shared:SSL:10m;
 ssl_session_tickets off; # Requires nginx >= 1.5.9
 ssl_stapling on; # Requires nginx >= 1.3.7
 ssl_stapling_verify on; # Requires nginx => 1.3.7
 resolver 223.5.5.5 114.114.114.114 valid=300s;
 resolver_timeout 5s; 
 # 啟用HSTS的配置,如果你的域名下還有非標(biāo)準(zhǔn)端口訪問(wèn)的http應(yīng)用,請(qǐng)勿啟用HSTS
 # add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
 # 下面這個(gè)配置會(huì)拒絕Frame標(biāo)簽內(nèi)容,請(qǐng)確認(rèn)你的網(wǎng)站沒(méi)有frame / iframe
 add_header X-Frame-Options DENY;
 add_header X-Content-Type-Options nosniff;
 add_header X-XSS-Protection "1; mode=block";

 # 為了let's encrypt續(xù)期用,不用let's encrypt不需要這個(gè)location
 location /.well-known {
  root /usr/share/nginx/html;
 }

  ... SNIP ...

 # 強(qiáng)制http跳轉(zhuǎn)為https
 if ($scheme != "https") {
  return 301 https://$http_host$request_uri;
 }
}

以上那一大堆ssl的配置參考來(lái)自于: https://cipherli.st/ 加強(qiáng)SSL的安全性配置

特別注意最后的強(qiáng)制https跳轉(zhuǎn),我們的目的是SSL雙向認(rèn)證,不走h(yuǎn)ttps無(wú)任何意義,所以必須強(qiáng)制跳轉(zhuǎn)https。

第二步 生成客戶端證書(shū)并簽證(腳本)

這個(gè)過(guò)程詳細(xì)描述的文章太多了,這里就不啰嗦介紹openssl和簽證過(guò)程了,本篇內(nèi)容是快速生成雙向認(rèn)證配置的證書(shū),所以直接貼腳本就行了,命令都是參考互聯(lián)網(wǎng)上各種openssl雙向配置文檔,在此基礎(chǔ)之上進(jìn)行了命令上的簡(jiǎn)化與非交互式的支持。

整個(gè)目錄結(jié)構(gòu)如圖:

# tree /etc/nginx/ssl_certs/
/etc/nginx/ssl_certs/
├── create_ca_cert.sh
├── create_client_cert.sh
├── revoke_cert.sh

0 directories, 3 files

自行創(chuàng)建/etc/nginx/ssl_certs/,放入三個(gè)腳本,分別用于生成CA證書(shū)以及CA目錄(create_ca_cert.sh腳本的作用,只有第一次需要運(yùn)行),創(chuàng)建客戶端證書(shū),并用CA證書(shū)簽證(create_client_cert.sh腳本的作用,必須先生成CA證書(shū)),revoke_cert.sh腳本用于吊銷(xiāo)證書(shū),需要收回權(quán)限的時(shí)候可以使用。

每個(gè)腳本內(nèi)容如下:

create_ca_cert.sh

#!/bin/bash -e

# 創(chuàng)建CA根證書(shū)
# 非交互式方式創(chuàng)建以下內(nèi)容:
# 國(guó)家名(2個(gè)字母的代號(hào))
C=CN
# 省
ST=Shannxi
# 市
L=Xian
# 公司名
O=My Company
# 組織或部門(mén)名
OU=技術(shù)部
# 服務(wù)器FQDN或頒發(fā)者名
CN=www.example.com
# 郵箱地址
emailAddress=admin@example.com

mkdir -p ./demoCA/{private,newcerts}
touch ./demoCA/index.txt
[ ! -f ./demoCA/seria ] && echo 01 > ./demoCA/serial
[ ! -f ./demoCA/crlnumber ] && echo 01 > ./demoCA/crlnumber
[ ! -f ./demoCA/cacert.pem ] && openssl req -utf8 -new -x509 -days 36500 -newkey rsa:2048 -nodes -keyout ./demoCA/private/cakey.pem -out ./demoCA/cacert.pem -subj "/C=${C}/ST=${ST}/L=${L}/O=${O}/OU=${OU}/CN=${CN}/emailAddress=${emailAddress}"
[ ! -f ./demoCA/private/ca.crl ] && openssl ca -crldays 36500 -gencrl -out "./demoCA/private/ca.crl"

create_client_cert.sh

#!/bin/bash -e

show_help() {
  echo "$0 [-h|-?|--help] [--ou ou] [--cn cn] [--email email]"
  echo "-h|-?|--help  顯示幫助"
  echo "--ou      設(shè)置組織或部門(mén)名,如: 技術(shù)部"
  echo "--cn      設(shè)置FQDN或所有者名,如: 馮宇"
  echo "--email     設(shè)置FQDN或所有者郵件,如: fengyu@example.com"
}

while [[ $# -gt 0 ]]
do
  case $1 in
    -h|-\&;|--help)
      show_help
      exit 0
      ;;
    --ou)
      OU="${2}"
      shift
      ;;    
    --cn)
      CN="${2}"      
      shift
      ;;
    --email)
      emailAddress="${2}"      
      shift
      ;;
    --)
      shift
      break
    ;;
    *)
      echo -e "Error: $0 invalid option '$1'\nTry '$0 --help' for more information.\n" >&2
      exit 1
    ;;
  esac
shift
done

# 創(chuàng)建客戶端證書(shū)
# 非交互式方式創(chuàng)建以下內(nèi)容:
# 國(guó)家名(2個(gè)字母的代號(hào))
C=CN
# 省
ST=Shannxi
# 市
L=Xian
# 公司名
O=My Company
# 組織或部門(mén)名
OU=${OU:-測(cè)試部門(mén)}
# 服務(wù)器FQDN或授予者名
CN=${CN:-demo}
# 郵箱地址
emailAddress=${emailAddress:-demo@example.com}

mkdir -p "${CN}"

[ ! -f "${CN}/${CN}.key" ] && openssl req -utf8 -nodes -newkey rsa:2048 -keyout "${CN}/${CN}.key" -new -days 36500 -out "${CN}/${CN}.csr" -subj "/C=${C}/ST=${ST}/L=${L}/O=${O}/OU=${OU}/CN=${CN}/emailAddress=${emailAddress}"
[ ! -f "${CN}/${CN}.crt" ] && openssl ca -utf8 -batch -days 36500 -in "${CN}/${CN}.csr" -out "${CN}/${CN}.crt"
[ ! -f "${CN}/${CN}.p12" ] && openssl pkcs12 -export -clcerts -CApath ./demoCA/ -inkey "${CN}/${CN}.key" -in "${CN}/${CN}.crt" -certfile "./demoCA/cacert.pem" -passout pass: -out "${CN}/${CN}.p12"

revoke_cert.sh

#!/bin/bash -e

# 吊銷(xiāo)一個(gè)簽證過(guò)的證書(shū)

openssl ca -revoke "${1}/${1}.crt"
openssl ca -gencrl -out "./demoCA/private/ca.crl"

簡(jiǎn)單分析一波腳本,首先是創(chuàng)建CA,對(duì)于Ubuntu系統(tǒng)來(lái)說(shuō),/etc/ssl/openssl.cnf配置中默認(rèn)的CA路徑就是./demoCA,為了不改動(dòng)默認(rèn)配置,直接按照默認(rèn)配置的內(nèi)容創(chuàng)建這些目錄和文件即可。還有就是openssl子命令非常多,但是也和git一樣,可以合并命令,比如用一條命令同時(shí)生成私鑰和簽證請(qǐng)求openssl req -nodes -newkey rsa:2048 -keyout client.key -new -out client.csr,在req的同時(shí)就做了genrsa。由于創(chuàng)建CA腳本只是第一次運(yùn)行需要,因此把證書(shū)配置直接寫(xiě)死在腳本中就完事了。

接下來(lái)是創(chuàng)建客戶端證書(shū),為了簡(jiǎn)化用戶的使用,在服務(wù)端幫助用戶生成證書(shū)并簽證,把簽證過(guò)的證書(shū)下發(fā)給用戶就可以了。由于用戶可能是不同部門(mén),不同姓名,不同郵件地址,因此將這三個(gè)參數(shù)外部化,做一下參數(shù)解析,加上友好的命令行提示防止遺忘。這個(gè)腳本特別注意最后一行,會(huì)生成一個(gè)PKCS12格式的證書(shū)。openssl默認(rèn)產(chǎn)生的證書(shū)格式都是PEM的,會(huì)將公鑰和私鑰分開(kāi),但是瀏覽器導(dǎo)入的時(shí)候需要將這些內(nèi)容合并起來(lái)形成證書(shū)鏈,所以需要將簽證過(guò)的證書(shū)和私鑰文件合并成一個(gè)PKCS12格式的證書(shū),直接將這個(gè).p12格式的證書(shū)交給用戶就可以了。

最后是吊銷(xiāo)證書(shū)了,當(dāng)希望收回某個(gè)用戶的訪問(wèn)權(quán)限時(shí),直接運(yùn)行這個(gè)腳本跟上目錄名就可以了。

接下來(lái)運(yùn)行創(chuàng)建CA的腳本:

./create_ca_cert.sh

Generating a 2048 bit RSA private key
.......................+++
........................................................................................................+++
writing new private key to './demoCA/private/cakey.pem'
-----
Using configuration from /usr/ssl/openssl.cnf

此時(shí)產(chǎn)生的./demoCA目錄結(jié)構(gòu)如下:

demoCA/
├── cacert.pem
├── crlnumber
├── crlnumber.old
├── index.txt
├── newcerts
├── private
│  ├── ca.crl
│  └── cakey.pem
└── serial

2 directories, 7 files

此時(shí)就可以配置nginx了,在上面單向ssl的配置中,追加以下配置:

 ssl_client_certificate ssl_certs/demoCA/cacert.pem;
 ssl_crl ssl_certs/demoCA/private/ca.crl;
 ssl_verify_client on;

ssl_client_certificate就是客戶端證書(shū)的CA證書(shū)了,代表此CA簽發(fā)的證書(shū)都是可信的,ssl_verify_client on;代表強(qiáng)制啟用客戶端認(rèn)證,非法客戶端(無(wú)證書(shū),證書(shū)不可信)都會(huì)返回400錯(cuò)。

特別注意ssl_crl這個(gè)配置,代表Nginx會(huì)讀取一個(gè)CRL(Certificate Revoke List)文件,之前說(shuō)過(guò),可能會(huì)有收回用戶權(quán)限的需求,因此我們必須有吊銷(xiāo)證書(shū)的功能,產(chǎn)生一個(gè)CRL文件讓Nginx知道哪些證書(shū)被吊銷(xiāo)了即可。

注意: Nginx配置都是靜態(tài)的,讀取配置文件之后都會(huì)加載到內(nèi)存中,即使文件內(nèi)容變化也不會(huì)重新讀取。因此當(dāng)CRL文件發(fā)生變更之后,Nginx并不能意識(shí)到有新的證書(shū)被吊銷(xiāo)了,所以必須使用reload指令讓Nginx重新讀取配置文件: service nginx reloadnginx -s reload

此時(shí)重啟Nginx服務(wù),就可以完成SSL雙向認(rèn)證配置了。

我們簽發(fā)一個(gè)證書(shū)看看:

 ./create_client_cert.sh --ou 財(cái)務(wù)部 --cn 財(cái)務(wù)經(jīng)理 --email cy@example.com
Generating a 2048 bit RSA private key
................................+++
.............................................................................+++
writing new private key to '財(cái)務(wù)經(jīng)理/財(cái)務(wù)經(jīng)理.key'
-----
Using configuration from /usr/ssl/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
    Serial Number: 1 (0x1)
    Validity
      Not Before: Jun 14 16:03:46 2018 GMT
      Not After : May 21 16:03:46 2118 GMT
    Subject:
      countryName        = CN
      stateOrProvinceName    = Shannxi
      organizationName     = My Company
      organizationalUnitName  = \U8D22\U52A1\U90E8
      commonName        = \U8D22\U52A1\U7ECF\U7406
      emailAddress       = cy@example.com
    X509v3 extensions:
      X509v3 Basic Constraints:
        CA:FALSE
      Netscape Comment:
        OpenSSL Generated Certificate
      X509v3 Subject Key Identifier:
        B5:91:0B:1F:FC:25:3B:2A:F9:EF:39:39:51:E3:1F:64:78:8A:C3:75
      X509v3 Authority Key Identifier:
        keyid:86:55:76:15:A3:F5:58:CB:8F:39:A3:56:8E:FF:18:97:AE:27:60:0F

Certificate is to be certified until May 21 16:03:46 2118 GMT (36500 days)

Write out database with 1 new entries
Data Base Updated

tree 財(cái)務(wù)經(jīng)理/
財(cái)務(wù)經(jīng)理/
├── 財(cái)務(wù)經(jīng)理.crt
├── 財(cái)務(wù)經(jīng)理.csr
├── 財(cái)務(wù)經(jīng)理.key
└── 財(cái)務(wù)經(jīng)理.p12

0 directories, 4 files

這個(gè)腳本生成了私鑰文件key,簽證請(qǐng)求文件csr,經(jīng)過(guò)CA簽證后的證書(shū)文件crt(里面沒(méi)有私鑰),以及將crt文件和key進(jìn)行bundle之后的PKCS12格式的證書(shū)文件p12,將p12文件下載到本地,雙擊一路Next導(dǎo)入證書(shū)即可。

注: 由于CA的證書(shū)文件不會(huì)發(fā)生變化,因此簽證新的客戶端證書(shū)不需要restart或reload nginx

這次打開(kāi)我們的網(wǎng)站https://www.example.com,瀏覽器就會(huì)提示我們選擇一個(gè)已有的客戶端證書(shū)進(jìn)行認(rèn)證了,沒(méi)問(wèn)題就可以看到網(wǎng)站內(nèi)容了

注: 每次導(dǎo)入新的證書(shū)之后,必須重啟瀏覽器才能提示使用新的證書(shū)文件

按照這種方式,有多少人需要授權(quán),就可以用這個(gè)腳本簽發(fā)多少個(gè)這樣的證書(shū),用戶將p12證書(shū)導(dǎo)入本地就可以正常訪問(wèn)網(wǎng)站了。

當(dāng)我們需要收回某人的權(quán)限的時(shí)候(比如離職了),我們需要吊銷(xiāo)他的證書(shū):

 ./revoke_cert.sh 財(cái)務(wù)經(jīng)理

Using configuration from /usr/ssl/openssl.cnf
Revoking Certificate 01.
Data Base Updated
Using configuration from /usr/ssl/openssl.cnf

service nginx reload

這個(gè)腳本會(huì)自動(dòng)吊銷(xiāo)他的簽證文件crt,并且自動(dòng)更新CRL文件。特別注意需要reload或restart nginx才能讓nginx重新加載CRL。這樣被吊銷(xiāo)的證書(shū)將無(wú)法訪問(wèn)網(wǎng)站了。

小結(jié)

本文我們通過(guò)Nginx配置SSL雙向認(rèn)證實(shí)現(xiàn)對(duì)客戶端的加密認(rèn)證,我們使用了簡(jiǎn)易的腳本幫助我們快速生成各種證書(shū)與簽證,免除記憶繁瑣openssl命令行,簡(jiǎn)化使用。

當(dāng)然這只是一個(gè)最小可用集,當(dāng)規(guī)模比較大的時(shí)候可能需要做很多改進(jìn),比如加入CA的web ui,直接可以操作簽證和吊銷(xiāo)證書(shū),并且可以自動(dòng)重啟nginx。

再比如CRL這種靜態(tài)配置文件不適合你的場(chǎng)景,希望的動(dòng)態(tài)更新吊銷(xiāo)證書(shū)列表,那么可以考慮OCSP方案,這個(gè)Nginx也是支持的,通過(guò)ssl_stapling_responder配置指定一個(gè)OCSP地址,這樣將不需要每次吊銷(xiāo)證書(shū)的時(shí)候都去重啟nginx了,openssl也提供了ocsp服務(wù)端的功能,這里就不贅述了,可以自行查找相關(guān)資料。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

標(biāo)簽:南陽(yáng) 邵陽(yáng) 岳陽(yáng) 泉州 葫蘆島 南陽(yáng) 撫州 白城

巨人網(wǎng)絡(luò)通訊聲明:本文標(biāo)題《詳解Nginx SSL快速雙向認(rèn)證配置(腳本)》,本文關(guān)鍵詞  詳解,Nginx,SSL,快速,雙向,;如發(fā)現(xiàn)本文內(nèi)容存在版權(quán)問(wèn)題,煩請(qǐng)?zhí)峁┫嚓P(guān)信息告之我們,我們將及時(shí)溝通與處理。本站內(nèi)容系統(tǒng)采集于網(wǎng)絡(luò),涉及言論、版權(quán)與本站無(wú)關(guān)。
  • 相關(guān)文章
  • 下面列出與本文章《詳解Nginx SSL快速雙向認(rèn)證配置(腳本)》相關(guān)的同類(lèi)信息!
  • 本頁(yè)收集關(guān)于詳解Nginx SSL快速雙向認(rèn)證配置(腳本)的相關(guān)信息資訊供網(wǎng)民參考!
  • 推薦文章
    恩平市| 克什克腾旗| 新泰市| 龙陵县| 崇文区| 开远市| 浦县| 安庆市| 察雅县| 云浮市| 廊坊市| 英德市| 井陉县| 永城市| 英吉沙县| 砚山县| 拜泉县| 临澧县| 浦县| 崇阳县| 湘阴县| 十堰市| 治多县| 天祝| 沙河市| 莎车县| 犍为县| 绵竹市| 南雄市| 韶关市| 松江区| 唐山市| 岐山县| 鄄城县| 淮安市| 娱乐| 丹阳市| 泸州市| 彰武县| 新宾| 香格里拉县|