nghttp2でhttp2を試してみる

vagrant環境：CentOS Linux release 7.1.1503 (Core)

公式通り、必要なモジュールをyumで入れる。
https://github.com/tatsuhiro-t/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
```
実際に必要だったモジュールは以下 pythonが必要。今回はv2.7.5

```
#yum install libtool binutils libev-devel autoconf automake python python-devel
```

libtoolsが無いとautoconf-iした時にメッセージが出る。

```lang:output
Can't exec "libtoolize": No such file or directory at /usr/share/autoconf/Autom4te/FileUtils.pm line 345, <GEN3> line 5.
autoreconf: failed to run libtoolize: No such file or directory
autoreconf: libtoolize is needed because this package uses Libtool
```


nghttp2 v1.5.0をgithubから

```
#wget https://github.com/tatsuhiro-t/nghttp2/releases/download/v1.5.0/nghttp2-1.5.0.tar.gz
#tar zxvf nghttp2-1.5.0.tar.gz
#cd nghttp2-1.5.0
#autoreconf -i
#automake
#autoconf
#./configure
#make
#make install
#make html
```

設定ファイルの作成

```
#touch /etc/sysconfig/nghttpd
#vi /etc/sysconfig/nghttpd
```

鍵の作成

```
#openssl genrsa 2048 > server.key
#openssl rsa -in server.key -out server.key
#openssl req -new -key server.key > server.csr
#openssl x509 -days 3650 -req -signkey server.key < server.csr > server.crt
```

nghttp2ユーザの作成

```
#chmod 600 server.crt
#chmod 600 server.key
#chown nghttp2:nghttp2 /root/ssl/server.key
#chown nghttp2:nghttp2 /root/ssl/server.crt
```

サービス登録

```
#cd /etc/systemd/system
#touch nghttpd.service
#vi nghttpd.service
#systemctl daemon-reload
#systemctl list-unit-files | grep nghttpd
#systemctl start nghttpd.service

```

確認

```
#ss -antup
Netid  State      Recv-Q Send-Q     Local Address:Port       Peer Address:Port
tcp    UNCONN     0      0                      *:51203                 *:*      users:(("dhclient",1175,20))
tcp    UNCONN     0      0                      *:68                    *:*      users:(("dhclient",1175,6))
tcp    UNCONN     0      0                     :::61435                :::*      users:(("dhclient",1175,21))
tcp    LISTEN     0      128                    *:22                    *:*      users:(("sshd",1147,3))
tcp    LISTEN     0      10             127.0.0.1:25                    *:*      users:(("sendmail",1213,4))
tcp    ESTAB      0      0              10.0.2.15:22             10.0.2.2:57340  users:(("sshd",2512,3),("sshd",2509,3))
tcp    LISTEN     0      128                   :::8080                 :::*      users:(("nghttpd",1149,10))
tcp    LISTEN     0      128                   :::22                   :::*      users:(("sshd",1147,4))

# ps ax | grep nghttp
21983 ?        Ss     0:00 /usr/local/bin/nghttpd -n 1 -d /var/www/html 8080 /etc/pki/tls/private/server.key /etc/pki/tls/private/server.crt
```

FireWalldを止める

```
#systemctl stop firewalld
#systemctl disable firewalld
```
ここまでで適当なディレクトリにindex.htmlファイルをおくと、http2でのブラウザ確認ができる。

<h2>curlをhttp2に対応させる</h2>
もともとCentOSに入っているopenssl,zlib,curlを使わず、最新を持ってくる。

```
# curl -LO https://www.openssl.org/source/openssl-1.0.2e.tar.gz
# tar zxvf openssl-1.0.2e.tar.gz
# cd openssl-1.0.2e
# ./config shared zlib-dynamic
# make && make test
# sudo make install

# curl -LO http://zlib.net/zlib-1.2.8.tar.gz
# tar zxvf zlib-1.2.8.tar.gz
# cd zlib-1.2.8
# ./configure
# make && make test
# make install

# curl -LO http://curl.haxx.se/download/curl-7.46.0.tar.gz
# tar zxvf curl-7.46.0.tar.gz
# cd curl-7.46.0
# ./configure --help
# ./configure --with-nghttp2=/usr/local/

