1. 程式人生 > >Nginx配置SSL證書實現訪問HTTPS網站

Nginx配置SSL證書實現訪問HTTPS網站

一、什麼是 SSL 證書,什麼是 HTTPS
SSL 證書是一種數字證書,它使用 Secure Socket Layer 協議在瀏覽器和 Web伺服器之間建立一條安全通道,從而實現:
1、資料資訊在客戶端和伺服器之間的加密傳輸,保證雙方傳遞資訊的安全性,不可被第三方竊聽;
2、使用者可以通過伺服器證書驗證他所訪問的網站是否真實可靠。

HTTPS 是以安全為目標的 HTTP 通道,即 HTTP 下加入 SSL 加密層。HTTPS 不同於 HTTP的埠,HTTP預設埠為80,HTTPS預設埠為443。

二、什麼網站需要使用SSL證書
1、購物交易類網站
不用多說,網上銀行、支付寶、Paypal等肯定會全程加密以保護你的資訊保安。

2、註冊與登陸
一些大的網站,比如電子郵箱,註冊會員或者登陸的時候,會專門通過SSL通道,保證密碼安全不被竊取。

3、某些線上代理
這個。。。嗯哼,就不說了。

4、裝B
比如我……

三、自行頒發不受瀏覽器信任的SSL證書
為晒晒IQ網頒發證書。ssh登陸到伺服器上,終端輸入以下命令,使用openssl生成RSA金鑰及證書。


# 生成一個RSA金鑰 
$ openssl genrsa -des3 -out 33iq.key

# 拷貝一個不需要輸入密碼的金鑰檔案
$ openssl rsa -in 33iq.key -out 33iq_nopass.key

# 生成一個證書請求
$ openssl req -new -key 33iq.key -out 33iq.csr

# 自己簽發證書
$ openssl x509 -req -days  -in 33iq.csr -signkey 33iq.key -out 33iq.crt

第3個命令是生成證書請求,會提示輸入省份、城市、域名資訊等,重要的是,email一定要是你的域名字尾的。這樣就有一個 csr檔案了,提交給 ssl 提供商的時候就是這個 csr 檔案。當然我這裡並沒有向證書提供商申請,而是在第4步自己簽發了證書。

編輯配置檔案nginx.conf,給站點加上HTTPS協議


server {
    server_name YOUR_DOMAINNAME_HERE;
    listen ;
    ssl on;
    ssl_certificate /usr/local/nginx/conf/33iq.crt;
    ssl_certificate_key /usr/local/nginx/conf/33iq_nopass.key;
    # 若ssl_certificate_key使用33iq.key,則每次啟動Nginx伺服器都要求輸入key的密碼。
}

重啟Nginx後即可通過https訪問網站了。

自行頒發的SSL證書能夠實現加密傳輸功能,但瀏覽器並不信任,會出現以下提示:

四、受瀏覽器信任的證書
要獲取受瀏覽器信任的證書,則需要到證書提供商處申請。證書授證中心,又叫做CA機構,為每個使用公開金鑰的使用者發放一個數字證書。瀏覽器在預設情況下內建了一些CA機構的證書,使得這些機構頒發的證書受到信任。VeriSign即是一個著名的國外CA機構,工行、建行、招行、支付寶、財付通等網站均使用VeriSign的證書,而網易郵箱等非金融網站採用的是中國網際網路資訊中心CNNIC頒發的SSL證書。一般來說,一個證書的價格不菲,以VeriSign的證書為例,價格在每年8000元人民幣左右。

據說也有免費的證書可以申請。和VeriSign一樣,StartSSL也是一家CA機構,它的根證書很久之前就被一些具有開源背景的瀏覽器支援(Firefox瀏覽器、谷歌Chrome瀏覽器、蘋果Safari瀏覽器等)。後來StartSSL竟然搞定了微軟:在升級補丁中,微軟更新了通過Windows根證書認證(Windows RootCertificate Program)的廠商清單,並首次將StartCom公司列入了該認證清單。現在,在Windows7或安裝了升級補丁的Windows Vista或WindowsXP作業系統中,系統會完全信任由StartCom這類免費數字認證機構認證的數字證書,從而使StartSSL也得到了IE瀏覽器的支援。(來源及申請步驟)

五、只針對註冊、登陸進行https加密處理
既然HTTPS能保證安全,為什麼全世界大部分網站都仍舊在使用HTTP呢?使用HTTPS協議,對伺服器來說是很大的負載開銷。從效能上考慮,我們無法做到對於每個使用者的每個訪問請求都進行安全加密(當然,Google這種大神除外)。作為一個普通網站,我們所追求的只是在進行交易、密碼登陸等操作時的安全。通過配置Nginx伺服器,可以使用rewrite來做到這一點。

在https server下加入如下配置:


if ($uri !~* "/logging.php$")
{
    rewrite ^/(.*)$ http://$host/$1 redirect;
}


在http server下加入如下配置:


if ($uri ~* "/logging.php$")
{
    rewrite ^/(.*)$ https://$host/$1 redirect;
}


這樣一來,使用者會且只會在訪問logging.php的情況下,才會通過https訪問。

更新:有一些開發框架會根據 $_SERVER['HTTPS'] 這個 PHP 變數是否為 on 來判斷當前的訪問請求是否是使用https。為此我們需要在 Nginx 配置檔案中新增一句來設定這個變數。遇到 https 連結重定向後會自動跳到 http問題的同學可以參考一下。

server {
    ...
    listen 443;
    location \.php$ {
        ...
        include fastcgi_params;
        fastcgi_param HTTPS on; # 多加這一句
    }
}
 
server {
    ...
    listen 80;
    location \.php$ {
        ...
        include fastcgi_params;
    }
}

另附我的nginx.conf:

worker_processes  2;# 雙核

events {
    worker_connections  1024;
}


http {
    include       mime.types;
    default_type  application/octet-stream;

    sendfile        on;
    keepalive_timeout  65;

    server {
        listen       808;
        server_name  localhost;

	    resolver YOUR_DNS_SERVER;
	    location / {
	    	proxy_pass http://$http_host$request_uri;
	     }

        error_page   500 502 503 504  /50x.html;
        location = /50x.html {
            root   html;
        }
    }


    server {
        ### server port and name ###
        listen          443 ssl;
        server_name     WHATEVER;
 
        ### SSL log files ###
        access_log      logs/ssl-access.log;
        error_log       logs/ssl-error.log;
 
        ### SSL cert files ###
        ssl_certificate      ssl/nixcraft.in.crt;
        ssl_certificate_key  ssl/nixcraft.in.key;
        ### Add SSL specific settings here ###
        keepalive_timeout    60;
 
        ###  Limiting Ciphers ########################
        # Uncomment as per your setup
        #ssl_ciphers HIGH:!ADH;
        #ssl_perfer_server_ciphers on;
        #ssl_protocols SSLv3;
        ##############################################
        ### We want full access to SSL via backend ###
        location / {
                proxy_pass  http://192.168.1.123;
                ### force timeouts if one of backend is died ##
                proxy_next_upstream error timeout invalid_header http_500 http_502 http_503;
 
                ### Set headers ####
                proxy_set_header Host $host;
                proxy_set_header X-Real-IP $remote_addr;
                proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 
                ### Most PHP, Python, Rails, Java App can use this header ###
                proxy_set_header X-Forwarded-Proto https;
 
                ### By default we don't want to redirect it ####
                proxy_redirect     off;
        }
    }
}