搜尋
首頁後端開發php教程Nginx SSL快速雙向認證配置(腳本)

Nginx SSL快速雙向認證配置(腳本)

Jul 07, 2018 pm 04:01 PM
nginxopensslssl

这篇文章主要介绍了关于Nginx SSL快速双向认证配置(脚本),有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下

目前遇到一个项目有安全性要求,要求只有个别用户有权限访问。本着能用配置解决就绝不用代码解决的原则,在Nginx上做一下限制和修改即可。

这种需求其实实现方式很多,经过综合评估考虑,觉得SSL双向认证方案对用户使用最简单,遂决定用此方案。

: 本方案在Ubuntu Server 16.04 LTS实施,其他操作系统请酌情修改

SSL双向认证

绝大多数SSL应用都以单向认证为主,即客户端只要信任服务端,就可以使用服务端的公钥加密后向服务端发起请求,由服务端的私钥解密之后获得请求数据。

如果这个过程反过来,让服务端信任客户端,服务端使用客户端的公钥加密之后将数据返回给客户端,其实也是可以做到的,原理和实现跟单向认证都差不多。

服务端信任客户端的操作往往也会伴随着客户端认证服务端的过程,所以让服务端信任客户端的SSL认证方式往往也被称为SSL双向认证,并且要配置SSL双向认证必须先开启服务端SSL,先配置客户端信任服务端。

Nginx的SSL双向认证配置

第一步 开启https访问

根据理论知识,我们必须先开启Nginx的SSL配置,即启用https。这个过程较为简单,目前有let's encrypt这种免费的证书方案,再也不用发愁自己搭建CA自签了。申请免费证书的过程略过,直接贴启用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协议
  # ssl_protocols TLSv1.3;
  # Nginx低于1.13.0版本用这个配置
  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的配置,如果你的域名下还有非标准端口访问的http应用,请勿启用HSTS
  # add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
  # 下面这个配置会拒绝Frame标签内容,请确认你的网站没有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续期用,不用let's encrypt不需要这个location
  location /.well-known {
    root /usr/share/nginx/html;
  }

   ... SNIP ...

  # 强制http跳转为https
  if ($scheme != "https") {
    return 301 https://$http_host$request_uri;
  }
}
以上那一大堆ssl的配置参考来自于: https://cipherli.st/ 加强SSL的安全性配置

特别注意最后的强制https跳转,我们的目的是SSL双向认证,不走https无任何意义,所以必须强制跳转https。

第二步 生成客户端证书并签证(脚本)

这个过程详细描述的文章太多了,这里就不啰嗦介绍openssl和签证过程了,本篇内容是快速生成双向认证配置的证书,所以直接贴脚本就行了,命令都是参考互联网上各种openssl双向配置文档,在此基础之上进行了命令上的简化与非交互式的支持。

整个目录结构如图:

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

0 directories, 3 files

自行创建/etc/nginx/ssl_certs/,放入三个脚本,分别用于生成CA证书以及CA目录(create_ca_cert.sh脚本的作用,只有第一次需要运行),创建客户端证书,并用CA证书签证(create_client_cert.sh脚本的作用,必须先生成CA证书),revoke_cert.sh脚本用于吊销证书,需要收回权限的时候可以使用。

每个脚本内容如下:

  • create_ca_cert.sh

#!/bin/bash -e

# 创建CA根证书
# 非交互式方式创建以下内容:
# 国家名(2个字母的代号)
C=CN
# 省
ST=Shannxi
# 市
L=Xian
# 公司名
O=My Company
# 组织或部门名
OU=技术部
# 服务器FQDN或颁发者名
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            设置组织或部门名,如: 技术部"
    echo "--cn            设置FQDN或所有者名,如: 冯宇"
    echo "--email         设置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

# 创建客户端证书
# 非交互式方式创建以下内容:
# 国家名(2个字母的代号)
C=CN
# 省
ST=Shannxi
# 市
L=Xian
# 公司名
O=My Company
# 组织或部门名
OU=${OU:-测试部门}
# 服务器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

# 吊销一个签证过的证书

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

