Upgrade to Pro — share decks privately, control downloads, hide ads and more …

2019-02 HTTP_DNS

A97eee01397705443a72a48ce29d3e19?s=47 Cybozu
May 27, 2019

2019-02 HTTP_DNS

A97eee01397705443a72a48ce29d3e19?s=128

Cybozu

May 27, 2019
Tweet

Transcript

  1. HTTP と DNS サイボウズ株式会社

  2. DNS Domain Name System

  3. 名前って何? ▌hoge.cybozu.com は人間に読みやすい・覚えやすい名前 ▌実際使われているのは IPアドレス ▌じゃあ hoge.cybozu.com の IPアドレスは?

  4. 名前解決 ▌hoge.cybozu.com = 103.79.14.41, 103.79.14.42 ▌ドメイン名を IPアドレスに紐づける

  5. 誰に聞けば良い? ▌dig コマンドを打ってみましょう ◼ 無かった場合: sudo apt install dnsutils ▌$>

    dig +noall +stats +answer hoge.cybozu.com bozuman.cybozu.com. 2795 IN A 103.79.14.41 bozuman.cybozu.com. 2795 IN A 103.79.14.42 ;; Query time: 0 msec ;; SERVER: 10.224.136.183#53(10.224.136.183) ;; WHEN: Wed May 15 16:13:32 JST 2019 ;; MSG SIZE rcvd: 79 ▌$> dig hoge.cybozu.com @1.1.1.1
  6. Recursive DNS Resolver ▌10.224.136.183 は何でも知っている? ▌hoge の IPアドレスが変わったらどうなる? ▌7億人が同時に名前解決したらどうなる? ▌そもそも

    10.224.136.183 は社内の IP
  7. 名前解決の流れ https://www.cloudflare.com/learning/dns/what-is-dns/ hoge.cybozu.com はど こ? 知らん。「.」に聞いてみる 俺も知らんし、断言する権限がない。「.com」なら知ってる hoge.cybozu.com はどこ? 知らん、断言する権限ない。「cybozu.com」なら知ってるはず

    hoge.cybozu.com はどこ? 103.79.14.41, 103.79.14.42 103.79.14.41, 103.79.14.42 だって こんちゃっす dns-1.cybozu.com
  8. Root Servers https://www.iana.org/domains/root/servers

  9. 実際に見てみましょう ▌$> dig +trace hoge.cybozu.com ▌$> dig +trace hoge.cybozu.cn ▌$>

    dig +trace hogehagehige.com
  10. 毎回やる? https://www.cloudflare.com/learning/dns/what-is-dns/ hoge.cybozu.com はど こ? こんちゃっす 覚えてる! 103.79.14.41, 103.79.14.42

  11. DNSレコードの種類 ▌SOA ▌NS ▌A ▌AAAA ▌CNAME ▌MX ▌TXT ▌PTR ▌…

  12. SOA ▌ Start of Authority ▌ DNS Zone の権威情報 ▌

    $> dig SOA +noall +multiline +answer cybozu.com cybozu.com. 51 IN SOA dns-1.cybozu.com. root.io.cybozu.co.jp. ( 2019050500 ; serial 3600 ; refresh (1 hour) 900 ; retry (15 minutes) 604800 ; expire (1 week) 60 ; minimum (1 minute) )
  13. NS ▌Name Server ▌対象ドメインの権威 DNSサーバー(達) ▌$> dig NS +noall +answer

    cybozu.com cybozu.com. 2819 IN NS dns-1.cybozu-bk.com. cybozu.com. 2819 IN NS dns-1.cybozu.com. cybozu.com. 2819 IN NS dns-2.cybozu.com. cybozu.com. 2819 IN NS dns-2.cybozu-bk.com. cybozu.com. 2819 IN NS dns-3.cybozu.com. cybozu.com. 2819 IN NS dns-4.cybozu.com.
  14. A ▌Address (IPv4) ▌$> dig A +noall +answer cybozu.com

  15. AAAA ▌IPv6アドレス(IPv4の4倍のbit数) ▌$> dig AAAA +noall +answer cybozu.com 無い ▌$>

    dig AAAA +noall +answer google.com google.com. 299 IN AAAA 2404:6800:4004:80a::200e
  16. CNAME ▌Canonical Name ▌ドメインのエイリアス ▌DNS レベルのリダイレクト ▌$> dig CNAME +noall

    +answer developers.cybozu.com developers.cybozu.com. 3593 IN CNAME d2p8ofl6yvcluu.cloudfront.net.
  17. MX ▌Mail eXchanger ▌メールサーバー ▌複数ある場合優先度も指定できる ▌$> dig MX +noall +answer

    cybozu.com
  18. TXT ▌Text: 何でもあり ▌定義されている特別な TXTレコードがある ◼ DMARC, DKIM, SPFなど ▌その他クラウドサービスを使う時のドメイン所有者確認など

    ▌$> dig TXT +short cybozu.com "v=spf1 +ip4:103.79.12.128/26 +ip4:103.79.14.16 +ip4:103.79.14.17 include:spf.protection.outlook.com include:fc5038.cuenote.jp -all“ ▌$> dig TXT +short matsuri.dev
  19. PTR ▌Pointer ▌逆名前解決 ◼ IPアドレスからドメイン名を問い合わせる ▌$> dig +noall +answer -x

    103.79.14.84 84.14.79.103.in-addr.arpa. 86394 IN PTR dns-3.cybozu.com. ▌$> dig +short dns-3.cybozu.com 103.79.14.84
  20. Zone ファイル $ORIGIN kaiun.lan. $TTL 60; 1 min @ IN

    SOA dns contact.kaiun.lan. ( 2019051701; serial 3600 ; refresh (1h) 900 ; retry (15m) 3600 ; expire (1h) 60 ; min TTL (1m) ) Zoneファイルの始まりを記す。 末尾の「.」も必要! Time To Live: キャシュされたレコードの 有効時間 $ORIGIN の略 プライマリーDNSサーバーと連絡 先のメールアドレス Zoneのバージョン番号 他のネームサーバーへのタイミン グ指示
  21. Zone ファイル <$ORIGIN下の名前> IN <レコードタイプ> <レコード値> 例)bozuman IN A 103.79.14.41

  22. 演習: DNSサーバーを触りましょう ▌Docker をインストール ◼ https://docs.docker.com/install/linux/docker- ce/ubuntu/#install-docker-ce ▌docker-compose をインストール ◼

    https://docs.docker.com/compose/install/ ▌演習用のレポジトリをクローン ◼ https://github.dev.cybozu.co.jp/tu-antoine/kaiun-dmz
  23. 構成 ▌dns: kaiun.lan の権威 DNS (NSD) ▌cache: recursive DNS resolver/cache

    (Unbound) ◼ kaiun.lan に関しては dns である 172.30.0.3 に問い合わせる ▌client: 外から見れないので client コンテナーに入って様々なコマンドを打つ ▌おまけ: ◼ l7lb: 負荷分散、TLS termination (nginx) ◼ 外から見えるのは l7lb。裏で実際のウエブサーバーにリクエストを割り当てる ◼ web: ウエブサーバー
  24. 演習: DNSサーバーを触りましょう ▌$> docker-compose -p kaiun up --build --scale ap=3

    ▌$> docker exec -it kaiun_client_1 bash ▌$> dig cybozu.com ▌$> dig kaiun.lan ▌$> curl kaiun.lan
  25. 演習: DNSサーバーを触りましょう ▌zoneファイルに DNSレコードを追加 (dnsダイレクトリー下) ◼ kaiun.lan -> 172.30.0.6 にしましょう

    ◼ rDNS もやりましょう ◼ ついでに www の CNAME も追加しよう (kaiun.lan のアリアス)
  26. 演習: DNSサーバーを触りましょう ▌$> docker-compose -p kaiun up --build --scale ap=3

    ▌$> docker exec -it kaiun_client_1 bash ▌$> dig kaiun.lan ▌$> curl –v kaiun.lan おまけ:L7LB も見ましょう ◼ $> seq 5 | xargs -n1 -P5 bash -c 'curl kaiun.lan'
  27. HTTP Hypertext Transfer Protocol

  28. Hypertext Transfer Protocol ▌hyper-text:テキストを超える ▌複数の文書をリンクにより関連付ける仕組み →HTML:Hypertext Markup Language ▌HTTP:hypertextを送受信する手順 ▌今では,hypertextに限らずあらゆるデータの送受信に使われる

    →演習:ファイルの受信
  29. 演習1:HTTPによるファイル受信 ターミナル1 テスト用HTTPサーバを立てる ターミナル2 HTTPサーバにアクセスし,hello.txtを受信 $ mkdir httproot $ cd

    httproot $ echo 'hello world' > hello.txt $ python3 -m http.server 8080 $ telnet localhost 8080 Trying 127.0.0.1... … GET /hello.txt HTTP/1.1 Host: 127.0.0.1:8080 HTTP/1.0 200 OK … hello world Connection closed by foreign host. ファイルの中身が受信できた!
  30. HTTPリクエスト(要求) ▌HTTPリクエスト:クライアントからHTTPサーバへの要求 GET /hello.txt HTTP/1.1 Host: 127.0.0.1:8080 User-Agent: curl/7.47.0 Accept:

    */*
  31. HTTPレスポンス(応答) ▌HTTPレスポンス:HTTPサーバからの応答 HTTP/1.0 200 OK Server: SimpleHTTP/0.6 Python/3.5.2 Date: Wed,

    15 May 2019 09:11:53 GMT Content-type: text/plain Content-Length: 12 Last-Modified: Wed, 15 May 2019 09:09:07 GMT hello world
  32. HTTP 1.Xのフォーマット 32 スタートライン ヘッダ ボディ (ないこともある) リクエスト レスポンス

  33. HTTPリクエスト

  34. Method: 要求の種類 34 ◼ GET ◼ POST ◼ DELETE ◼

    PUT ◼ CONNECT … ▌このリクエストがどのようなものか推測する手がかり (例:安全か、べき等か、キャッシュ可能か) Request line
  35. Request target: 要求の対象 35 ▌Webサーバが持つどのサービスに対 するリクエストか ▌サービス ◼ 単なるファイル ◼

    動的なファイル ◼ DBへの書き込み ◼ etc.
  36. Version:HTTPのバージョン 36 ▌HTTP/X.Y というフォーマット 「メジャーバージョンが同じなら 後方互換性がある」…というタテマエ ※ HTTP/2はそもそもバイナリプロトコル メジャーバー ジョン

    マイナー バージョン
  37. Hostヘッダ: サーバの名前 37 ▌どのサーバに対するリクエストか ← 同じIPアドレス上に複数のHTTP サーバがいることがある (Virtual Host)

  38. その他のヘッダ 38 ◼ Controls ◼ Conditionals ◼ Content Negotiation ◼

    Authentication Credentials ◼ Request Context ◼ 独自拡張
  39. Message Body: データ部分 39 ▌ヘッダ部分と空行(CRLF)で隔てら れた部分 ▌メソッドによってあったりなかったり ◼ 典型的には… ◼

    GETはボディを持たない ◼ PUT/POSTはボディを持つ
  40. HTTPレスポンス

  41. Status Code: リクエストの処理結果 41 ◼ 1XX: コネクションの情報 ◼ 2XX: 成功

    ◼ 3XX: リダイレクト ◼ 4XX: クライアント側のエラー ◼ 5XX: サーバ側のエラー ▌クライアントはこれに応じてリトライしたりエ ラー処理をしたりする
  42. Status Codeに対するクライアントの反応例 ▌302 Found → Locationヘッダに指定されたURLを見に行く ▌304 Not Modified →

    キャッシュされている結果を使う ▌500 Internal Server Error → 500エラーを画面に出す ▌401 Unauthorized → 認証パスワードを再度求める 42
  43. Status Codeの罠 ▌ステータスコードを信用しすぎてはいけない ◼ サーバーが実装を間違えている ◼ ステータスコードは200でもボディにエラーメッセージが入る ◼ 独自のステータスコードを返す 43

    HTTP/1.0 200 OK {"status": "error"} 200 OKなのにエラーを返す例
  44. Reason Phrase 44 ▌人間が読むための文字列 ▌プログラムからは利用しない

  45. 動的コンテンツ ▌HTTPサーバは,受け取ったHTTPリクエストに対し,反応する ▌HTTPレスポンスをどうやって生成するか ◼ ファイルをそのまま送る ◼ 内容を動的に生成して送る ▌Webアプリ(kintoneやGaroonなど)がやっているのはこれ!

  46. 演習2:動的コンテンツを送信するHTTPサーバを作る $ curl http://localhost:8080/add/2/3 5 $ curl http://localhost:8080/add/-4/3 -1 ▌仕様

    ◼ GET /add/X/Y とすると X+Y の結果を返す ◼ X,Yはともに整数(値の範囲は自由に仮定していいです) ▌ひな形 https://gist.github.com/uchan-nos/18fdd22cdf9c358109dd938c98ca79cd メモ: 演習2は20分想定. 時間が足りなそうなら 演習2はスキップする.
  47. 演習2のプログラム起動方法 (ほぼ答え)四則演算に対応した版 https://gist.github.com/uchan-nos/9d05dbaa7b190f890ea962cf4e81456a $ chmod +x simple_add_server.py $ ./simple_add_server.py $

    curl http://localhost:8080/add/2/3 5 $ ターミナル1 HTTPサーバを立てる ターミナル2 HTTPサーバにアクセスする
  48. 演習2のヒント ▌(ほぼ答え)四則演算に対応した版 https://gist.github.com/uchan-nos/9d05dbaa7b190f890ea962cf4e81456a # X+Y result = arguments[0] + arguments[1]

    # レスポンスボディの作成 self.wfile.write(バイト列) # 数値→バイト列の変換 '{}'.format(数値).encode('utf-8')
  49. HTTPS HTTP Secure

  50. HTTP Secure ▌HTTPは平文プロトコル = 攻撃者が簡単に情報を盗める ▌HTTPS:HTTPをTLSの上に構築 ◼ TLS:Transport Layer Security

    ▌暗号化されるので盗聴されても解読が難しい HTTP TCP/UDP IP Ethernet HTTP TCP/UDP IP Ethernet TLS アプリケーション/プレゼンテーション層 セッション層 トランスポート層 ネットワーク層 データリンク/物理層
  51. TLSで守りたいもの・守り方 ▌通信相手が本物であること → デジタル署名 ◼ (クライアント視点で)本物のサーバか? ◼ (サーバ視点で)本物のクライアントか? ▌通信内容が盗聴されないこと →

    対称暗号 ◼ クレジットカード番号などが漏洩しないように ▌通信内容が改竄されないこと → メッセージ認証コード ◼ 説明は省略
  52. デジタル署名:通信相手が本物であること 認証局 サーバB クライアントA 公開鍵B 秘密鍵B' 公開鍵T 秘密鍵T' 公開鍵B Bのハッシュ

    一方向ハッシュ Bの署名 暗号化 証明書B Bの署名 証明書B Bの署名 Bのハッシュ 復号 比較 公開鍵B 一方向ハッシュ Bのハッシュ
  53. 対称暗号:通信内容が盗聴されないこと ▌共通鍵暗号とも呼ぶ ▌公開鍵暗号またはDiffie-Hellman鍵交換にて クライアントとサーバが鍵を共有する ▌公開鍵暗号より対称暗号の方が(とても)速い 鍵K 鍵K サーバB クライアントA msg

    暗号化 復号 msg
  54. TLSハンドシェイク ▌TLS通信をするには,クライアントとサーバ間で合意が必要 ◼ 証明書のやり取り ◼ 共通鍵の生成と交換 ▌開発環境のドメインにアクセスしてハンドシェイクの様子を見てみよう $ curl -v

    https://foo.cybozu-dev.com/
  55. $ curl -v https://foo.cybozu-dev.com/ * Trying 192.0.2.100... * TCP_NODELAY set

    * Connected to foo.cybozu-dev.com (192.0.2.100) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /etc/ssl/certs/ca-certificates.crt CApath: /etc/ssl/certs * TLSv1.2 (OUT), TLS handshake, Client hello (1): * TLSv1.2 (IN), TLS handshake, Server hello (2): * TLSv1.2 (IN), TLS handshake, Certificate (11): * TLSv1.2 (IN), TLS handshake, Server key exchange (12): * TLSv1.2 (IN), TLS handshake, Server finished (14): * TLSv1.2 (OUT), TLS handshake, Client key exchange (16): * TLSv1.2 (OUT), TLS change cipher, Client hello (1): * TLSv1.2 (OUT), TLS handshake, Finished (20): * TLSv1.2 (IN), TLS handshake, Finished (20): * SSL connection using TLSv1.2 / ECDHE-RSA-AES128-GCM-SHA256 (続く)… foo.cybozu-dev.com にアクセスするときの TLSハンドシェイクの様子
  56. … * ALPN, server accepted to use http/1.1 * Server

    certificate: * subject: OU=Domain Control Validated; CN=*.cybozu-dev.com * start date: Aug 29 10:54:08 2018 GMT * expire date: Oct 29 01:13:38 2020 GMT * subjectAltName: host "foo.cybozu-dev.com" matched cert's "*.cybozu-dev.com" * issuer: … CN=Starfield Secure Certificate Authority - G2 * SSL certificate verify ok. > GET / HTTP/1.1 > Host: foo.cybozu-dev.com > User-Agent: curl/7.58.0 > Accept: */* > < HTTP/1.1 200 OK … ここからHTTPが始まる
  57. RFC 57

  58. RFCとは ▌Request for Comments(コメント求む)の略 ▌RFCの目的は色々 ◼ インターネット標準を定める ◼ 情報提供 ◼

    ジョーク … ▌RFC 2616 https://tools.ietf.org/html/rfc2616 Hypertext Transfer Protocol -- HTTP/1.1 58
  59. なぜ標準が必要か ▌HTTPの場合:様々なサーバ、様々なクライアント… 59 nginx Apache IIS 自作サーバ Chrome Firefox IE

    Edge curl wget 独自クライアント
  60. なぜ標準が必要か ▌もしも標準がないと… ◼ メッセージがうまく処理できず、サービスが動かない ◼ 色んな独自仕様に対応しないといけなくなってとても大変 ◼ セキュリティ上の抜け穴が発生する ※Googleのようにサーバもクライアントも自社開発する場合,自社製 品に独自の仕様を突っ込んで普及させ,後からインターネット標準に仕

    立て上げる、ということもできる。SPDY,HTTP/2,QUIC 60
  61. ググった記事よりRFC ▌みんな、自分が思うように相手が動いてほしいと思っている → 「なぜうちに合わせて◦◦という動作じゃないの?」 → 「そっちこそなぜうちに合わせて××じゃないんだ!?」 → もめる ▌…ということになるので、相手に合わせるのではなくRFCに合わせましょう ▌「正しい挙動」が知りたいときは、ググって出てくるページではなくRFCを読

    む 61
  62. RFCを読もう ▌RFCの中にはユーモアにあふれるものもある ◼ RFC1149 https://tools.ietf.org/html/rfc1149 ◼ 「鳥類キャリアによるIPデータグラムの伝送に関する標準」 ◼ 1990年4月1日に発表 ▌(もちろん,ほとんどのRFCは真面目)

    ▌明日のRFC精読会をお楽しみに!