http2协议介绍及抓包分析

0x00 简介

之前有个Pwnhub的题目,学习了下http2相关知识,把相关知识简单记录下。题目是gopher协议内网打http2服务,不自己构造http2协议包的,可以用curl配合nc简单构造的小技巧。

1
2
3
4
5
6
curl -vv --http2-prior-knowledge 127.0.0.1:1234
nc -lvvv 1234 > res.txt # URL编码数据称gopher协议

得到返回结果,可以使用nc解码得到flag:
nc -lvvv 1234 < response.res
curl -vv --http2-prior-knowledge 127.0.0.1:1234

题目还是主要能让我们学到相关知识,之后我也将博客升级成了https+http2。这里记录下http2协议的知识点:

  • 头部(Header)基于Huffman编码,实现了HPACK算法压缩。python有hpack库,直接可以编码和解码。

    1
    2
    3
    4
    5
    6
    7
    from hpack import Encoder, Decoder

    e = Encoder()
    encoded_bytes = e.encode(headers)

    d = Decoder()
    decoded_headers = d.decode(encoded_bytes)
  • 使用二进制而非明文传输。

  • http2协议分为两种:h2和h2c。h2c通过TCP纯明文传输。h2则是HTTP/2协议通过TLS加密与客户端服务端交互传输。现在浏览器不支持直接传输的h2c协议,只支持h2。因此,Web网站必须先上https才能使用http2协议。

  • 多种压缩和二进制传输技术,使其速度变快,更安全。

0x01 Nginx配置http2

  • nginx版本升级,Docker直接使用最新版本镜像即可。
  • nginx配置https + http2
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    listen       443 ssl http2; # 这里加http2就行。
    server_name your_server;

    ssl_certificate /cert/cert.pem;
    ssl_certificate_key /cert/cert.key;
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
    ssl_ciphers HIGH:!aNULL:!MD5;

    ssl_prefer_server_ciphers on;
    ssl_session_timeout 5m;

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

安装插件http2-and-spdy-indicator,右上角会出现蓝色标记。
蓝色标记
使用curl -v命令也能看到http2的请求过程:

0x02 wireshark抓包分析

1. h2c明文抓包

使用Spring Boot可以搭建明文的http2服务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.AprLifecycleListener;
import org.apache.coyote.http2.Http2Protocol;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizer;
import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory;
import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory;
import org.springframework.context.annotation.Bean;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;

@SpringBootApplication
public class ApplicationHttp2 extends WebMvcConfigurerAdapter {
/**
* https://github.com/snowdrop/quickstart-spring-boot-http-2
* @return
*/

@Bean
public EmbeddedServletContainerCustomizer tomcatCustomizer() {
return (container) -> {
if (container instanceof TomcatEmbeddedServletContainerFactory) {
((TomcatEmbeddedServletContainerFactory) container)
.addConnectorCustomizers((connector) -> {
connector.addUpgradeProtocol(new Http2Protocol());
connector.addLifecycleListener(new AprLifecycleListener());
});
}
};
}

@Bean
public EmbeddedServletContainerFactory servletContainer() {
TomcatEmbeddedServletContainerFactory container = new TomcatEmbeddedServletContainerFactory();
container.addAdditionalTomcatConnectors(createStandardConnector());
return container;
}

private Connector createStandardConnector() {
Connector connector = new Connector("org.apache.coyote.http11.Http11NioProtocol");
connector.addUpgradeProtocol(new Http2Protocol());
connector.setPort(8087); // curl -vv --http2 127.0.0.1:8087
return connector;
}

public static void main(String[] args) {
SpringApplication.run(ApplicationHttp2.class, args);
}
}
/*
设置application.properties
server.http2.enabled=true
*/

run起来抓包,只能使用curl -v --http2-prior-knowledge 127.0.0.1:8087访问,然后用wireshark抓包,清楚地看到是基于TCP的二进制协议包传输: 图中框住的部分相当于HTTP1的request和response,但都是二进制内容~

2. wireshark抓https+http2包

wireshark支持http2协议,可以自动解压头部数据,但首先需要抓到https的包。参考使用Wireshark 调试HTTP/2流量进行配置:

1
2
3
4
5
6
7
8
9
10
# 新建目录
mkdir ~/tls && touch ~/tls/sslkeylog.log

# 设置环境变量
export SSLKEYLOGFILE=~/tls/sslkeylog.log"

# 设置wireshark的SSL协议「(Pre)-Master-Secret log filename」为LogFile~

# 命令行打开firefox(chrome没成功)
open /Applications/Firefox.app

如图所示,能看到解压的头部信息,也能看到非常详细的二进制交互过程~

0x03 参考

http2 rfc文档
https://httpwg.org/specs/rfc7540.html
https://imququ.com/post/http2-traffic-in-wireshark.html
https://github.com/snowdrop/quickstart-spring-boot-http-2/blob/master/README.md

文章作者: angelwhu
文章链接: https://www.angelwhu.com/paper/2019/02/18/introduction-to-http2-protocol-and-packet-capture-analysis/
版权声明: 本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 angelwhu_blog