简单分析一波脚本,首先是创建CA,对于Ubuntu系统来说,/etc/ssl/openssl.cnf配置中默认的CA路径就是./demoCA,为了不改动默认配置,直接按照默认配置的内容创建这些目录和文件即可。还有就是openssl子命令非常多,但是也和git一样,可以合并命令,比如用一条命令同时生成私钥和签证请求openssl req -nodes -newkey rsa:2048 -keyout client.key -new -out client.csr,在req的同时就做了genrsa。由于创建CA脚本只是第一次运行需要,因此把证书配置直接写死在脚本中就完事了。

接下来是创建客户端证书,为了简化用户的使用,在服务端帮助用户生成证书并签证,把签证过的证书下发给用户就可以了。由于用户可能是不同部门,不同姓名,不同邮件地址,因此将这三个参数外部化,做一下参数解析,加上友好的命令行提示防止遗忘。这个脚本特别注意最后一行,会生成一个PKCS12格式的证书。openssl默认产生的证书格式都是PEM的,会将公钥和私钥分开,但是浏览器导入的时候需要将这些内容合并起来形成证书链,所以需要将签证过的证书和私钥文件合并成一个PKCS12格式的证书,直接将这个.p12格式的证书交给用户就可以了。

最后是吊销证书了,当希望收回某个用户的访问权限时,直接运行这个脚本跟上目录名就可以了。

接下来运行创建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

此时产生的./demoCA目录结构如下:

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

2 directories, 7 files

此时就可以配置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就是客户端证书的CA证书了,代表此CA签发的证书都是可信的,ssl_verify_client on;代表强制启用客户端认证,非法客户端(无证书,证书不可信)都会返回400错。

特别注意ssl_crl这个配置,代表Nginx会读取一个CRL(Certificate Revoke List)文件,之前说过,可能会有收回用户权限的需求,因此我们必须有吊销证书的功能,产生一个CRL文件让Nginx知道哪些证书被吊销了即可。

注意: Nginx配置都是静态的,读取配置文件之后都会加载到内存中,即使文件内容变化也不会重新读取。因此当CRL文件发生变更之后,Nginx并不能意识到有新的证书被吊销了,所以必须使用reload指令让Nginx重新读取配置文件: service nginx reloadnginx -s reload

此时重启Nginx服务,就可以完成SSL双向认证配置了。

我们签发一个证书看看:

 ./create_client_cert.sh --ou 财务部 --cn 财务经理 --email cy@example.com
Generating a 2048 bit RSA private key
................................+++
.............................................................................+++
writing new private key to '财务经理/财务经理.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 财务经理/
财务经理/
├── 财务经理.crt
├── 财务经理.csr
├── 财务经理.key
└── 财务经理.p12

0 directories, 4 files

这个脚本生成了私钥文件key,签证请求文件csr,经过CA签证后的证书文件crt(里面没有私钥),以及将crt文件和key进行bundle之后的PKCS12格式的证书文件p12,将p12文件下载到本地,双击一路Next导入证书即可。

: 由于CA的证书文件不会发生变化,因此签证新的客户端证书不需要restart或reload nginx

这次打开我们的网站https://www.example.com,浏览器就会提示我们选择一个已有的客户端证书进行认证了,没问题就可以看到网站内容了

: 每次导入新的证书之后,必须重启浏览器才能提示使用新的证书文件

按照这种方式,有多少人需要授权,就可以用这个脚本签发多少个这样的证书,用户将p12证书导入本地就可以正常访问网站了。

当我们需要收回某人的权限的时候(比如离职了),我们需要吊销他的证书:

 ./revoke_cert.sh 财务经理
Using configuration from /usr/ssl/openssl.cnf
Revoking Certificate 01.
Data Base Updated
Using configuration from /usr/ssl/openssl.cnf

service nginx reload

这个脚本会自动吊销他的签证文件crt,并且自动更新CRL文件。特别注意需要reload或restart nginx才能让nginx重新加载CRL。这样被吊销的证书将无法访问网站了。

小结

本文我们通过Nginx配置SSL双向认证实现对客户端的加密认证,我们使用了简易的脚本帮助我们快速生成各种证书与签证,免除记忆繁琐openssl命令行,简化使用。

当然这只是一个最小可用集,当规模比较大的时候可能需要做很多改进,比如加入CA的web ui,直接可以操作签证和吊销证书,并且可以自动重启nginx。

