.internal ドメインを予約する提案仕様

IETFのdnsop WGで .internal ドメインを予約する「The .internal TLD.」という仕様が、GoogleのWarren Kumari氏によって提案されています。

DNSに関しては詳しくないのですが、ざっと読んだので簡単にメモ。

.internal

.internalというドメインを内部的に使用しているという方もおられるでしょう。

.internal TLDは、ICANNの「DNS名前衝突ブロックリスト」に含まれており、gTLDになることはありません。その事に関しては以下のINTERNET Watch様の記事が詳しいです。

萌えドメインなのに……「anime.moe」の登録をICANNが禁じている理由とは -INTERNET Watch Watch

しかし、この.internalはIANA(ポート番号や識別子を管理する組織)には登録されていません。現在ドメイン名で特別に予約されているドメインは、.exampleや.localなどがあります。一覧はIANAのWebページから確認できます。

.internal の予約

すでに.internalは使用されており、root DNSへもクエリが漏れてるのだとは思いますが
DNSプロトコルとして .internalを内部利用のために予約する提案が「The .internal TLD.」です。

この提案では、背景、なぜ他の登録済みドメインを利用しないのか、DNSSEC利用時の取扱、それぞれの.internalの扱いについて書かれています。

利用者/オペレータ/レジストラの.internalの扱いは以下のようになるようです

  • アプリケーション及びソフトウェアの作者は .internal を特別に扱う必要はありません
  • キャッシュDNSは .internal を特別扱いしても良いです。ローカルのゾーン情報を使用すべきですが、権威サーバにフォワードしても良いです。
  • 権威サーバは .internal を特別扱いしてはいけません。ローカルでのみ特別な意味を持ちます。
  • DNSオペレータは、.inteenal へのクエリはグローバルなものでないことに注意し、外部にリークされることに注意してください。
  • DNSレジストリ/レジストラは .internal を登録する要求を許可してはいけません。

すでにdnsop WGメーリングリストですでに議論はあったようですが、ドラフトは出たばっかりですのでまだまだ議論が続くことでしょう。

Nginxのリバースプロキシでバックエンドとhttp2通信する

以前書いたとおり、ApacheではリバースプロキシでバックエンドとHTTP2通信することができます。

asnokaze.hatenablog.com

f:id:ASnoKaze:20170531004524p:plain:w450

Nginxの場合は、開発者のメーリングリストGoogleの人が書いてる「ngx_http_v2_upstream」パッチを利用することでバックエンド(upstream)とHTTP2通信することが出来るようになります。

ビルド

環境はUbuntu16.04

$ hg clone http://hg.nginx.org/nginx/
$ cd ./nginx
$ hg update -r 7039

# 順番にパッチを当ててく
$ patch -p1 < ./1.patch
...

$ ./auto/configure  --with-http_ssl_module --with-http_v2_module
$ make

#今回はインストールしてしまう
$ sudo make install

設定

proxy_http_versionに2.0が指定できるようになります。
proxy_passにhttp://を指定すると、h2cダイレクトでバックエンドと接続しに行きます
(証明書は適当に準備)

#nginx.conf
    proxy_http_version 2.0;

    upstream backend {
        server 127.0.0.1;
    }

    server {
        listen       443 ssl http2;
        server_name  localhost;

        ssl_certificate      /home/yuki/server.crt;
        ssl_certificate_key  /home/yuki/server.key;

        location / {
          proxy_pass http://backend/test;
        }
    }

その他、h2cダイレクトではなくhttpsでプロキシする際に、ALPNを使うように出来るようですがちょっと動作が怪しいようです....

proxy_ssl_alpn on;

動作確認

バックエンドはh2cで接続できるようにしておきます。

#nginx.conf
    server {
        listen       80 http2;
        server_name  localhost;
    }

ブラウザでサーバにアクセスすると、バックエンド(/proxy/)もHTTP/2.0で接続できている事が確認できました

