Curl即將支持HSTS
全面HTTPS化是目前互聯(lián)網(wǎng)的共識,基本上目前所有的瀏覽器均已經(jīng)將使用HTTP協(xié)議或者部分HTTPS的站點表示為了不安全。而且實現(xiàn)全面HTTPS化有一個協(xié)議很關(guān)鍵,那就是HSTS協(xié)議,而HSTS有賴于各個Web服務(wù)器和瀏覽器客戶端的支持,本文我們就來說說即將發(fā)布Curl7.74對HSTS的支持。
概述
HSTS(HTTP Strict Transport Security,HTTP嚴(yán)格安全傳輸協(xié)議,是用于站點的標(biāo)準(zhǔn)HTTP響應(yīng)標(biāo)頭,用于告知客戶端在指定時間段內(nèi),該主機(jī)不接受純HTTP訪問,只使用HTTPS進(jìn)行訪問。該協(xié)議在2012年的RFC 6797中提出。
由于歷史遺留原因或者考慮到兼容性問題,網(wǎng)站可能會同時支持通過HTTP和HTTPS訪問服務(wù)器資源,對http請求通過301/302跳轉(zhuǎn)到https,這樣就無法真正減少中間人攻擊,存在被劫持的風(fēng)險。

HSTS和瀏覽器預(yù)加載

HSTS 主要是通過服務(wù)器發(fā)送Strict-Transport-Security頭的方式來控制瀏覽器操作:
首先在服務(wù)器響應(yīng)頭中添加 HSTS 響應(yīng)頭:
Strict-Transport-Security: max-age=expireTime [; includeSubDomains] [; preload]
該響應(yīng)頭只有在 https 訪問才生效,其中[ ]中的參數(shù)表示可選;max-age 參數(shù)為設(shè)置的時間,建議為6個月,即15552000秒。
典型一個nginx設(shè)置為
- server {
- …
- add_header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload";
- …
- }
當(dāng)用戶下次使用 HTTP 訪問,客戶端瀏覽器就會進(jìn)行內(nèi)部跳轉(zhuǎn)307 Redirect Interne,直接訪問HTTPS,而無任何HTTP請求。
開啟 HSTS后網(wǎng)站可以有效防范中間人劫持,無需301/302跳轉(zhuǎn)也可以調(diào)高網(wǎng)站性能和用戶訪問體驗。
HSTS的Strict-Transport-Security HTTP標(biāo)頭為流行瀏覽器中預(yù)加載列表之一??梢杂盟麄冾A(yù)加載站點的系統(tǒng)設(shè)置。首次啟動瀏覽器時就已經(jīng)知道其站點HSTS狀態(tài)。
Curl中HSTS的實現(xiàn)
預(yù)計在2020年12月發(fā)布的curl 7.74.0開始,curl開始提供HSTS實驗性支持,默認(rèn)情況不會啟用,不。
可以通過參數(shù)--enable-hsts手動啟動curl HSTS,使用--hsts
libcurl
libcurl庫也加入了該功能,用來進(jìn)行HTTP(S)傳輸?shù)膽?yīng)用程序可以使用。使用libcurl,應(yīng)用程序可以設(shè)置文件名以用于加載和保存高速緩存,還提供了一些附加選項,以提供更大的靈活性和功能:

CURLOPT_HSTS:允許設(shè)置一個文件名以從/向中讀取/寫入HSTS緩存。
- CURL *curl = curl_easy_init();
- if(curl) {
- curl_easy_setopt(curl, CURLOPT_HSTS, "/home/user/.hsts-cache");
- curl_easy_perform(curl);
CURLOPT_HSTS_CTRL:啟用此傳輸?shù)腍STS功能。
- CURL *curl = curl_easy_init();
- if(curl) {
- curl_easy_setopt(curl, CURLOPT_HSTS_CTRL, CURLHSTS_ENABLE);
- curl_easy_perform(curl);
- }
CURLOPT_HSTSREADFUNCTION:libcurl即將開始傳輸時,由libcurl調(diào)用該回調(diào),并允許應(yīng)用程序預(yù)加載HSTS條目,就像它們是通過curl讀取并添加到緩存中一樣。
- {
- /* set HSTS read callback */
- curl_easy_setopt(curl, CURLOPT_HSTSREADFUNCTION, hstsread);
- /* pass in suitable argument to the callback */
- curl_easy_setopt(curl, CURLOPT_HSTSREADDATA, &hstspreload[0]);
- result = curl_easy_perform(curl);
- }
: libcurl刷新其內(nèi)存中的緩存并允許應(yīng)用程序?qū)⒕彺姹4嬖谀程幓蝾愃频牡胤綍r,會重復(fù)調(diào)用此回調(diào)。
- CURL *curl = curl_easy_init();
- struct MyData this;
- if(curl) {
- curl_easy_setopt(curl, CURLOPT_URL, "http://example.com");
- /* pass pointer that gets passed in to the
- CURLOPT_HSTSREADFUNCTION callback */
- curl_easy_setopt(curl, CURLOPT_HSTSREADDATA, &this);
- curl_easy_perform(curl);