libnghttp2を使う ※環境によっては、boostが必要
# cd nghttp2をインストールしたディレクトリ
# ./configure --enable-asio-lib
# make
# make install
```

```lang:output
curl version:     7.46.0
Host setup:       x86_64-pc-linux-gnu
Install prefix:   /usr/local
Compiler:         gcc
SSL support:      enabled (OpenSSL)
SSH support:      no      (--with-libssh2)
zlib support:     enabled
GSS-API support:  no      (--with-gssapi)
TLS-SRP support:  no      (--enable-tls-srp)
resolver:         default (--enable-ares / --enable-threaded-resolver)
IPv6 support:     enabled
Unix sockets support: enabled
IDN support:      no      (--with-{libidn,winidn})
Build libcurl:    Shared=yes, Static=yes
Built-in manual:  enabled
--libcurl option: enabled (--disable-libcurl-option)
Verbose errors:   enabled (--disable-verbose)
SSPI support:     no      (--enable-sspi)
ca cert bundle:   /etc/pki/tls/certs/ca-bundle.crt
ca cert path:     no
LDAP support:     no      (--enable-ldap / --with-ldap-lib / --with-lber-lib)
LDAPS support:    no      (--enable-ldaps)
RTSP support:     enabled
RTMP support:     no      (--with-librtmp)
metalink support: no      (--with-libmetalink)
PSL support:      no      (libpsl not found)
HTTP2 support:    enabled (nghttp2)★
Protocols:        DICT FILE FTP FTPS GOPHER HTTP HTTPS IMA
```

googleはhttp2対応していてyahooはしていなかった。

```
#/usr/local/bin/nghttp -nv https://google.com
[  0.015] Connected
[  0.020][NPN] server offers:
          * h2
          * spdy/3.1
          * http/1.1
The negotiated protocol: h2 ★
[  0.032] recv SETTINGS frame <length=18, flags=0x00, stream_id=0>
          (niv=3)
          [SETTINGS_MAX_CONCURRENT_STREAMS(0x03):100]
          [SETTINGS_INITIAL_WINDOW_SIZE(0x04):1048576]
          [SETTINGS_MAX_FRAME_SIZE(0x05):16384]
[  0.032] recv WINDOW_UPDATE frame <length=4, flags=0x00, stream_id=0>
          (window_size_increment=983041)
[  0.032] 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.032] send SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.032] send PRIORITY frame <length=5, flags=0x00, stream_id=3>
          (dep_stream_id=0, weight=201, exclusive=0)
[  0.032] send PRIORITY frame <length=5, flags=0x00, stream_id=5>
          (dep_stream_id=0, weight=101, exclusive=0)
[  0.032] send PRIORITY frame <length=5, flags=0x00, stream_id=7>
          (dep_stream_id=0, weight=1, exclusive=0)
[  0.032] send PRIORITY frame <length=5, flags=0x00, stream_id=9>
          (dep_stream_id=7, weight=1, exclusive=0)
[  0.032] send PRIORITY frame <length=5, flags=0x00, stream_id=11>
          (dep_stream_id=3, weight=1, exclusive=0)