$ tail /var/log/nginx/access.log
127.0.0.1 - - [02/Jul/2017:16:36:40 +0000] "GET /proxy/ HTTP/2.0" 404 571 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
192.168.0.104 - - [02/Jul/2017:16:36:40 +0000] "GET / HTTP/2.0" 404 571 "-" "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"

Webページを丸ごとパッケージングする Web Packagingとは

20180824追記
Loading Signed Exchangesについて記事を書きました
Loading Signed Exchangesの仕様 (WebPackaging) - ASnoKaze blog

20180208追記
Bundled HTTP Exchangesについて記事を書きました
Bundled HTTP Exchanges とは (WebPackagingの議論より) - ASnoKaze blog

20180121追記
署名の仕組みとして Origin-Signed HTTP Exchanges を利用する方向のようです
HTTP/2 クロスオリジン サーバプッシュを可能にする提案仕様 - ASnoKaze blog

20171001追記
IETF99にてユースケースについてまずまとめるべき気というフィードバックが有り、それをうけて「Use Cases and Requirements for Web Packages」が提出されています


Webページを丸ごとパッケージングする、Web Packagingの仕様がIETFで提案されています

オフラインやローカル環境で共有出来るようになっており、主な特徴は

  • 証明書及び署名がつけられるため、そのパッケージの真正性が確認できる
  • HTTPリクエスト/HTTPレスポンスも含まれている(HPACKを利用)
  • サブパッケージが利用でき、複数のオリジンをパッケージング可能
  • データはCBORで表現される (RFC 7049 - Concise Binary Object Representation (CBOR))
  • Index化されており、オフセットを用いて各リソースにランダムアクセス可能

以上の点で、ZIPで固めて保存するのとはまったく違うことがわかるかと思います。

ユースケース

幾つかユースケースがありますが、主なものは以下のとおりです

  • ローカル環境での共有。SDカードでの共有から、Physical Webと言ったその場でのBluetoothを用いた配信など
  • Webのスナップショット保存。そのページをスナップショットとして保存する(署名無し)
  • CDNでの配布。CDNや別の場所から再配布することが可能。この場合は署名をつけての配布が可能となる

提案仕様と経緯

6月30日に、GoogleのJeffrey Yasskin氏より「Web Packaging」という提案がIETFにて出されました。おそらく議論はDispatch WGで行われ、今月実施されるIETF99
https://www.ietf.org/meeting/99/
でもオフラインでの議論があるかもしれません。

もともと、Webページをパッケージングする仕様は、W3Ctag「Packaging on the Web」というものがありましたが、そこから署名などの機能を追加し整理した「Web Packaging」という仕様がW3CのWICGで議論されておりました。

このW3C WICGの仕様は、データフォマットが要でありIETFで標準化していくのが適切ではないかとIETFに持ち込まれた形になります。

フォーマット

webpackageのフォーマットは以下の通りである

webpackage = [
  magic1: h'F0 9F 8C 90 F0 9F 93 A6',  ; 🌐📦 in UTF-8.
  section-offsets: { * (($section-name .within tstr) => offset) },
  sections: ({ * $$section }) .within ({ * $section-name => any }),
  length: uint,                        ; Total number of bytes in the package.
  magic2: h'F0 9F 8C 90 F0 9F 93 A6',  ; 🌐📦 in UTF-8.
]
  • magic: 先頭と最後に挿入されるMagicコード。意味はない
  • section-offsets: 各セクションへのオフセット値が与えられる。必須ではない
  • sections: ここにManifestや実際のコンテンツが格納される(manifest, indexed-content)
  • length: データ長

manifest及び、indexed-contentは以下で説明します。

manifest

sectionsに格納されるmanifestデータ。必須ではない。

日付、オリジン名、証明書、署名が格納される。また、アレば別オリジンのパッケージをサブパッケージとして読み込むことが出来る。