再比如CRL这种静态配置文件不适合你的场景,希望的动态更新吊销证书列表,那么可以考虑OCSP方案,这个Nginx也是支持的,通过ssl_stapling_responder配置指定一个OCSP地址,这样将不需要每次吊销证书的时候都去重启nginx了,openssl也提供了ocsp服务端的功能,这里就不赘述了,可以自行查找相关资料。

以上就是本文的全部内容,希望对大家的学习有所帮助,更多相关内容请关注PHP中文网!

相关推荐:

Nginx 部署静态页面

nginx关于root与alias的区别

以上是Nginx SSL快速雙向認證配置(腳本)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
解釋負載平衡如何影響會話管理以及如何解決。解釋負載平衡如何影響會話管理以及如何解決。Apr 29, 2025 am 12:42 AM

負載均衡會影響會話管理,但可以通過會話複製、會話粘性和集中式會話存儲解決。 1.會話複製在服務器間複製會話數據。 2.會話粘性將用戶請求定向到同一服務器。 3.集中式會話存儲使用獨立服務器如Redis存儲會話數據,確保數據共享。

說明會話鎖定的概念。說明會話鎖定的概念。Apr 29, 2025 am 12:39 AM

Sessionlockingisatechniqueusedtoensureauser'ssessionremainsexclusivetooneuseratatime.Itiscrucialforpreventingdatacorruptionandsecuritybreachesinmulti-userapplications.Sessionlockingisimplementedusingserver-sidelockingmechanisms,suchasReentrantLockinJ

有其他PHP會議的選擇嗎?有其他PHP會議的選擇嗎?Apr 29, 2025 am 12:36 AM

PHP會話的替代方案包括Cookies、Token-basedAuthentication、Database-basedSessions和Redis/Memcached。 1.Cookies通過在客戶端存儲數據來管理會話,簡單但安全性低。 2.Token-basedAuthentication使用令牌驗證用戶,安全性高但需額外邏輯。 3.Database-basedSessions將數據存儲在數據庫中,擴展性好但可能影響性能。 4.Redis/Memcached使用分佈式緩存提高性能和擴展性,但需額外配

在PHP的上下文中定義'會話劫持”一詞。在PHP的上下文中定義'會話劫持”一詞。Apr 29, 2025 am 12:33 AM

Sessionhijacking是指攻擊者通過獲取用戶的sessionID來冒充用戶。防範方法包括:1)使用HTTPS加密通信;2)驗證sessionID的來源;3)使用安全的sessionID生成算法;4)定期更新sessionID。

PHP的完整形式是什麼?PHP的完整形式是什麼?Apr 28, 2025 pm 04:58 PM

文章討論了PHP,詳細介紹了其完整形式,在We​​b開發中的主要用途,與Python和Java的比較以及對初學者的學習便利性。

PHP如何處理形式數據?PHP如何處理形式數據?Apr 28, 2025 pm 04:57 PM

PHP使用$ \ _ post和$ \ _獲取超級全局的php處理數據,並通過驗證,消毒和安全數據庫交互確保安全性。

PHP和ASP.NET有什麼區別?PHP和ASP.NET有什麼區別?Apr 28, 2025 pm 04:56 PM

本文比較了PHP和ASP.NET,重點是它們對大規模Web應用程序,性能差異和安全功能的適用性。兩者對於大型項目都是可行的,但是PHP是開源和無關的,而ASP.NET,

PHP是對病例敏感的語言嗎?PHP是對病例敏感的語言嗎?Apr 28, 2025 pm 04:55 PM

PHP的情況敏感性各不相同:功能不敏感,而變量和類是敏感的。最佳實踐包括一致的命名和使用對案例不敏感的功能進行比較。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

DVWA

DVWA

Damn Vulnerable Web App (DVWA) 是一個PHP/MySQL的Web應用程序,非常容易受到攻擊。它的主要目標是成為安全專業人員在合法環境中測試自己的技能和工具的輔助工具,幫助Web開發人員更好地理解保護網路應用程式的過程,並幫助教師/學生在課堂環境中教授/學習Web應用程式安全性。 DVWA的目標是透過簡單直接的介面練習一些最常見的Web漏洞,難度各不相同。請注意,該軟體中

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。