HTTP/2探索第二篇——工具及应用

版权声明:本文由张浩然原创文章,转载请注明出处: 
文章原文链接:https://www.qcloud.com/community/article/88

来源:腾云阁 https://www.qcloud.com/community

由于不同环境过于复杂,本文仅基于Mac OS和Linux来讲解工具及应用。

一.HTTP/2环境搭建所需软件概览

本文需要安装的软件为(Mac用户请使用homebrew来安装,括号里都是Mac的安装方式)

  • curl (brew install nghttp2 —with-nghttp2)
    Linux安装
    wget https://curl.haxx.se/download/curl-7.48.0.tar.gz
    tar xvf curl-7.48.0.tar.gz && cd curl-7.48.0
    然后输入以下命令,exit一次再进入然后版本是7.48就成功了:

    $ ./configure --with-nghttp2=/usr/local --with-ssl
    $ make
    $ sudo make install
    $ ldconfig
    $ usr/local/bin/curl -V
    
  • nghttp2 (brew install nghttp2)
    安装网址
    sudo apt-get install g++ make binutils autoconf automake autotools-dev libtool pkg-config zlib1g-dev libcunit1-dev libssl-dev libxml2-dev libev-dev libevent-dev libjansson-dev libjemalloc-dev cython python3-dev python-setuptools
    

    上面是安装依赖,之后就可以编译了:

    $ autoreconf -i
    $ automake
    $ autoconf
    $ ./configure
    $ make
    $ sudo make install
    nginx (brew install nginx —devel)
    
  • nginx (brew install nginx —devel)
    Linux安装
    vim到/etc/apt/sources.list
    增加以下两行,其中$codename自行去该网站查询,比如Ubuntu 14.04 是 trusty;
    deb http://nginx.org/packages/mainline/ubuntu/ $codename nginx
    deb-src http://nginx.org/packages/mainline/ubuntu/ $codename nginx
    

    然后sudo apt-get update && sudo apt-get install nginx就可以装最新支持HTTP2的nginx啦;

  • apache (brew install httpd24 —with-http2)[本文重点讲解nginx]
    Linux安装

    二.证书

    1.自签发

    打开提供的Demo文件,terminal打开/keys路径,输入./ca.sh http2test.com,也可以生成其他域名或泛域名(.xx.com).注意:也可以不用生成证书,直接使用keys文件下提供的http2test.com证书;
    Let’s Encrypt
    打开Let’s Encrypt的官网,这里讲解如果已经启动nginx的情况下,如何签发证书。
    步骤:

  • 首先需要把代码克隆下来:git clone https://github.com/letsencrypt/letsencrypt && cd letsencrypt
  • 然后./letsencrypt-auto --help会执行一些初始化工作,并且显示支持的命令;
  • 比如我的web目录在~/www下,此步骤需要已搭建好服务器,并且可以通过example.com访问~/www里的内容,如果是动态网站,需要在nginx层设置一个映射,将/.well-known/acme-challenge映射到刚设置好的目录,也就是~/www
    location /.well-known/acme-challenge {
    root /home/$username/www;
    }
    
  • (需要nginx已经装好,没装好的完成下面的nginx部分后再回来设置)那么./letsencrypt-auto certonly --webroot -w ~/www -d example.com,example.com是你希望申请证书的域名,然后证书下发成功。
  • 然后在nginx中设置证书信息
    ssl_certificate      /etc/letsencrypt/live/$example.com/fullchain.pem;
    ssl_certificate_key  /etc/letsencrypt/live/$example.com/privkey.pem;
    
  • 然后sudo nginx -t && sudo nginx -s reload就可以看到啦

三、基本工具

  • curl
    curl的基本用法是:
    curl -v -o /dev/null --http2 http://nghttp2.org
    这里输入的是HTTP而不是HTTPS是因为,这里会采用HTTP2的ClearText模式,使用101 改变协议协商升级为HTTP2协议。
