Monday, December 12, 2016

103 Early Hints に対応した Starlet 0.31 をリリースしました

Perl のウェブアプリケーションサーバである Starlet の新バージョン、0.31をリリースしました。

今回搭載された新機能は 100 番台の中間レスポンスの送信に対応した点です。

たとえば以下のような感じで 103 Early Hints レスポンスを送信することで、アプリケーションでリクエストを処理する前に、HTTP/2 リバースプロキシに関連アセットのプッシュの開始を指示することができます

sub {
    my $env = shift;
    $env["psgix.informational"}->(103, [
      'link' => '; rel=preload'
    ]);
    my $resp = ... application logic ...
    $resp;
}

Early Hints は、現在 IETF の HTTP WG で Call for Adoption を迎えている段階ですが、H2O version 2.1-beta のほか、nghttpxApache HTTP Server の HTTP/2 実装である mod_h2 の trunk などが既に対応しています。

注: HTTP クライアントによっては中間レスポンスの処理にバグを抱えている可能性があるため、Early Hints の使用はリバースプロキシを挟んでいる場合に限ることを現時点ではおすすめします。

Saturday, December 10, 2016

HTTP/2の課題と将来について、YAPC Hokkaidoで話してきた

スライドは以下になります。内容は先月のVelocity in Amsterdamでの発表と、それ以降のアップデートですが、スライドが日本語になっているので、日本人の方にはこちらのほうが良いかと思います。

Sunday, October 30, 2016

mmapを使ってファイルベースの巨大なバッファを確保する話

小さなバッファはインメモリでもつが、メモリに収まらないような大きなバッファはテンポラリファイルを作り、file I/Oでアクセスする、というのが昔からの汎用的なバッファ実装のアプローチ。

だが、バッファに格納するデータ量によってアクセス手段を変えるというのはめんどくさいし、そこを抽象化すると無駄なオーバーヘッドが発生する。

幸いなことに最近は、メモリ空間が広い 64bit CPU だけ考えればいい。なので、ファイルの「読み込み」については、めんどくさいから全部mmapするというのが一般的なアプローチになってきている(例: LLVMのリンカであるlld)。

同様のことが、テンポラリファイルを使う可変長のバッファについても可能であり、h2o では実際に実装している。詳しくは h2o_buffer_reserve 関数の実装を見てもらえばいいと思いますが、ざっくりとした手順は以下のとおり:

▪️バッファ作成もしくはリサイズ処理:
  1. テンポラリファイルを作り、すぐ消す(作成の場合のみ。mkstemp, unlink してから file descriptor を使い続ける)
  2. サイズを設定する(posix_fallocate もしくは ftruncate)
  3. 旧来のマップされた領域を munmap する(リサイズの場合のみ)
  4. 全体を mmap する
▪️解放処理:
  1. munmap して close する

Windowsなら、ファイルを消すのを解放時にする必要があるかも。

Wednesday, September 14, 2016

H2O version 2.0.4 / 2.1.0-beta3 released including a vulnerability fix

Today we have released H2O version 2.0.4 / 2.1.0-beta3, which includes a fix to a vulnerability (CVE-2016-4864).

Users of H2O are advised to update immediately.

For detail, please refer to the issue page at https://github.com/h2o/h2o/issues/1077.

Thursday, September 8, 2016

H2O version 2.0.3 / 2.1.0-beta2 released

I am happy to announce the release of H2O HTTP/2 server version 2.0.3 and 2.1.0-beta2.

Version 2.0.3 is a maintenance release fixing issues found since the release of 2.0.2.

Version 2.1.0-beta2 introduces many features in addition to those introduced in 2.1.0-beta1, including mruby-based DSL for access control and DoS mitigation.

Please let us know if you find any issues in the beta release. We plan to release final version of 2.1.0 pretty soon.

Friday, June 24, 2016

H2O HTTP/2 server 2.0.1 / 2.1.0-beta1 released, with new features and performance optimizations

Today I am happy to announce the release of H2O HTTP/2 server version 2.0.1 and 2.1.0-beta1.

Version 2.0.1 is a bug-fix release of the 2.0 series. Existing users can upgrade to the new version to avoid the issues listed in the changeling.