具体的には以下のパラメータです

  • metadata: 日付、及びオリジンが記述される。また、あればサブパッケージの指定
  • resource-hashes: 各リソースのハッシュ値
  • signatures: 署名
  • certificates: 証明書

    "manifest": {
      "manifest": {
        "metadata": {
          "date": 1(1494583200),
          "origin": 32("https://example.com")
        },
        "resource-hashes": {
          "sha384": [
            h'3C3A03F7C3FC99494F6AAA25C3D11DA3C0D7097ABBF5A9476FB64741A769984E8B6801E71BB085E25D7134287B99BAAB',
            ...
          ]
        }
      },
      "signatures": [
        {
          "keyIndex": 0,
          "signature": h'3044022015B1C8D46E4C6588F73D9D894D05377F382C4BC56E7CDE41ACEC1D81BF1EBF7E02204B812DACD001E0FD4AF968CF28EC6152299483D6D14D5DBE23FC1284ABB7A359'
        }
      ],
      "certificates": [
        DER(
          Certificate:
              ...
              Signature Algorithm: ecdsa-with-SHA256
                  Issuer: C=US, O=Honest Achmed's, CN=Honest Achmed's Test Intermediate CA
                      Public Key Algorithm: id-ecPublicKey
                          Public-Key: (256 bit)
                          pub:
                              ...
        ),
        DER(
          Certificate:
              ...
        )
      ]
    },
indexed-content

sectionsに格納される、indexed-content。ここにコンテンツの中身が格納される。
各リソースに対するHTTPリクエスト及びHTTPレスポンスが合わせて格納されており、ヘッダに関してはそれぞれHPACKでエンコードされている。

    "indexed-content": [
      [
        [ hpack({
            :method: GET
            :scheme: https
            :authority: example.com
            :path: /index.html
          }), 1]
        [ hpack({
            :method: GET
            :scheme: https
            :authority: example.com
            :path: /otherPage.html
          }), 121],
        [ hpack({
            :method: GET
            :scheme: https
            :authority: example.com
            :path: /images/world.png
          }), 243]
        ],
      ],
      [
        [ hpack({
            :status: 200
            content-type: text/html
            date: Wed, 15 Nov 2016 06:25:24 GMT
            expires: Thu, 01 Jan 2017 16:00:00 GMT
          }),
          '<body>\n  <a href=\"otherPage.html\">Other page</a>\n</body>\n'
        ]
        [ hpack({
            :status: 200
            content-type: text/html
            date: Wed, 15 Nov 2016 06:25:24 GMT
            expires: Thu, 01 Jan 2017 16:00:00 GMT
          }),
          '<body>\n  Hello World! <img src=\"images/world.png\">\n</body>\n'
        ],
        [ hpack({
            :status: 200
            content-type: image/png
            date: Wed, 15 Nov 2016 06:25:24 GMT
            expires: Thu, 01 Jan 2017 16:00:00 GMT
          }),
          '... binary png image ...'
        ]
      ]
    ]

セキュリティについて

オフラインの利用を想定しているため、証明書の失効確認については難しいところがあります。Webパッケージの利用者は正当性を確認する際は、オンライン時はOCSPを利用して失効確認が可能ですが、オフラインのときはブラウザによって判断されることになるでしょう(1週間だけ有効など)。

そこの部分については今後の議論になるかと思われます。

TLS1.3の0-RTT通信と、HTTP 425 ステータスコードの提案仕様(RFC8470)

20190502 追記
動いた

20180922 追記
RFC8470として標準化されました

無事Too Earlyのステータスコードが 425になりました (URL)

本記事は、draft-00時点の記述の通り、未定を示す4NNのままとしておきます。


2020/01/19追記

#http_tokyo で詳しい説明をしました。あわせてどうぞ

www.slideshare.net



TLS1.3では、0-RTTハンドシェイクの際にearly_dataとしてアプリケーションデータを送信できます。しかし、この0-RTTハンドシェイクで送信するデータには、リプレイ攻撃のリスクがあります。
そのリスクをさけるための機能をHTTPに追加する提案が出ています。

