代碼來源:cnblogs
原文作者:百衲本
原文連結:https://www.cnblogs.com/panwenbin-logs/p/11850737.html
本文版權歸原作者所有,如有侵權請立即與我聯繫,我將及時處理。
註:生成的免費證書在瀏覽器是不被信任的
一、準備
環境:centos7.6
nginx:1.13.6
二、創建SSL相關證書
首先安裝依賴包:
yum install -y gcc gcc-c++ autoconf automake make zlib zlib-devel openssl openssl-devel pcre pcre-devel1. 安裝nginx
tar -xf nginx-1.13.6.tar.gzcd nginx-1.13.6./configure --prefix=/usr/local/nginx --with-pcre --with-http_stub_status_module --with-http_gzip_static_module --with-http_ssl_modulemake && make install或者yum安裝
[root@localhost ~]# yum install nginx -y #默認yum安裝已經支持SSL,如果是自己編譯的可以通過 nginx -V 查看當前Nginx是否支持SSL[root@localhost ~]# cd /etc/nginx/[root@localhost nginx]# mkdir ssl[root@localhost nginx]# cd ssl/2.生成一個RSA密鑰
[root@localhost ssl]# openssl genrsa -des3 -out nginx.key 1024 #實際使用中看伺服器性能,如果足夠好也可以使用4096位秘鑰Generating RSA private key, 1024 bit long modulus..++++++...++++++e is 65537 (0x10001)Enter pass phrase for nginx.key: #輸入密碼,自定義,不少於4個字符Verifying - Enter pass phrase for nginx.key: #確認密碼3.生成一個證書請求
[root@localhost ssl]# openssl req -new -key nginx.key -out nginx.csrEnter pass phrase for nginx.key: #輸入剛剛創建的秘密碼You are about to be asked to enter information that will be incorporatedinto your certificate request.What you are about to enter is what is called a Distinguished Name or a DN.There are quite a few fields but you can leave some blankFor some fields there will be a default value,If you enter '.', the field will be left blank.Country Name (2 letter code) [XX]:CN #國家名稱State or Province Name (full name) []:ShangHai #省Locality Name (eg, city) [Default City]:ShangHai #市Organization Name (eg, company) [Default Company Ltd]:ACBC #公司Organizational Unit Name (eg, section) []:Tech #部門Common Name (eg, your name or your server's hostname) []:*.mydomain.com #注意,此處應當填寫你要部署的域名,如果是單個則直接添加即可,如果不確定,使用*,表示可以對所有mydomain.com的子域名做認證Email Address []:admin@mydomain.com #以域名結尾即可
Please enter the following 'extra' attributesto be sent with your certificate request A challenge password []: #是否設置密碼,可以不寫直接回車 An optional company name []: #其他公司名稱 可不寫4.創建不需要輸入密碼的RSA證書,否則每次reload、restart都需要輸入密碼
[root@localhost ssl]# openssl rsa -in nginx.key -out nginx_nopass.keyEnter pass phrase for nginx.key: #之前RSA秘鑰創建時的密碼writing RSA key5.籤發證書(由於是測試自己籤發,實際應該將自己生成的csr文件提交給SSL認證機構認證)
[root@localhost ssl]# openssl x509 -req -days 3650 -in nginx.csr -signkey nginx.key -out nginx.crt Signature oksubject=/C=CN/ST=ShangHai/L=ShangHai/O=ACBC/OU=Tech/CN=*.mydomain.com/emailAddress=admin@mydomain.comGetting Private keyEnter pass phrase for nginx.key: #RSA創建時的密碼
三、配置Nginx1、修改配置文件(注意域名,特別是443)
# For more information on configuration, see:# * Official English Documentation: http://nginx.org/en/docs/# * Official Russian Documentation: http://nginx.org/ru/docs/
user nginx;worker_processes auto;error_log /var/log/nginx/error.log;pid /run/nginx.pid;# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.include /usr/share/nginx/modules/*.conf;
events { worker_connections 1024;}
http { 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; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048;
include /etc/nginx/mime.types; default_type application/octet-stream;
include /etc/nginx/conf.d/*.conf; server { listen 80 default_server; listen [::]:80 default_server; server_name test.mydomain.com; #配置自己的域名 注意要以自己申請證書時填寫的域名一致 root /usr/share/nginx/html;
# Load configuration files for the default server block. include /etc/nginx/default.d/*.conf;
location / { }
error_page 404 /404.html; location = /40x.html { }
error_page 500 502 503 504 /50x.html; location = /50x.html { } }
# Settings for a TLS enabled server. server { listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server; server_name test.mydomain.com; #與申請時的域名保持一致,否則會報錯 root /usr/share/nginx/html;
ssl_certificate "/etc/nginx/ssl/nginx.crt"; # ssl_certificate_key "/etc/nginx/ssl/nginx_nopass.key"; ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on;
# Load configuration files for the default server block. include /etc/nginx/default.d/*.conf;
location / { }
error_page 404 /404.html; location = /40x.html { }
error_page 500 502 503 504 /50x.html; location = /50x.html { } }
}配置簡介
ssl_certificate證書 其實是個公鑰,它會被發送到連接伺服器的每個客戶端,ssl_certificate_key私鑰是用來解密的,所以它的權限要得到保護但nginx的主進程能夠讀取。當然私鑰和證書可以放在一個證書文件中,這種方式也只有公鑰證書才發送到client。ssl_session_timeout 客戶端可以重用會話緩存中ssl參數的過期時間,內網系統默認5分鐘太短了,可以設成30m即30分鐘甚至4h。ssl_protocols指令 用於啟動特定的加密協議,nginx在1.1.13和1.0.12版本後默認是ssl_protocols SSLv3 TLSv1 TLSv1.1 TLSv1.2,TLSv1.1與TLSv1.2要確保OpenSSL >= 1.0.1 ,SSLv3 現在還有很多地方在用但有不少被攻擊的漏洞。ssl_ciphers 選擇加密套件,不同的瀏覽器所支持的套件(和順序)可能會不同。這裡指定的是OpenSSL庫能夠識別的寫法,你可以通過 openssl -v cipher 『RC4:HIGH:!aNULL:!MD5』(後面是你所指定的套件加密算法) 來看所支持算法。ssl_prefer_server_ciphers on 設置協商加密算法時,優先使用我們服務端的加密套件,而不是客戶端瀏覽器的加密套件。2.啟動服務
[root@localhost nginx]# nginx -tnginx: the configuration file /etc/nginx/nginx.conf syntax is oknginx: configuration file /etc/nginx/nginx.conf test is successful[root@localhost nginx]# echo "This test page" > /usr/share/nginx/html/test.html #創建一個測試頁面[root@localhost nginx]# systemctl restart nginx3.測試
修改hosts文件,綁定 test.mydomain.com 域名對應的IP到客戶端
使用HTTPS協議訪問,有個警告,正常,因為我們的證書沒有經過認證,點擊高級,點擊繼續前往
從結果看出,HTTPS配置成功
4.有時候我們希望無論是HTTP或者HTTPS協議都通過HTTPS訪問,可以做如下配置
server { listen 80 default_server; listen [::]:80 default_server; server_name test.mydomain.com; root /usr/share/nginx/html;
# Load configuration files for the default server block. include /etc/nginx/default.d/*.conf; return 301 https://$server_name$request_uri; #在80監聽埠 配置跳轉在使用HTTP協議訪問,為避免緩存的影響,可以換一個瀏覽器
輸入URL後回車,跳轉到HTTPS了, 點擊高級-->接受風險並繼續
三、配置Nginx使用HTTPS代理後端Tomcat服務1.下載Tomcat,並測試是否訪問正常
[root@localhost nginx]# cd /mnt/[root@localhost mnt]# tar xf apache-tomcat-7.0.96.tar.gz [root@localhost mnt]# cd apache-tomcat-7.0.96/bin/[root@localhost bin]# ./startup.sh [root@localhost bin]# curl -I http://172.16.150.132:8080 #如果在他為200 OK則正常2.配置Nginx代理到Tomcat
Nginx代理可以分為兩種情況
1.全代理
2.只代理動態請求,靜態請求本地或者代理到其他靜態伺服器上,即動靜分離
我們先配置第一種情況:全代理
[root@localhost bin]# cd /etc/nginx/[root@localhost nginx]# vim nginx.conf server { listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server; server_name test.mydomain.com; root /usr/share/nginx/html;
ssl_certificate "/etc/nginx/ssl/nginx.crt"; ssl_certificate_key "/etc/nginx/ssl/nginx_nopass.key"; ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on;
# Load configuration files for the default server block. include /etc/nginx/default.d/*.conf;
location / { proxy_pass http://localhost:8080; #使用proxy_pass 直接代理 }
[root@localhost bin]# cd /etc/nginx/[root@localhost nginx]# vim nginx.conf[root@localhost nginx]# systemctl restart nginx瀏覽器訪問測試一下,沒有問題
動靜分離配置
[root@localhost nginx]# vim nginx.conf location / { #刪除之前的8080代理 index index.html index.htm; }
location ~ \.(jsp|jspx|do|action)(\/.*)?$ { proxy_set_header real_ip $remote_addr; proxy_pass http://localhost:8080; }
[root@localhost nginx]# nginx -t[root@localhost nginx]# systemctl restart nginx3.生產其他常見配置
proxy_set_header Host $http_host; #避免http請求中丟失Host頭部的情況下Host不被重寫的失誤proxy_set_header X-Forwarded-For $http_x_forwarded_for; #代表客戶端,也就是HTTP的請求端真實的IPproxy_set_header X-Real-IP $remote_addr; #將$remote_addr的值放進變量X-Real-IP中,此變量名可變,$remote_addr的值為客戶端的ipadd_header Access-Control-Allow-Origin *; #表示允許訪問的外域請求add_header Access-Control-Allow-Headers X-Requested-With; #首部欄位用於預檢請求的響應。其指明了實際請求中允許攜帶的首部欄位。add_header Access-Control-Allow-Methods GET,POST,OPTIONS; #首部欄位用於預檢請求的響應。其指明了實際請求所允許使用的 HTTP 方法。add_header Strict-Transport-Security "max-age=31536000; includeSubdomains; preload"; #防止中間人攻擊add_header X-Frame-Options:ALLOW-FROM http://www.growingio.com; # 避免點擊劫持 (clickjacking) 的攻擊add_header X-Content-Type-Options nosniff; #不允許瀏覽器任何猜測的行為
ssi on; #開啟SSIssi_silent_errors on;ssi_types *;
proxy_redirect http:// $scheme://; #修改從被代理伺服器傳來的應答頭中的"Location"和"Refresh"欄位,將http修改為httpsport_in_redirect on; #告訴nginx,遇到跳轉的時候,不要加上自己的埠號
#可配置參數由openssl 的ciphers定義 openssl ciphers -v #查看支持的配置參數ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256';
ssl_stapling on; #啟用或禁用 伺服器對OCSP響應的裝訂 #檢驗證書合法性的在線查詢服務 ssl_stapling_verify on; #啟用或禁用伺服器對OCSP響應的驗證
#如果啟用了ssl_stapling,則以file PEM格式 指定具有受信任CA證書的證書,用於驗證客戶端證書和OCSP響應。順序為 站點證書、中間證書(1張或多張)、根證書ssl_trusted_certificate /path/to/file;
#使用Diffie-Hellman方法讓訪問者的瀏覽器和伺服器安全的交換密鑰 #使用 openssl dhparam -out /usr/ssl/dhparam.pem 2048 命令生成需要的pem文件 其中默認為1024位ssl_dhparam /etc/ssl/certs/dhparam.pem;網站SSL配置檢查:
https://www.ssllabs.com/ssltest/
https://myssl.com/myssl.com
網站SSL證書有效期檢測腳本:
#!/usr/bin/env bashfunction verified_for_certificate(){ host=$1 port=${2:-"443"}
end_date=`echo | timeout 6 openssl s_client -servername ${host} -connect ${host}:${port} 2>/dev/null | openssl x509 -noout -dates | grep notAfter | awk -F "=" '{print $NF}'`
if [ -n "$end_date" ]; then # 把時間轉換為時間戳 end_date_seconds=`date '+%s' --date "$end_date"` # 獲取當前時間 now_seconds=`date '+%s'` valid_days=$(echo "($end_date_seconds-$now_seconds)/24/3600" | bc) echo "${host}剩餘有效期天數為:${valid_days}天" fi}
function main(){ verified_for_certificate $1 $2}
main $1 $2五、自定義 conf
server { listen 80 default_server; listen [::]:80 default_server; server_name c.a.com;
root /usr/share/nginx/c.a.com/public; index index.php index.html index.htm;
return 301 https://$server_name$request_uri; #在80監聽埠 配置跳轉
client_max_body_size 80m;
location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=/$1 last; break; } client_max_body_size 50m; }
location /img { proxy_pass http://172.17.0.3/img; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_redirect off; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; }
location ~\.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; client_max_body_size 50m; fastcgi_buffer_size 64k; fastcgi_buffers 8 64k; }}
server { listen 443 ssl http2 default_server; listen [::]:443 ssl http2 default_server; server_name c.a.com;
ssl_certificate "/etc/nginx/ssl/nginx.crt"; ssl_certificate_key "/etc/nginx/ssl/nginx_nopass.key"; ssl_session_cache shared:SSL:1m; ssl_session_timeout 10m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; ssl_protocols TLSv1.2;
root /usr/share/nginx/c.a.com/public; index index.php index.html index.htm;
client_max_body_size 80m;
location / { if (!-e $request_filename) { rewrite ^(.*)$ /index.php?s=/$1 last; break; } client_max_body_size 50m; }
location /img { proxy_pass http://172.17.0.3/img; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header REMOTE-HOST $remote_addr; proxy_redirect off; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; }
error_page 500 502 503 504 /50x.html; location = /50x.html { root /usr/share/nginx/html; }
location ~\.php$ { fastcgi_pass 127.0.0.1:9000; fastcgi_index index.php; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; client_max_body_size 50m; fastcgi_buffer_size 64k; fastcgi_buffers 8 64k; }}