Version 2.1.0-beta1 is the first beta release of 2.1, with a new throttle-response handler for per-response bandwidth throttling, and an enhancement to the status handler (pull #893). It also includes two new features that improve HTTP/2 performance: TCP latency optimization and support for link: rel=preload headers in informational response (pull #916).

With TCP latency optimization, users can expect 1 RTT or more reduction in time-to-render if the main resource (i.e. HTML) is much larger INITCWND (typically ~15KB).

The reduction comes from the fact that with the optimization enabled, H2O tries to keep the amount of HTTP/2 frames kept unsent in the TCP send buffer very small (to just two packets) during the slow-start phase. Since the amount of data unsent is kept small, the server can switch to sending a resource that blocks the rendering path (e.g. CSS) immediately when it receives a request for such resource, instead of pushing the HTML body stored in the TCP send buffer. As CWND grows, the connection handling switches to bandwidth-optimization mode, that pre-fills more data into the send buffer so that the kernel can send additional data immediately after receiving ACKs without user-space intervention.

Support for link: rel=preload headers in informational response helps web developers utilize HTTP/2 push. Use of the link header is becoming the standard way to instruct HTTP/2 servers to start pushing assets. The downside of the approach is that application servers typically cannot send the header until it generates the final response. Generation of the final response often involves time-consuming operations such as access to the database, keeping the HTTP/2 connection idle for that period.

Use of informational response lets us use the time slot for pushing asset files. Application servers can now send an informational response with link rel=preload headers to H2O to start pushing the asset files, then perform heavy tasks, and send the final response. Use of 1xx response will not cause interoperability issues, since only the final response is sent to the client connected to H2O.

Details of the two optimizations were covered in my presentation at Tokyo RubyKaigi 11. The slides are shown below:

Wednesday, June 1, 2016

H2O HTTP2 server 2.0 released!

We are happy to announce the release of H2O version 2.0.

It is a major update from 1.7 series, including many improvements and bug fixes.

The most prominent changes are:Full list of changes can be found here. Please refer to the reference documentation to find out how to use them.

Have fun!

Thursday, May 26, 2016

H2O version 1.7.3 / 2.0.0-beta5 released with a vulnerability fix

We have just released version 1.7.3 and 2.0.0-beta5 of the H2O HTTP/2 server.

The releases include a fix for a security issue (CVE-2016-4817). Existing users are encouraged to update their installations.

The details of the issue can be found here.

We would like to thank Tim Newsham for reporting the issue and Frederik Deweerdt for providing a fix.

Monday, May 9, 2016

H2O HTTP/2 server 1.7.2 / 2.0.0-beta3 released

Today I have released H2O HTTP/2 server version 1.7.2 and 2.0.0-beta3.

The releases include an updated version of LibreSSL that fixes CVE-2016-2107; users of H2O built with the bundled version of LibreSSL are advised to update their installations.

In addition to the fix, 2.0.0-beta3 includes many new features and bug fixes.

Especially, support for reverse-proxying over HTTPS (#875) and the new configuration directives for tweaking environment variables passed to FastCGI (#868) might be helpful to the users who have wanted them.

We plan to release the final version of 2.0 soon, and then proceed to optimizing the server even further. Stay tuned!

Wednesday, March 23, 2016

H2O version 2.0.0-beta2 released, with a new "status" handler

Today I am happy to announce the release of H2O HTTP/2 server version 2.0.0-beta2.

The release comes with the new status handler that shows the HTTP requests in-flight. Now, you can monitor what's going on inside H2O!

Some notable features are:
  • both HTTP/1 and HTTP/2 requests are shown
  • HTTP/2 priorities are shown
  • the screen can be updated automatically by clicking the Refresh checkbox


Under the hood, the status is served via a JSON API (lib/handler/status.c L169), and rendered by a static HTML document(share/h2o/status/index.html). So it would be easy for anyone to extend the status or retrieve and use the status from another program.

The documentation of the status handler can be found here.

Thursday, March 17, 2016

File-level mapping introduced in H2O version 2.0

As the developer of H2O, the lack of ability to define a mapping for a specific path (not a directory) has been one of the complaints I hear the most. Finally, we have a fix for the issue, and that is why the next release will be given the number 2.0.

Starting from H2O version 2.0.0beta-1, it is possible to write a configuration like the following. The example maps all requests to a FastCGI server, with the exception of /robots.txt and /favicon.ico being served statically.
paths:
  /:
    fastcgi.connect:
      port: /tmp/fcgi.sock
      type: unix
  /robots.txt:
    file.file: /path/to/robots.txt
  /favicon.ico:
    file.file: /path/to/favicon.png
Pretty straight forward, isn't it?

For details, please refer to the updated documentation of paths directive, or refer to the discussion in the pull request.

Tuesday, March 15, 2016

H2O HTTP/2 server goes 2.0 adding support for Brotli

Today, I am happy to announce the release of H2O version 2.0.0-beta1, the first release of the 2.0 series. In the release, we have added support for Brotli in two ways.

For those who do not know, Brotli is a new compression method developed by Google. It is said to compress files ~20% smaller than gzip - means less bandwidth consumed and faster rendering on the client side. Mozilla has already added support for Brotli in Firefox 44, and Chrome is gradually turning the knob on as well.

Starting with H2O version 2.0.0-beta1, when the file.send-compressed directive is set to ON, the server sends a file with .br or .gz suffix instead of file being requested should such file exist. For example, if index.html is requested with a Accept-Encoding: br request header, and if a file named index.html.br exists, the server sends the contents of index.hmtl.br as the response with the Content-Encoding: br response header being set. In case the client is capable of decompressing both algorithms both algorithms and if both of .br and .gz files exist, the .br file is selected as the response.
# send pre-compressed files (.br or .gz)
file.send-compressed: ON

The other directive: compress controls on-the-fly compression. When turned on, it compresses the response as it is being sent to the client, using either brotli or gzip depending on the configuration and browser support. This can be used for compressing output from PHP and other dynamically-generated content.
# perform on-the-fly compression (brotli or gzip)
compress: [ brotli, gzip ]
Server administrators may also be interested in fine-tuning the compression quality of the compression methods. The following configuration sets the compression quality of brotli to 4 and gzip to 6, a suggested setting by Understanding Brotli's Potential - The Akamai Blog. The compression speed becomes about half of the default (1 for both gzip and brotli), but the size of the content after compression is expected to become ~15% smaller for both methods.
# perform more effective (but CPU-intensive) compression
compress:
  brotli: 4
  gzip:   6

In my upcoming blogposts I will cover other changes in the 2.0 release of H2O. Stay tuned!

Friday, March 11, 2016

H2O version 1.7.1 released

Today we have shipped version 1.7.1 of the H2O HTTP/2 server.

It includes several bug fixes and stability improvements from 1.7.0. Users of existing versions are recommended to upgrade to 1.7.1.

Please refer to the Changelog of 1.7.1 for details.

Wednesday, February 10, 2016

Name Constraints を使った独自CAの運用手順

ウェブブラウザが新機能をHTTPSでしか有効にしないことが多くなってきたので、開発環境でもHTTPSを使いたい。でも、開発環境用にサーバ証明書を買うのは手間。Let's Encryptも運用がめんどくさいとか、社内からしかアクセスできないサーバへの証明書発行が難しいとかいろいろあるし…ってそこでName Constraintsを使った独自CAですよ奥さん。

Name Constraints が何であるかについては、以前オレオレ認証局の適切な運用とName Constraintsに書いたとおり。

本稿では、Name Constraintsを使うCAの運用手順を説明する。

1. CA鍵と証明書の作成

1.1. CAの秘密鍵を作成
% openssl genrsa -out ca.key 2048

1.2. openssl.cnfにCA証明書に設定する属性を指定するセクションを追記
[private_ca]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always,issuer
basicConstraints=critical,CA:true
nameConstraints=critical,permitted;DNS:.example.com
注:nameConstraintsの項がCAが証明書を発行できる対象のドメインを指定。この例では.example.com。

1.3. CA証明書の作成
% openssl req -new -x509 -days 3650 -key ca.key -out ca.crt \
  -extensions private_ca

2. 証明書管理用ディレクトリを作成
% mkdir -p demoCA/newcerts
% touch demoCA/index.txt
% echo 00 > demoCA/serial
注:ディレクトリ名(demoCA)はopenssl.cnfの設定で変更可能。

3. 証明書発行要求を受け取って証明書を発行
% openssl ca -keyfile ca.key -cert ca.crt \
  -extensions usr_cert -policy policy_anything -days 365 \
  -md sha256 -in foo.example.com.csr -out foo.example.com.crt

以上です。

難点としては、SafariおよびOSXで動作するChromeではこのルート証明書で署名されたサーバ証明書を正当なものとして認識してくれないところ(手動でサーバ証明書を登録すれば使えるはず)。他のウェブブラウザ+モダンなOSなら問題ないはず。

Friday, February 5, 2016

H2O HTTP/2 server 1.7.0 released; added a new benchmark

Today, I am happy to announce the release of H2O HTTP/2 server, version 1.7.0.

Major additions in this update are:
  • asynchronous HTTP client for mruby handler
  • Support for CGI and Basic Authentication
  • Support for wild-card hostnames

You can find more detailed description of the additions in my previous blogpost: H2O version 1.7.0-beta1 released with enhanced mruby scripting, CGI, and much more. And along with the new features, we have also enabled the use of Neverbleed by default, to reduce the risk of private key disclosure in case of a vulnerability.

We have also updated the numbers of the request-per-seconds benchmark.

I have seen many people hesitating to move to HTTPS or HTTP/2 in fear of performance issues. But what is apparent from this benchmark is that the performance of HTTP/2 with TLS is actually on par with HTTP/1 without TLS (in case of nginx) or much faster (in case of H2O).


Details of the benchmark (along with other benchmarks) can be found at h2o.examp1e.net/benchmarks.html.

Wednesday, January 13, 2016

H2O 1.6.2 released fixing a response splitting vulnerability in redirect handler

I have just released H2O version 1.6.2 that includes a fix for a response splitting vulnerability found in prior releases.

Users using the redirect directive are affected; they are advised to update immediately.

Edit: version 1.7.0-beta3 has also been released fixing the same issue in the earlier releases of 1.7.0 beta series.

Related Links:
https://github.com/h2o/h2o/releases/tag/v1.6.2
https://h2o.examp1e.net/vulnerabilities.html#CVE-2016-1133
https://github.com/h2o/h2o/issues/682
https://github.com/h2o/h2o/pull/684

Tuesday, January 5, 2016

H2O version 1.7.0-beta1 released with enhanced mruby scripting, CGI, and much more

Today I am happy to announce that we have tagged the 1.7.0-beta1 release of H2O HTTP2 server. Among the changes, there are few ones that should be noted.

HTTP client in mruby #643

In 1.7, mruby support has ben enhanced so that handlers written in mruby can issue HTTP requests. And it is damn simple. Shown below is a full-fledged reverse proxy implementation using mruby.
mruby.handler: |
  Proc.new do |env|
    # copy headers
    headers = {}
    env.each do |key, value|
      if /^HTTP_/.match(key)
        headers[$'] = value
      end
    end
    # issue the request
    http_request(
      "http://app.example.com#{env["REQUEST_URI"]}",
      method:  env["REQUEST_METHOD"],
      headers: headers,
      body:    env["rack.input"],
    ).join
  end
H2O exports one ruby method named http_request. It takes a URL and a hash of optional parameters (e.g. method, headers, body) as the arguments, and returns immediately a handle to the request. All the network operations are handled asynchronously in the event loop of H2O.

When the mruby code calls the #join method, it returns a Rack response, either immediately (if available), or when the response headers become available. The returned body (3rd element of the response array) is an object that responds to #each; calling the method will yield the chunks of an HTTP response as they arrive.

Using the asynchronous nature of the HTTP client interface, it is possible to implement sophisticated server-side logic like Edge-side includes in very few lines of code; hopefully I will cover that in a different post.

Support for CGI #618

A FastCGI-to-CGI gateway script is included in the distribution. As shown in the example below, it is easy to create per-extention mapping to the gateway script to run CGI applications as they do on the Apache HTTP server.
file.custom-handler:
  extension: .cgi
  fastcgi.spawn:
    command: "exec share/h2o/fastcgi-cgi"
It also has the flexibility to limit the number of CGI processes running concurrently (by using --max-workers option), or to run CGI applications under different directories with different user privileges by specifying appropriate user names for each directory-level fastcgi.spawn configuration.

Support for Basic Authentication #624

The distribution also bundles a basic authenticator written in mruby. The configuration snippet below will be enough to understand how it should be configured.
mruby.handler: |
  require "#{$H2O_ROOT}/share/h2o/mruby/htpasswd.rb"
  Htpasswd.new("/path/to/.htpasswd", "realm-name")
file.dir: /path/to/secret-files
The script will also be a good reference for people learning how to write mruby handlers for H2O.

Support for wild-card hostnames #634

The server finally supports wild-card hostnames as well, which is essential if you have multiple wild-card certificates to be used.