提案仕様は、「Using TLS Early Data in HTTP」で公開されており、著者はMartin Thomson, Mark Nottinghamらである。

この仕様ではHTTPに以下の機能を追加します

背景

現在標準化の大詰めを迎えているTLS1.3の機能の一つに 0-RTT Data というものがります。

これは、一度TLSハンドシェイクを行ったサーバに対して再度ハンドシェイクを行う際は、ClientHelloと共にアプリケーションデータも送信する手順です。通常のフルハンドシェイク手順よりも早くアプリケーションデータを送信し始めることができます。パケットの往復を待たずに送りたいデータを送ることから、0-RTTハンドシェイクとも呼ばれます。

具体的な手順は、TLS1.3の仕様の2.3節で示されています
f:id:ASnoKaze:20170618234412p:plain:w350

この0-RTTハンドシェイクで送信されるアプリケーションデータはもちろん暗号化されていますが、リプレイ攻撃が可能です。0-RTTハンドシェイクのClientHelloのパケットを観測し、再度サーバに送りつけ多重にリクエストを処理させることができます。

そのため、この0-RTTハンドシェイクで送信するアプリケーションデータはべき等なもの、つまり、なんど処理をしても結果が変わらないものに限られるべきです。HTTPで言えばGETメソッドなどがそう言えるでしょう(そうでないものも多いですが)。

4NN (Too Early)と、Early-Dataヘッダ

この 0-RTT Dataのリスクを軽減するために「Using TLS Early Data in HTTP」という提案がでています。この仕様ではHTTPに以下の機能を追加します

4NN (Too Early)

4NN (Too Early)は、サーバがリプレイ攻撃の危険性がある0-RTTハンドシェイクのearly_dataデータを処理したくないことをクライアントに通知するステータスコードです。

このステータスコードを受け取ったクライアント(User-Agentやプロキシ)は自動でリクエストを再試行すべきではありません、全く新しいコネクションとしてサーバに接続する必要があります。

418 VS その他

具体的なステータス番号については、Author間で議論がありました。まだIANAに登録されていない418を使うという提案がありましたが、Hyper Text Coffee Pot Control Protocolで「418 I'm a teapot」として使用されています。

「418 I'm a teapot」は https://www.google.com/teapot 実際にデプロイされておりますが、HTCPCPはジョークRFCであり、HTTPとは別のプロトコルであるためステタース番号はかぶっても良いという意見です。

また、ジョークRFCによって貴重な番号が消費される事についても意見がついているようです。

しかし最終的には関係者と議論して決めるようです。

Early-Dataヘッダ

TLSを終端するサーバとアプリケーションサーバが別れている構成は一般的です。もちろんCDNクラウドサービスのTLS終端サービスはそのHTTPリクエストがリプレイ攻撃されても問題ないか判断はできません。

そのため、TLS終端したサーバはそれが元々0-RTTハンドシェイクで送られてきたデータなのか区別できるようにする必要があります。

仕様では、HTTPリクエストが0-RTTearly_dataで送信されていることを示すEarly-Dataヘッダが定義されています。0もしくは1であり、1がearly_dataで送信されていることを示します。

TLSを終端しているサーバがEarly-Dataヘッダを付与します。"Early-Data"ヘッダーフィールドは、ユーザーエージェント(つまり最初のリクエストを送った者)が使用するためのものではありません。

f:id:ASnoKaze:20170619000602p:plain

この時、4NNを受け取った場合の終端サーバはクライアントにそれを転送しなければなりません。

またEarly-Dataヘッダは、4NNステータスコードを理解できることも示しています。

QUIC標準化現状確認メモ

2018/2
asnokaze.hatenablog.com


Googleの考案したQUICは現在IETFで標準化が進められており、多くの人々によって議論されております。QUICの中身よりも現在の状況について、自分用に整理する。

Issueが追えてないので残念感ある。

概要

