如何在Node.js中使用SSL / TLS
本文轉(zhuǎn)載自微信公眾號「新鈦云服 」,作者魏建民 翻譯 。轉(zhuǎn)載本文請聯(lián)系新鈦云服公眾號。
在2020年,您的網(wǎng)站沒有理由不使用HTTPS。訪客期望它,Google將其用作排名因素,瀏覽器制造商很樂意于點名那些沒有使用它的網(wǎng)站。在本教程中,我將引導您通過一個實際示例,
說明如何將Let's Encrypt生成的證書添加到Express.js服務(wù)器。但是,僅使用HTTPS保護我們的網(wǎng)站和應(yīng)用程序還不夠。我們還應(yīng)該要求正在與之通信的服務(wù)器進行加密連接。我們將看到有可能激活SSL / TLS層,即使默認情況下未啟用它也是如此。
注意:如果您在配置NGINX作為Node應(yīng)用程序的反向代理時正在尋找有關(guān)如何使用NGINX設(shè)置SSL的說明,請查看我們的快速提示“ 使用Node.js配置NGINX和SSL ”。
讓我們從簡短回顧一下HTTPS的當前狀態(tài)開始。
一、HTTPS無處不在
HTTP / 2規(guī)范于2015年5月以RFC 7540的形式發(fā)布,這意味著它是該標準的一部分。這是一個重要的里程碑?,F(xiàn)在,我們都可以將服務(wù)器升級為使用HTTP / 2。最重要的方面之一是與HTTP 1.1的向后兼容性以及選擇不同協(xié)議的協(xié)商機制。盡管該標準未指定強制加密,但是當前沒有瀏覽器支持未加密的HTTP / 2。這給HTTPS帶來了另一個提升。終于,HTTPS無處不在!
我們的堆棧實際上是什么樣的?從瀏覽器中運行的網(wǎng)站(在應(yīng)用程序級別)的角度來看,我們必須遍歷以下幾層才能達到IP級別:
1.客戶端瀏覽器、
2.HTTP、
3.SSL / TLS、
4.TCP協(xié)議、
5.知識產(chǎn)權(quán)
HTTPS就是SSL / TLS之上的HTTP協(xié)議。因此,所有HTTP規(guī)則仍然適用。這個額外的層實際上給了我們什么?有很多優(yōu)點:我們通過擁有密鑰和證書來進行身份驗證;由于以非對稱方式對連接進行加密,因此可以確保某種類型的隱私和機密性;并且還保留了數(shù)據(jù)完整性,因為傳輸?shù)臄?shù)據(jù)在傳輸過程中無法更改。
最普遍的神話之一是,使用SSL / TLS的計算量很大,并且會降低服務(wù)器的速度。這肯定不再是事實。我們也不需要帶有加密單元的任何專用硬件。即使對于Google而言,SSL / TLS層也占不到CPU負載的1%,與HTTP相比,HTTPS的網(wǎng)絡(luò)開銷也低于2%。總而言之,為了節(jié)省一些開銷,放棄HTTPS是沒有意義的。
最新版本是TLS 1.3。TLS是SSL的后繼產(chǎn)品,最新版本的SSL 3.0中提供了TLS。從SSL到TLS的更改排除了互操作性,但是基本過程保持不變。我們有三個不同的加密通道。第一個是用于證書鏈的公鑰基礎(chǔ)結(jié)構(gòu)。第二種提供用于密鑰交換的公共密鑰加密。最后,第三個是對稱的。在這里,我們有用于數(shù)據(jù)傳輸?shù)拿艽a學。
TLS 1.3對某些重要操作使用哈希處理。從理論上講,可以使用任何哈希算法,但是強烈建議使用SHA2或更強大的算法。SHA1長期以來一直是標準,但最近已過時。
HTTPS也越來越受到客戶的關(guān)注。隱私和安全問題一直存在,但是隨著在線可訪問數(shù)據(jù)和服務(wù)數(shù)量的增長,人們越來越關(guān)注。對于那些未實現(xiàn)此功能的網(wǎng)站,有一個有用的瀏覽器擴展-EFF的HTTPS Everywhere-可加密我們與大多數(shù)網(wǎng)站的通信。
創(chuàng)建者意識到許多網(wǎng)站僅部分提供HTTPS。該插件使我們可以重寫僅提供部分HTTPS支持的網(wǎng)站的請求。另外,我們也可以完全阻止HTTP(請參見上面的屏幕截圖)。
二、基本說明
證書的驗證過程包括驗證證書簽名和有效期。我們還需要驗證它是否鏈接到受信任的根。最后,我們需要檢查它是否已被撤銷。世界上有專門的可信賴的機構(gòu)來頒發(fā)證書。如果其中之一遭到破壞,則來自該機構(gòu)的所有其他證書將被吊銷。
HTTPS握手的序列圖如下所示。我們從客戶端初始化開始,然后是帶有證書和密鑰交換的消息。服務(wù)器發(fā)送完成的包后,客戶端可以開始密鑰交換和密碼規(guī)范傳輸。至此,客戶端結(jié)束。最后,服務(wù)器確認密碼規(guī)范選擇并關(guān)閉握手。
整個序列獨立于HTTP觸發(fā)。如果我們決定使用HTTPS,則僅更改套接字處理。客戶端仍在發(fā)出HTTP請求,但是套接字將執(zhí)行前面描述的握手并加密內(nèi)容(標頭和正文)。那么,要使SSL / TLS與Express.js服務(wù)器一起使用,我們需要做什么?
三、HTTPS
默認情況下,Node.js通過HTTP提供內(nèi)容。但是,還必須使用HTTPS模塊,以便通過安全通道與客戶端進行通信。這是一個內(nèi)置模塊,用法與我們使用HTTP模塊的方式非常相似:
暫時忽略/srv/www/keys/my-site-key.pem和和/srv/www/keys/chain.pem文件。這些是我們需要生成的SSL證書,我們稍后會做。這是讓我們加密的部分。以前,我們必須生成一個私鑰/公鑰對,將其發(fā)送給受信任的機構(gòu),向他們付款并可能要花一點時間才能獲得SSL證書。如今,“讓我們加密”可立即免費生成并驗證您的證書!
四、生成證書
(1)Certbot
TLS規(guī)范要求證書,該證書由受信任的證書頒發(fā)機構(gòu)(CA)簽名。CA確保證書持有人確實是他們聲稱的真實身份。因此,基本上,當您看到綠色的鎖定圖標(或瀏覽器中URL左側(cè)的任何其他綠色符號)時,表明您與之通信的服務(wù)器確實是它聲稱的身份。如果您在facebook.com上并且看到一個綠色鎖,則幾乎可以確定您確實在與Facebook通信,并且沒有人可以看到您的通信,或者,也沒有其他人可以閱讀它。
值得注意的是,此證書不一定必須由諸如“加密”之類的權(quán)威機構(gòu)進行驗證。還有其他付費服務(wù)。您可以從技術(shù)上親自對其進行簽名,但是(由于您不是受信任的CA),訪問您網(wǎng)站的用戶可能會看到大量可怕的警告信息,以使他們恢復安全。
在下面的示例中,我們將使用Certbot,它用于通過Let's Encrypt生成和管理證書。在Certbot網(wǎng)站上,您可以找到有關(guān)如何為幾乎所有OS /服務(wù)器組合安裝Certbot的說明。您應(yīng)該選擇適合您的選項。
在最新的LTS Ubuntu上,NGINX是部署Node應(yīng)用程序的常見組合,這就是我將在這里使用的。
(2)Webroot
Webroot是一個Certbot插件,除了Certbot默認功能(該功能會自動生成您的公鑰/私鑰對并為其生成SSL證書)外,還將證書復制到您的webroot文件夾中,并通過放置一些驗證碼來驗證服務(wù)器進入名為的隱藏臨時目錄.well-known。為了跳過手動執(zhí)行的某些步驟,我們將使用此插件。該插件默認情況下與Certbot一起安裝。為了生成和驗證我們的證書,我們將運行以下命令:certbot certonly --webroot -w /var/www/example/ -d www.example.com -d example.com
您可能必須以sudo身份運行此命令,因為它將嘗試寫入/var/log/letsencrypt。
您還會被要求提供您的電子郵件地址。最好輸入一個經(jīng)常使用的真實地址,因為如果證書即將過期,您會收到通知。讓我們加密發(fā)行免費證書的權(quán)衡是該證書每三個月到期一次。幸運的是,更新就像運行一個簡單的命令一樣容易,我們可以將其分配給cron作業(yè),而不必擔心過期。此外,更新SSL證書是一種很好的安全做法,因為它可使攻擊者更少的時間來破壞加密。有時,開發(fā)人員甚至將這個cron設(shè)置為每天運行,這是完全可以的,甚至建議這樣做。
請記住,您必須在-d(針對域)標志下指定的域解析為的服務(wù)器(即生產(chǎn)服務(wù)器)上運行此命令。即使您的本地主機文件中有DNS解析,該方法也無法使用,因為該域?qū)耐獠窟M行驗證。因此,如果您在本地執(zhí)行此操作,則很可能會失敗,除非您打開了從本地計算機到外界的端口,并使該端口在解析為您的計算機的域名后面運行。這是極不可能的情況。
最后但并非最不重要的一點是,在運行此命令之后,輸出將包含私鑰和證書文件的路徑。將這些值復制到上一個代碼段中- cert證書的key屬性和密鑰的屬性中:
五、思考
(1)HTTP嚴格傳輸安全
您是否曾經(jīng)在一個網(wǎng)站上從HTTP切換到HTTPS,并且仍有一些剩余重定向仍在重定向到HTTP?HTTP嚴格傳輸安全性(HSTS)是一種Web安全策略機制,可緩解協(xié)議降級攻擊和cookie劫持。
HSTS有效地迫使客戶端(瀏覽器訪問您的服務(wù)器)通過HTTPS引導所有流量,這是“安全或根本不安全”的思想!
Express JS默認情況下不允許我們添加此標頭,因此我們將使用Helmet,這是一個允許我們執(zhí)行此操作的Node模塊。通過運行以下命令安裝頭盔:npm install helmet然后,我們只需將其作為中間件添加到Express服務(wù)器中即可:
(2)Diffie-Hellman Strong(er)參數(shù)
為了跳過一些復雜的數(shù)學運算,讓我們開始追逐。用非常簡單的術(shù)語來說,有兩種不同的密鑰用于加密:從證書頒發(fā)機構(gòu)獲得的證書,以及由服務(wù)器生成的用于密鑰交換的證書。密鑰交換的默認密鑰(也稱為Diffie-Hellman密鑰交換,即DH)使用的“密鑰”比證書的密鑰“小”。為了解決這個問題,我們將生成一個強大的DH密鑰,并將其提供給我們的安全服務(wù)器以供使用。
為了生成更長的密鑰(2048位),您將需要openssl默認安裝的。如果您不確定,請運行openssl -v。如果找不到該命令,請openssl通過運行安裝sudo apt install openssl(或在此處訪問其下載頁面):openssl dhparam -out /var/www/example/sslcert/dh-strong.pem 2048
然后將文件的路徑復制到我們的配置中:
六、結(jié)論
在2020年及以后,沒有理由不支持HTTPS。未來的方向顯而易見:HTTPS無處不在!在Node.js中,我們有許多利用SSL / TLS的選項。我們可以使用HTTPS發(fā)布網(wǎng)站,可以創(chuàng)建對加密網(wǎng)站的請求,還可以授權(quán)其他不受信任的證書。