Connected to nghttp2.org (106.186.112.116) port 80 (#0)> GET / HTTP/1.1> Host: nghttp2.org
> User-Agent: curl/7.48.0> Accept: */*
> Connection: Upgrade, HTTP2-Settings
> Upgrade: h2c
> HTTP2-Settings: AAMAAABkAAQAAP__>
< HTTP/1.1 101 Switching Protocols
< Connection: Upgrade
< Upgrade: h2c
* Received 101* Using HTTP2, server supports multi-use* Connection state changed (HTTP/2 confirmed)
* TCP_NODELAY set
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=21* Connection state changed (MAX_CONCURRENT_STREAMS updated)!
< HTTP/2.0 200< date:Sun, 10 Apr 2016 16:52:43 GMT
< content-type:text/html
< content-length:6646< last-modified:Sun, 03 Apr 2016 06:53:14 GMT
< etag:"5700bdda-19f6"< link:</stylesheets/screen.css>; rel=preload; as=stylesheet
< accept-ranges:bytes
< x-backend-header-rtt:0.000625< server:nghttpx nghttp2/1.10.0-DEV
< via:2 nghttpx
< x-frame-options:SAMEORIGIN
< x-xss-protection:1; mode=block
< x-content-type-options:nosniff
<

现在的大多数网站,都是通过302跳转到HTTPS网站来协商升级的,例如我厂的QQ邮箱;

Connected to mail.qq.com (183.60.15.162) port 80 (#0)
> GET / HTTP/1.1
> Host: mail.qq.com> User-Agent: curl/7.48.0
> Accept: */*
> Connection: Upgrade, HTTP2-Settings
> Upgrade: h2c
> HTTP2-Settings: AAMAAABkAAQAAP__>
<
HTTP/1.1 302 Found
< Server: TWS
< Connection: close
< Date: Sun, 10 Apr 2016 16:58:48 GMT
< Content-Type: text/html; charset=GB18030
< Location: https://mail.qq.com/cgi-bin/loginpage
< Content-Length: 0
<
  • nghttp
    官方文档,安装nghttp2后有配套的nghttp 客户端、nghttpd 服务器、nghttpx 反向代理、h2load 负载测试等工具。
    输入命令nghttp -nv https://nghttp2.org(n代表不输出,v代表详细信息):
    结果列出了连接过程中的HTTP2各个Stream信息,例如SETTINGS Frame,HEADER Frame等,也可以带上参数:
[  0.170] Connected
The negotiated protocol: h2
[  0.732] recv SETTINGS frame <length=12, flags=0x00, stream_id=0>
          (niv=2)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[  0.732] send SETTINGS frame <length=12, flags=0x00, stream_id=0>
          (niv=2)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[  0.732] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=3>
          (dep_stream_id=0, weight=201, exclusive=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=5>
          (dep_stream_id=0, weight=101, exclusive=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=7>
          (dep_stream_id=0, weight=1, exclusive=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=9>
          (dep_stream_id=7, weight=1, exclusive=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=11>
          (dep_stream_id=3, weight=1, exclusive=0)
[  0.732] send HEADERS frame <length=36, flags=0x25, stream_id=13>
          ; END_STREAM | END_HEADERS | PRIORITY
          (padlen=0, dep_stream_id=11, weight=16, exclusive=0)
          ; Open new stream
          :method: GET
          :path: /
          :scheme: https
          :authority: nghttp2.org
          accept: */*
          accept-encoding: gzip, deflate
          user-agent: nghttp2/1.9.1
[  0.891] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.891] recv (stream_id=13) :method: GET
[  0.891] recv (stream_id=13) :scheme: https
[  0.892] recv (stream_id=13) :path: /stylesheets/screen.css
[  0.892] recv (stream_id=13) :authority: nghttp2.org
[  0.892] recv (stream_id=13) accept-encoding: gzip, deflate
[  0.892] recv (stream_id=13) user-agent: nghttp2/1.9.1
[  0.892] recv PUSH_PROMISE frame <length=47, flags=0x04, stream_id=13>
          ; END_HEADERS
          (padlen=0, promised_stream_id=2)
[  0.892] recv (stream_id=13) :status: 200
[  0.892] recv (stream_id=13) date: Sun, 10 Apr 2016 17:00:25 GMT
[  0.892] recv (stream_id=13) content-type: text/html
[  0.892] recv (stream_id=13) content-length: 6646
[  0.892] recv (stream_id=13) last-modified: Sun, 03 Apr 2016 06:53:14 GMT
[  0.892] recv (stream_id=13) etag: "5700bdda-19f6"
[  0.892] recv (stream_id=13) link: </stylesheets/screen.css>; rel=preload; as=stylesheet
[  0.892] recv (stream_id=13) accept-ranges: bytes
[  0.892] recv (stream_id=13) x-backend-header-rtt: 0.000663
[  0.892] recv (stream_id=13) strict-transport-security: max-age=31536000
[  0.892] recv (stream_id=13) server: nghttpx nghttp2/1.10.0-DEV
[  0.892] recv (stream_id=13) via: 2 nghttpx
[  0.892] recv (stream_id=13) x-frame-options: SAMEORIGIN
[  0.892] recv (stream_id=13) x-xss-protection: 1; mode=block
[  0.892] recv (stream_id=13) x-content-type-options: nosniff
[  0.892] recv HEADERS frame <length=266, flags=0x04, stream_id=13>
          ; END_HEADERS
          (padlen=0)
          ; First response header
[  0.893] recv DATA frame <length=6646, flags=0x01, stream_id=13>
          ; END_STREAM
[  0.893] recv (stream_id=2) :status: 200
[  0.893] recv (stream_id=2) date: Sun, 10 Apr 2016 17:00:25 GMT
[  0.893] recv (stream_id=2) content-type: text/css
[  0.893] recv (stream_id=2) content-length: 39082
[  0.893] recv (stream_id=2) last-modified: Sun, 03 Apr 2016 06:53:14 GMT
[  0.893] recv (stream_id=2) etag: "5700bdda-98aa"
[  0.893] recv (stream_id=2) accept-ranges: bytes
[  0.893] recv (stream_id=2) x-backend-header-rtt: 0.000427
[  0.893] recv (stream_id=2) strict-transport-security: max-age=31536000
[  0.893] recv (stream_id=2) server: nghttpx nghttp2/1.10.0-DEV
[  0.893] recv (stream_id=2) via: 2 nghttpx
[  0.893] recv (stream_id=2) x-frame-options: SAMEORIGIN
[  0.893] recv (stream_id=2) x-xss-protection: 1; mode=block
[  0.893] recv (stream_id=2) x-content-type-options: nosniff
[  0.893] recv (stream_id=2) x-http2-push: 1
[  0.893] recv HEADERS frame <length=62, flags=0x04, stream_id=2>
          ; END_HEADERS
          (padlen=0)
          ; First push response header
[  1.407] recv DATA frame <length=16384, flags=0x00, stream_id=2>[  1.563] send WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
          (window_size_increment=33412)
[  1.740] recv DATA frame <length=16384, flags=0x00, stream_id=2>[  1.741] recv DATA frame <length=6314, flags=0x01, stream_id=2>
          ; END_STREAM
[  1.741] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
          (last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])

[  0.170] Connected
The negotiated protocol: h2
[  0.732] recv SETTINGS frame <length=12, flags=0x00, stream_id=0>
          (niv=2)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[  0.732] send SETTINGS frame <length=12, flags=0x00, stream_id=0>
          (niv=2)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):65535]
[  0.732] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=3>
          (dep_stream_id=0, weight=201, exclusive=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=5>
          (dep_stream_id=0, weight=101, exclusive=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=7>
          (dep_stream_id=0, weight=1, exclusive=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=9>
          (dep_stream_id=7, weight=1, exclusive=0)
[  0.732] send PRIORITY frame <length=5, flags=0x00, stream_id=11>
          (dep_stream_id=3, weight=1, exclusive=0)
[  0.732] send HEADERS frame <length=36, flags=0x25, stream_id=13>
          ; END_STREAM | END_HEADERS | PRIORITY
          (padlen=0, dep_stream_id=11, weight=16, exclusive=0)
          ; Open new stream
          :method: GET
          :path: /
          :scheme: https
          :authority: nghttp2.org
          accept: */*
          accept-encoding: gzip, deflate
          user-agent: nghttp2/1.9.1
[  0.891] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.891] recv (stream_id=13) :method: GET
[  0.891] recv (stream_id=13) :scheme: https
[  0.892] recv (stream_id=13) :path: /stylesheets/screen.css
[  0.892] recv (stream_id=13) :authority: nghttp2.org
[  0.892] recv (stream_id=13) accept-encoding: gzip, deflate
[  0.892] recv (stream_id=13) user-agent: nghttp2/1.9.1
[  0.892] recv PUSH_PROMISE frame <length=47, flags=0x04, stream_id=13>
          ; END_HEADERS
          (padlen=0, promised_stream_id=2)
[  0.892] recv (stream_id=13) :status: 200
[  0.892] recv (stream_id=13) date: Sun, 10 Apr 2016 17:00:25 GMT
[  0.892] recv (stream_id=13) content-type: text/html
[  0.892] recv (stream_id=13) content-length: 6646
[  0.892] recv (stream_id=13) last-modified: Sun, 03 Apr 2016 06:53:14 GMT
[  0.892] recv (stream_id=13) etag: "5700bdda-19f6"
[  0.892] recv (stream_id=13) link: </stylesheets/screen.css>; rel=preload; as=stylesheet
[  0.892] recv (stream_id=13) accept-ranges: bytes
[  0.892] recv (stream_id=13) x-backend-header-rtt: 0.000663
[  0.892] recv (stream_id=13) strict-transport-security: max-age=31536000
[  0.892] recv (stream_id=13) server: nghttpx nghttp2/1.10.0-DEV
[  0.892] recv (stream_id=13) via: 2 nghttpx
[  0.892] recv (stream_id=13) x-frame-options: SAMEORIGIN
[  0.892] recv (stream_id=13) x-xss-protection: 1; mode=block
[  0.892] recv (stream_id=13) x-content-type-options: nosniff
[  0.892] recv HEADERS frame <length=266, flags=0x04, stream_id=13>
          ; END_HEADERS
          (padlen=0)
          ; First response header
[  0.893] recv DATA frame <length=6646, flags=0x01, stream_id=13>
          ; END_STREAM
[  0.893] recv (stream_id=2) :status: 200
[  0.893] recv (stream_id=2) date: Sun, 10 Apr 2016 17:00:25 GMT
[  0.893] recv (stream_id=2) content-type: text/css
[  0.893] recv (stream_id=2) content-length: 39082
[  0.893] recv (stream_id=2) last-modified: Sun, 03 Apr 2016 06:53:14 GMT
[  0.893] recv (stream_id=2) etag: "5700bdda-98aa"
[  0.893] recv (stream_id=2) accept-ranges: bytes
[  0.893] recv (stream_id=2) x-backend-header-rtt: 0.000427
[  0.893] recv (stream_id=2) strict-transport-security: max-age=31536000
[  0.893] recv (stream_id=2) server: nghttpx nghttp2/1.10.0-DEV
[  0.893] recv (stream_id=2) via: 2 nghttpx
[  0.893] recv (stream_id=2) x-frame-options: SAMEORIGIN
[  0.893] recv (stream_id=2) x-xss-protection: 1; mode=block
[  0.893] recv (stream_id=2) x-content-type-options: nosniff
[  0.893] recv (stream_id=2) x-http2-push: 1
[  0.893] recv HEADERS frame <length=62, flags=0x04, stream_id=2>
          ; END_HEADERS
          (padlen=0)
          ; First push response header
[  1.407] recv DATA frame <length=16384, flags=0x00, stream_id=2>[  1.563] send WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
          (window_size_increment=33412)
[  1.740] recv DATA frame <length=16384, flags=0x00, stream_id=2>[  1.741] recv DATA frame <length=6314, flags=0x01, stream_id=2>
          ; END_STREAM
[  1.741] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
          (last_stream_id=2, error_code=NO_ERROR(0x00), opaque_data(0)=[])

还有这些参数:

-v : 显示详细信息
-n : 不输出请求返回数据内容
-t : 请求超时设置
-w : 设置初始窗口大小
-a : 解析页面获取页面上的资源
-H : 给请求增加特定头部信息,例如: -H‘:method:PUT‘-p: 设置请求权重
--no-dep : 不发送依赖信息
  • nghttpd
    官方文档,使用nghttpd,可以架设一个简易的支持HTTP2的服务器。打开附件中的示例文件,在路径demos/nghttp/里有一个run.sh(需要以管理员权限执行)

    $ cd demos/nghttp
    $ sudo ./run.sh [server-push]
    

    就可以执行提供的shell脚本,第三个参数server-push是可选的,如果不需要server-push功能,直接sudo ./run.sh就可以了,在本地设置好host 127.0.0.1 http2test.com后,就可以在本地浏览器中访问了,路径是https://http2test.com/examples/dashboard/。由于自签的证书不被信任,需要安装公钥keys/*.crt文件并信任(Mac中需要打开keychain这个软件,然后找到刚安装的证书,改为总是信任),安装信任后,打开Chrome就不会提示警告了;
    如果需要开启server-push功能,输入指令sudo ./run.sh server-push,shell脚本里设置了-p/examples/dashboard/=/examples/dashboard/d3.js,当请求路径/examples/dashboard/时,就推送/examples/dashboard/d3.js文件。

四、服务器准备

  • nginx
    nginx的conf文件里的设置,设置完后需要sudo nginx -s reload,由于nginx的ngx_http_v2_module模块是替代以前的ngx_http_spdy_module,故开启HTTP2支持后,就无法同时开启SPDY支持:

    server {
    listen       443 ssl http2;
    server_name  http2test.com; 
    
    ssl_certificate      $证书地址;
    ssl_certificate_key  $证书私钥地址;  
    
    ssl_session_cache    shared:SSL:1m;
    ssl_session_timeout  5m; 
    
    ssl_ciphers  HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers  on;   
    
    location / {
    root   $静态文件地址;
    index  index.html index.htm;
        }
    }
    
  • h2o
    这里引入下Server Push的概念,在上一篇概念篇有介绍道,Server Push就是,当请求时,服务器同时将其它文件也推送过来,HTTP2的说明中,并没有规定Server Push具体的实现策略,这个可由服务器和客户端自主决定:
  • Jetty:jetty通过referrer建立了一个依赖模型,该模型可以应用在CDN里,方便配置;
  • h2o:通过Cookie实现了cache aware server push——可感知缓存的服务器推送。第一次推送时,服务器端set-cookie,将要推送的路径+etag存入一个集合,通过算法生产指纹编码为base64存入cookie,之后通过cookie来判断是否需要推送该文件;
    这里着重介绍h2o,为什么h2o要这么做呢?因为流量就是钱啊。。。客户端接收到服务器端发送的PUSHPROMISE Frame后,可以通过是否发送RST Frame来拒绝掉服务器推送的文件,但是在这个过程中,服务器推送的文件可能已经发送一部分过来了,如果客户端决定不接收服务器推送的文件,那么之前发送的部分就是浪费掉的流量,h2o就是为了解决这个问题;在设置好h2o后,我们来看看第一次访问的结果:

    让我们来看看第二次访问的结果:

    可以看到,第二次访问时,并没有PUSHPROMISE Frame了,也就是说,服务器不再推送文件了。

五.开发准备

  • wireshark
    这里讲解基本的wireshark使用,由于大多数的HTTP2都是基于Over TLS版,也就是需要解密才能看到正确的HTTP2包内容;wireshark提供了两个方式:
    使用SSLKEYLOGFILE,使得wireshark可以使用Firefox/Chrome的解密信息
    首先在wireshark的Preferences -> Protocol -> SSL配置一个可读的文件地址,然后在环境变量,例如Mac是~/.bashprofile

    export SSLKEYLOGFILE=$刚配置的地址
    source     ~/.bashprofile
    

    通过Terminal打开Firefox或Chrome,这样才能使用环境变量SSLKEYLOGFILE
    open -a Google\ Chrome
    该方法的局限是,只能在电脑上抓包使用,并且只能使用Chrome和Firefox;
    还有一个方法是配置RSA私钥,不过这种办法的局限是多种加密方式不支持,并且该方法必须纪录完整的TLS握手过程,所以建议打开浏览器访问前就已经开始监听;
    配置好解密方式后,使用浏览器打开刚跑起来的HTTP2 Demo,https://http2test.com/examples/dashboard/,然后再筛选出输入http2并回车,就可以看到筛选的HTTP2包。

  • fiddler
    fiddler解密HTTPS采用的是中间人攻击的方法,客户端访问到fiddler代理服务器,然后fiddler代理服务器再模拟客户端访问到网站。那么,需要安装Fiddler的根认证证书,同时启用HTTPS解密功能。

    对于Fiddler来说,对于每个机器其实下发的其实是不同的根证书,所以,一定要通过Fiddler的配置网页来安装证书(配置代理后,打开网站http://ipv4.fiddler:8888,然后点击图中的FiddlerRoot Certificate来下载安装)

    针对iOS及部分高版本的Android,证书中的部分信息是必要的,有两个办法。
    (1) 采用如图所示的设置(iOS 9亲测可用),
    (2) 安装使用Fiddler CertMaker插件
    然后需要介绍的一个点是FiddlerScript,这是一个很强大的功能。如果需要将以前调试HTTP的方法在HTTPS同样适用,需要有这些设置。,然后之后我也会继续更新Fiddler调试部分的内容,请收藏哦。在Willow的rule里设置HTTPS -> HTTP; HTTPS -> File; 都是可以生效的。
    如果需要HTTPS -> HTTPS 或者 HTTPS -> HTTP,可以采用上面链接的方法,也可以设置oSession["x-replywithtunnel"] = "FakeTunnel"。
    if (oSession.HostnameIs("app.yourdomain.com"))
    {    // Handle CONNECT Tunnels
    if (oSession.HTTPMethodIs("CONNECT"))
    {
        oSession["x-replywithtunnel"] = "FakeTunnel";        return;
    }
    
    oSession.fullUrl = "http://somedomain:someport" + oSession.PathAndQuery;
    }
    

六.SSL/TLS部分小贴士

1.活用证书,提高性能

首先来看本地搭建的HTTPS服务:

第一个情况是,同一个IP,但是域名不同,同时,使用的证书也不同:第一张图显示的域名是http2test.com,第二张图显示的域名是http2.icese7en.com,他们使用的证书也是不同的,可以看到TCP Stream这一列,具有不同的序号(相同序号表明他们使用的是同一个TCP连接)

第二个情况是,同一个IP,域名不同,但是使用的证书是相同的:第一张图的域名是cdn1.http2test.com,第二张图的域名是cdn2.http2test.com,他们使用的证书(第三张图)是泛域名*.http2test.com,他们的TCP Stream序号都是30,复用同一条TCP连接



那么,如果域名不同,甚至都不是子域名的方式,也可以通过这一个点去优化吗?是可以的,通过证书里的subjectAltName,我们可以在证书里管理多个不同域名,例如google的证书:

不过这样证书很贵就是了 - -

2.SSL/TLS提高安全

HSTS——HTTP严格传输协议
HSTS主要是为了改善以下几个问题:

  • 没办法知道一个网站是否支持TLS:例如第一次连接时,如果没有指定协议名,会优先采用http协议,有安全隐患。而开启HSTS后,第一次(之前访问过该域名)之后的访问浏览器会自动强制使用HTTPS访问;
  • 对证书问题的宽容:未开启HSTS时,如果证书有问题,客户端只会提示警告,而不是禁止访问,开启HSTS后,会被禁止访问;
  • mixed-content问题:开启HSTS后,一个HTTPS页面上的同域名下的非HTTPS资源会自动升级为HTTPS访问;

要开启HSTS,只需要服务器端在返回头中返回(不支持IP)

Strict-Transport-Security: max-age=31536000 [; includeSubDomains] [; preload]
# includeSubDomains 可以开启子域名的HSTS功能# 不过需要评估这么做的是否会有负面影响

在max-age指定的时间内,浏览器都自动以HTTPS访问。如果需要关闭HSTS,返回max-age=0就可以了。

注意

  • HSTS的第一次访问仍然具有被挟持的危险,可通过HSTS preload来减轻影响(需要申请加入各浏览器的preload-list);
  • HSTS时间是基于本地时间计算的,如果客户端时间被篡改,可能会造成HSTS策略被失效绕过。
  • 引用自关于启用 HTTPS 的一些经验分享(一)

    只要你不能确保永远提供 HTTPS 服务,就不要启用。因为一旦 HSTS 生效,你再想把网站重定向为 HTTP,之前的老用户会被无限重定向,唯一的办法是换新域名

CSP——内容安全政策
CSP是一个声明式的安全机制,原本的目的是防止XSS跨站脚本攻击。例如,CSP可以完全禁止内联的Javascript代码的执行,控制哪些外联的Javascript文件可以被执行。

Content-Security-Policy: default-src ‘self‘; img-src *; script-src scripts.example.com
上面的CSP策略是,默认允许本源的资源的访问,允许所有URL的图片显示,外链脚本只允许来自于scripts.example.com的文件执行;

Content-Security-Policy: default-src https: ‘unsafe-inline‘ ‘unsafe-eval‘; connect-src https:
上面的CSP策略是,默认允许来自于任何URL的资源,只要它是安全的HTTPS,同时开启了内联JS和eval的执行(默认是被CSP禁止的),connect-src设定了Ajax请求只能请求HTTPS;(部分开启内联JS的执行可参考Content Security Policy Level 2介绍)

CSP上报
使用report-uri指令,违反CSP策略的行为都会被上报到该CGI

文章来源于公众号:小时光茶社(Tech Teahouse)

时间: 2024-10-12 20:44:11

HTTP/2探索第二篇——工具及应用的相关文章

Android开源项目第二篇——工具库篇

本文为那些不错的Android开源项目第二篇——开发工具库篇,主要介绍常用的开发库,包括依赖注入框架.图片缓存.网络相关.数据库ORM建模.Android公共库.Android 高版本向低版本兼容.多媒体相关及其他. Android开源项目系列汇总已完成,包括: Android开源项目第一篇——个性化控件(View)篇 Android开源项目第二篇——工具库篇 Android开源项目第三篇——优秀项目篇 Android开源项目第四篇——开发及测试工具篇 Android开源项目第五篇——优秀个人和

微信开发第二篇:工具篇

自从写了第一篇后,最近一直在整理另一个项目的需求,没有继续研究下去,今天晚上终于开始了我的第二篇. 本次微信的项目是想基于H5做的,所以现在的想法还是先从前端入手. 要做一个移动端H5的网站有很多种方式: 1.使用Html5.css3.js自己从头开始做. 但如果这样,对于目前主要从事项目管理及后端开发工作的我,无疑是困难重重:另外自己也已经对前端的东西很久没碰过了.如果选择这种方式,肯定会本末倒置.最后说不定整个项目都没得戏(虽说这个项目完全是自己的个人爱好!!) 2.使用现在已有的移动端H5

kubernetes之CI/CD工具jenkins第二篇,helm的使用

1. kubernetes之CI/CD第二篇-jenkins结合helm部署应用: 1. 概述: ?? 在前期的博文中我已经初步介绍过kubernetes环境下的CI/CD的使用.主要是jenkins slave pod自动创建和销毁,当有jenkins job任务执行的时候,就会自动创建一个jenkins slave pod.在本篇博文中,我们将介绍jenkins生成slave pod的另外一种方法,就是在pipeline脚本里面定义slave pod的镜像等,同时将Dockerfile.Je

认识IL代码---从开始到现在 &lt;第二篇&gt;

·IL代码分析方法 ·IL命令解析 ·.NET学习方法论 1.引言 自从『你必须知道.NET』系列开篇以来,受到大家很多的关注和支持,给予了anytao巨大的鼓励和动力.俱往昔,我发现很多的园友都把目光和焦点注意在如何理解IL代码这个问题上.对我来说,这真是个莫大的好消息,因为很明显我们的思路慢慢的从应用向底层发生着转变,技巧性的东西是一个方面的积累,底层的探索在我认为也是必不可少的修炼.如果我们选择了来关注这项修炼,那么我们就应该选择如何来着手这项修炼,首先关注anytao的『你必须知道的.N

EnjoyingSoft之Mule ESB基础系列第二篇:Mule ESB基本概念

目录 1. 使用Anypoint Studio开发 2. Mule ESB Application Structure - Mule ESB应用程序结构 3. Mule ESB Application整体构造 4. Mule ESB构造元素 - Flow 5. Mule ESB构造元素 - Connector 6. Mule ESB构造元素 - Processor Mule ESB在众多开源的ESB中处于领先者的地位,MuleSoft公司也作为独角兽,2017年在纽交所上市.我们作为MuleSo

拿出来分享了!VIP珍藏!!!全网最齐全的 DEDECMS模板 网盘地址!没有你找不到的!【第二篇】

拿出来分享了!VIP珍藏!!!全网最齐全的 DEDECMS模板 网盘地址!没有你找不到的! 模板类型最齐全: -------------优美的走起!---------- 五:DEDECMS模板--服装类模板列表: 织梦模板爱搭配服装行业dedecms门户模板下载.zip 35.25 MB昨天16:43VIP永久 服装行业dedecms模板.zip 138.09 KB昨天16:43VIP永久 织梦模板爱搭配服装行业dedecms门户模板下载.zip 35.25 MB昨天16:43VIP永久 201

Android开发艺术探索——第二章:IPC机制(上)

Android开发艺术探索--第二章:IPC机制(上) 本章主要讲解Android的IPC机制,首先介绍Android中的多进程概念以及多进程开发模式中常见的注意事项,接着介绍Android中的序列化机制和Binder,然后详细的介绍Bundle,文件共享,AIDL,Messenger,ContentProvider和Socker等进程间通讯的方法,为了更好的使用AIDL进行进程间通讯,本章引入了Binder连接池的概念,最后,本章讲解各种进程间通信方式的优缺点和使用场景,通过本章,可以让读者对

Android艺术开发探索——第二章:IPC机制(下)

Android艺术开发探索--第二章:IPC机制(下) 我们继续来讲IPC机制,在本篇中你将会学习到 ContentProvider Socket Binder连接池 一.使用ContentProvider ContentProvider是Android中提供的专门用来不同应用之间数据共享的方式,从这一点来看,他天生就是适合进程间通信,和Messenger一样,ContentProvider的底层实现同样也是Binder,由此可见,Binder在Android系统中是何等的重要,虽然Conten

Android高手速成--第二部分 工具库

主要包括那些不错的开发库,包括依赖注入框架.图片缓存.网络相关.数据库ORM建模.Android公共库.Android 高版本向低版本兼容.多媒体相关及其他. 一.依赖注入DI 通过依赖注入减少View.服务.资源简化初始化,事件绑定等重复繁琐工作 AndroidAnnotations(Code Diet)android快速开发框架项目地址:https://github.com/excilys/androidannotations文档介绍:https://github.com/excilys/a