UDP上で信頼性のある暗号化されたHTTP/2通信を行うQUICは、もともとはGoogleが考案・実装・実証をすすめられていた。

IETFの会合で数度のBoF(WG設立前の議論)の開催へて、2016年にQUIC WGが出来QUICの標準化を進めることが決定した。

QUIC WGのゴールはCharterにかかれている通り、大まかに以下のとおりである

  • アプリケーションのために、コネクション及びトランスポートの遅延を最小化すること
  • head-of-lineブロッキングの無い多重化を提供すること
  • エンドポイントの変更のみでデプロイ可能とすること
  • マルチパスとFEC(forward error correction)を拡張機能として有効にする
  • TLS1.3を使用した常時暗号を提供すること

また、マイルストーンとしては主要な4つの仕様は 2018年ごろにほぼほぼ標準としては固まった状態となり、IESGに提出される予定になっている

  • Mar 2018 Core Protocol document to IESG
  • Mar 2018 Loss detection and Congestion Control document to IESG
  • Mar 2018 TLS 1.3 Mapping document to IESG
  • Nov 2018 HTTP/2 mapping document to IESG
  • Nov 2018 QUIC Applicability and Manageability Statement to IESG
  • May 2019 Multipath extension document to IESG

7月に行われるIETF99において、以下にあげる仕様(draft04)で相互接続通信ハッカソンが行われる予定になっている。しかし、フル実装ではなく1RTTハンドシェイクにフォーカスしたものである (Home · quicwg/base-drafts Wiki · GitHub)

仕様・ドキュメント

主要仕様

現在の仕様、主要な4つに関してはWGドラフトとなりすでに改版が進んでいる。直近で6/13にdraft-04となっている

Ops

Opsに関して、すでにAdopetされている個人ドラフト

個人ドラフト

その他個人ドラフト

ドキュメント

その他仕様ではないが、参照されるもの

Google QUIC

その他Google QUIC側の資料は「Chromiumのプロジェクトページ」から辿れる。すべての資料ではないが、YoutubeにおいてFECを有効にした際の評価についての資料などもある。

議論/発表資料

直近の議論と、発表資料についてまとめる

IETF QUIC Working Group Interim Meeting

6/6~8にかけて行われた、IETFの本会合との間に設けられているQUIC WGの中間会議

議事録」の通りとなるが、Implementation Draftの議論、幾つかのIssueについての熱い議論及び、下記の発表があった

過去のIETF/Interimの議事録・発表資料はGithubで公開されている
https://github.com/quicwg/wg-materials

The HTTP Workshop

6/12~13にかけて行われた、標準化の場ではないが、仕様の著者、ブラウザベンダ、ミドルウェア実装者、CDNや大手サービスがHTTPについて議論するWorkshopであり、QUICに関する発表もあった。

Next IETF

次のIETFは7/16~21であり、もちろんQUIC WGのセッションもある。スケジュールはすでに公開されており、QUICのセッションは20, 21である。

余談だが、リモートでの参加は誰でも無料で出来る、深夜帯ではあるが興味ある方は下記記事を参照頂ければと思う
qiita.com

CookieのNoHttp属性の提案仕様

以前、「Cookieの仕様改定版、RFC6265bisの議論」でも書いたとおり、IETFのHTTPBis WGではCookieのセキュリティ向上に向けて改訂作業が行われています。

Cookieの改訂版のAuthorでもあるGoogleのMike West氏が、それとは別に新しくCookieに「NoHttp」属性を追加する新しい「Non-HTTP Cookies」という提案仕様を書いています。

この属性の付いたCookieは、サーバには送信されなくなります。

Non-HTTP Cookies

背景

良くも悪くもCookieはSame-Originを超えて共有できます。analyticsのサービスなどは、document.cookieを通して他のページとユーザの状態を共有するものがあります。しかしこの場合は、document.cookieでアクセス出来れば良いようで、HTTPリクエスト送信時にCookieヘッダに付与する必要ないケースが有るようです。(Mike West氏のツイート)