[  0.032] send HEADERS frame <length=35, 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: google.com
          accept: */*
          accept-encoding: gzip, deflate
          user-agent: nghttp2/1.5.0
[  0.037] recv SETTINGS frame <length=0, flags=0x01, stream_id=0>
          ; ACK
          (niv=0)
[  0.037] recv (stream_id=13) :status: 302
[  0.037] recv (stream_id=13) cache-control: private
[  0.037] recv (stream_id=13) content-type: text/html; charset=UTF-8
[  0.037] recv (stream_id=13) location: https://www.google.co.jp/?gfe_rd=cr&ei=ESVpVsPeOer98weXwJPYCA
[  0.037] recv (stream_id=13) content-length: 262
[  0.037] recv (stream_id=13) date: Thu, 10 Dec 2015 07:09:05 GMT
[  0.037] recv (stream_id=13) server: GFE/2.0
[  0.037] recv (stream_id=13) alternate-protocol: 443:quic,p=0
[  0.037] recv (stream_id=13) alt-svc: clear
[  0.037] recv HEADERS frame <length=160, flags=0x04, stream_id=13>
          ; END_HEADERS
          (padlen=0)
          ; First response header
[  0.037] recv DATA frame <length=262, flags=0x01, stream_id=13>
          ; END_STREAM
[  0.038] recv PING frame <length=8, flags=0x00, stream_id=0>
          (opaque_data=0000000000000000)
[  0.038] send GOAWAY frame <length=8, flags=0x00, stream_id=0>
          (last_stream_id=0, error_code=NO_ERROR(0x00), opaque_data(0)=[])

yahooにアクセス
# /usr/local/bin/nghttp -nv https://yahoo.com
[  0.100] Connected
[  0.191][NPN] server offers:
          * spdy/3.1
          * spdy/3
          * http/1.1
          * http/1.0
[ERROR] HTTP/2 protocol was not selected. (nghttp2 expects h2)
Some requests were not processed. total=1, processed=0
```

curlを使ってアクセス

```
# curl -vso /dev/null --http2 https://youtube.com
* Rebuilt URL to: https://youtube.com/
*   Trying 216.58.221.14...
* Connected to youtube.com (216.58.221.14) port 443 (#0)
* Cipher selection: ALL:!EXPORT:!EXPORT40:!EXPORT56:!aNULL:!LOW:!RC4:@STRENGTH
* successfully set certificate verify locations:
*   CAfile: /etc/pki/tls/certs/ca-bundle.crt
  CApath: none
* TLSv1.2 (OUT), TLS handshake, Client hello (1):
} [252 bytes data]
* TLSv1.2 (IN), TLS handshake, Server hello (2):
{ [116 bytes data]
* NPN, negotiated HTTP2 (h2)
* TLSv1.2 (IN), TLS handshake, Certificate (11):
{ [3700 bytes data]
* TLSv1.2 (IN), TLS handshake, Server key exchange (12):
{ [148 bytes data]
* TLSv1.2 (IN), TLS handshake, Server finished (14):
{ [4 bytes data]
* TLSv1.2 (OUT), TLS handshake, Client key exchange (16):
} [70 bytes data]
* TLSv1.2 (OUT), TLS change cipher, Client hello (1):
} [1 bytes data]
* TLSv1.2 (OUT), TLS handshake, Unknown (67):
} [36 bytes data]
* TLSv1.2 (OUT), TLS handshake, Finished (20):
} [16 bytes data]
* TLSv1.2 (IN), TLS change cipher, Client hello (1):
{ [1 bytes data]
* TLSv1.2 (IN), TLS handshake, Finished (20):
{ [16 bytes data]
* SSL connection using TLSv1.2 / ECDHE-ECDSA-AES128-GCM-SHA256
* Server certificate:
*        subject: C=US; ST=California; L=Mountain View; O=Google Inc; CN=*.google.com
*        start date: Nov 26 00:09:43 2015 GMT
*        expire date: Feb 23 00:00:00 2016 GMT
*        subjectAltName: youtube.com matched
*        issuer: C=US; O=Google Inc; CN=Google Internet Authority G2
*        SSL certificate verify ok.
* 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=0
* Using Stream ID: 1 (easy handle 0x1ad2fb0)
> GET / HTTP/1.1
> Host: youtube.com
> User-Agent: curl/7.46.0
> Accept: */*
>
< HTTP/2.0 301
< date:Thu, 10 Dec 2015 07:38:04 GMT
< server:gwiseguy/2.0
< location:https://www.youtube.com/
< content-length:0
< content-type:text/html
< x-xss-protection:1; mode=block
< alternate-protocol:443:quic,p=0
< alt-svc:clear
<
* Connection #0 to host youtube.com left intact
```


参考
http://takeshiyako.blogspot.jp/2015/09/curl-http2.html
https://blog.cloudflare.com/tools-for-debugging-testing-and-using-http-2/
http://qiita.com/0xfffffff7/items/3a3c75f46c781d83a70d