全面HTTPS化是目前互联网的共识,基本上目前所有的浏览器均已经将使用HTTP协议或者部分HTTPS的站点表示为了不安全。而且实现全面HTTPS化有一个协议很关键,那就是HSTS协议,而HSTS有赖于各个Web服务器和浏览器客户端的支持,本文我们就来说说即将发布Curl7.74对HSTS的支持。

概述

HSTS(HTTP Strict Transport Security,HTTP严格安全传输协议,是用于站点的标准HTTP响应标头,用于告知客户端在指定时间段内,该主机不接受纯HTTP访问,只使用HTTPS进行访问。该协议在2012年的RFC 6797中提出。

由于历史遗留原因或者考虑到兼容性问题,网站可能会同时支持通过HTTP和HTTPS访问服务器资源,对http请求通过301/302跳转到https,这样就无法真正减少中间人攻击,存在被劫持的风险。

HSTS和浏览器预加载

HSTS 主要是通过服务器发送Strict-Transport-Security头的方式来控制浏览器操作:

首先在服务器响应头中添加 HSTS 响应头:

Strict-Transport-Security: max-age=expireTime [; includeSubDomains] [; preload]

该响应头只有在 https 访问才生效,其中[ ]中的参数表示可选;max-age 参数为设置的时间,建议为6个月,即15552000秒。

典型一个nginx设置为

server {

add_header Strict-Transport-Security "max-age=15552000; includeSubDomains; preload";

}

当用户下次使用 HTTP 访问,客户端浏览器就会进行内部跳转307 Redirect Interne,直接访问HTTPS,而无任何HTTP请求。

开启 HSTS后网站可以有效防范中间人劫持,无需301/302跳转也可以调高网站性能和用户访问体验。

HSTS的Strict-Transport-Security HTTP标头为流行浏览器中预加载列表之一。可以用他们预加载站点的系统设置。首次启动浏览器时就已经知道其站点HSTS状态。

Curl中HSTS的实现

预计在2020年12月发布的curl 7.74.0开始,curl开始提供HSTS实验性支持,默认情况不会启用,不。

可以通过参数--enable-hsts手动启动curl HSTS,使用--hsts <filename>来配置HSTS信息加载/保存高速缓存保存到文件,HSTS会被缓存,并在退出时进行更新。如果重复使用同一缓存文件进行调用,通过HSTS标头,就可以有效地避免使用明文HTTP访问。

libcurl

libcurl库也加入了该功能,用来进行HTTP(S)传输的应用程序可以使用。使用libcurl,应用程序可以设置文件名以用于加载和保存高速缓存,还提供了一些附加选项,以提供更大的灵活性和功能:

CURLOPT_HSTS:允许设置一个文件名以从/向中读取/写入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:启用此传输的HSTS功能。

CURL *curl = curl_easy_init();

if(curl) {

curl_easy_setopt(curl, CURLOPT_HSTS_CTRL, CURLHSTS_ENABLE);

curl_easy_perform(curl);

}

CURLOPT_HSTSREADFUNCTION:libcurl即将开始传输时,由libcurl调用该回调,并允许应用程序预加载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刷新其内存中的缓存并允许应用程序将缓存保存在某处或类似的地方时,会重复调用此回调。

CURL *curl = curl_easy_init();

struct MyData this;

if(curl) {

curl_easy_setopt(curl, CURLOPT_URL, "127.0.0.1");

/* pass pointer that gets passed in to the

CURLOPT_HSTSREADFUNCTION callback */

curl_easy_setopt(curl, CURLOPT_HSTSREADDATA, &this);

curl_easy_perform(curl);

相关文章