つまり、無駄にCookieを送信していることになり、通信量的にもセキュリティ的にも余計な事をしていることになります。

そこで、それを抑制するNoHttp属性が出てきます

NoHttp属性

NonHttp属性の付いたクッキーはサーバには送信されないようになります。

例えば以下のように設定します

document.cookie = "name=value; Secure; NonHttp";

HTTPヘッダでも同様に設定できます

Set-Cookie: name=value; Secure; NonHttp

但し、もちろん対応していないクライアントはこのフラグを無視するためHTTPリクエストの際に付与されても良いようにしておく必要はあります。

その他

名称については、NoHttp、DOMOnly、DocumentCookieOnlyなどの変更の可能性があるようです。

また、著者が「Cookieは "HTTP State Management" 機能ですが、そこからHTTPを除くユースケースというのは奇妙だが、インターネットは奇妙な場所である」と書かれているのも、また印象的でした。

署名式 SRI(Subresource Integrity)の議論

W3CのWeb Application Securityワーキンググループで、署名式 SRIの議論が出ていたので簡単に書く

背景

セキュリティ向上の目的で、Webページ上で読み込まれるリソース(JavaScript等)を制限する方法に、CSP(Content Security Policy)やSRI(Subresource Integrity)と言った技術がある。

CSP

CSPを利用することで、読み込むJavaScriptを信頼できるURLのみに制限出来る。

CSPのscript-srcディレクティブで、以下のように制限できる。

script-src https://example.com/script/trusted.js


しかし、CSP Is Dead, Long Live CSP! On the Insecurity of Whitelists and the Future of Content Security Policyで述べられているように、URLベースの制限は非常に細かく記述する必要があり、大規模なサービスでちゃんと運用することは難しい面があるようです。

SRI

SRIを利用することで、リソースが本当に意図したものである場合のみ読むこむように出来ます。

scriptタグのintegirty属性にコンテンツのハッシュ値を付与することで、リソースの正当性が評価されます。これは、CDNなどを利用してる時に、CDNによる悪意ある改ざんから防ぐことが出来ます。

<script src="https://example.com/example-framework.js"
        integrity="sha384-Li9vy3DqF8tnTXuiaAJuML3ky+er10rcgNR/VqsVpcw+ThHmYcwiB1pbOxEbzJr7"
        crossorigin="anonymous"></script>

しかし、SRIはリソースの更新の順番に課題があり、リソース自体の更新とscriptタグ側のintegrity値の更新を行われなければなりません。

署名式 SRI

W3CのWeb Application Securityワーキンググループのメーリングリストで、GoogleのMike Westより「Proposal: Signatures in SRI.」として投げかけられました。

まだ、議論の段階だが概要についても、W3Cのリポジトリで公開されている。

Ed25519公開鍵で署名し、リソースの正当性を担保する。scriptタグ側に公開鍵を、HTTPレスポンスのIntegrityヘッダに署名値が含まれる形である。

javascriptタグ

<script src="https://my.cdn.com/whatever.js" integrity="ed25519-[base64-encoded public key]">

HTTPレスポンス

HTTP/1.1 200 OK
Accept-Ranges: none
Vary: Accept-Encoding
Content-Type: text/javascript; charset=UTF-8
Access-Control-Allow-Origin: *
...
Integrity: ed25519-[base64-encoded result of Ed25519(`console.log("Hello, world!");`)]
 
console.log("Hello, world!");

この方式であればCDNを利用していても、与えられた公開鍵で署名値を確認することで、意図してないリソースを読み込む(実行する)事は防がれる。また、javascriptタグ側の変更は不要である点もメリットとしてあり、これでSRIにあった更新順序の問題は解決される。


実際に需要があるのか?古いバージョンのファイルを提供する攻撃が可能か?鍵管理が困難ではないのか?PKIやX.509を利用したほうが良いのではないか?といった疑問については、上記でも上げた概要に書かれている。