class: title, smokescreen, shelf, no-footer # <small>情報技術応用特論 第01回<br>TCP/IP(1)</small> <div class=footnote> <small><small> Copyright (C) Ken'ichi Fukamachi <fukachan@fml.org>, 2021-2025. CC BY-NC-SA 4.0 </small></small> </div> --- class: compact # 概要 <div class=footnote> <small><small> (脚注1) <B>学部の「コンピュータネットワーク」は履修済</B>の想定です。 ところどころ復習もありますが、 基本用語は知っているはずなので、 省略か(スライドにあっても)軽くふれるだけで飛ばしていきます <br> (脚注2) われわれプロにとってのインターネットは<B>データ(パケット)転送システム</B>のことです。 素人さんには 「インターネットってブラウザでいろいろできることじゃないの?」 というイメージがあると思いますが、 それは(データ転送後の)ある一つのアプリケーションの動作の話にすぎません。 ブラウザというアプリが圧倒的に利用頻度が高いので、 そういう偏見が生まれるのでしょうけどもね <br> (脚注3) 多くのものはアプケーション層とトランスポート層の間に暗号化レイヤーをはさむ形なので、 アプリケーションプロトコル単体では暗号云々という話は無関係です <br> (脚注4) [歴史] TCP/IPの設計は1970年代に始まっていますが、OSIモデルは1980年代です。つまりOSIが後 </small></small> </div> <small> - アプリケーションプロトコルに慣れましょう。可読性,非暗号化の簡単な例のみ - ウエブ: HTTP - メールの受信: POP3 - メールの送信,転送: SMTP - だいたい、なんでも「<B>サーバクライアントモデル</B>」(<- 復習, 分かっている想定) - アプリケーション層 ... 俗にレイヤー7とも呼ぶが、正確にはOSIモデルのL7と同等ではない - 実際には裏でDNSも動いていますが、簡単化のため最初はDNS抜きで説明し、後にDNSあり版 </small> --- class: title, smokescreen, shelf, no-footer # WWW<br>- アプリケーション層の例(1) - <div class=footnote> <small><small> </small></small> </div> <div class=digest-begin-01></div> --- class: col-2,compact # WWW (ワールドワイドウエブ)の全体像 <div class=footnote> <small><small> (脚注1) コンテンツの代表例はHTML形式のファイルですが、画像でも動画でも何でもOK。 技術的には、すべて<B>バイトストリーム</B> <br> (脚注2) 【重要】データの種類や表現などはTCP/IPと無関係です! TCP/IPの仕事はブラウザにデータを確実に届けること <br> (脚注3) 組織と規格文書: W3C (World Wide Web Consorcium)からの勧告。 IETFでRFCになるものもある。 <B>だれでも参加可能</B> </small></small> </div> <small> - 転送プロトコルは<B>HTTP</B> - 特にHTTP/1.0はシンプルな<B>ステートレス</B>プロトコルの良い例(後述) - データ(転送内容=コンテンツ)は何でも良い - ブラウザでは URI を指定する - かつては URL と呼んでいたため、歴史的に URL と呼ぶ人も多い <wbr> - 用語: URI が URL と URN の上位概念 - 情報空間で一位に特定できるIDがURI - URL (Uniform Resource Locator) ... (サイバースペース上の)場所に相当するもの - 例: https://サーバ名/パス(OS上の場所)/ - URN ... 場所という概念が無いもの - 例: 電話番号, 本のISBN番号 ``` [URIの例] https://portal.mc.chitose.ac.jp/portal2/ tel:0123-27-6097 isbn:978-0321336316 ``` </small> --- class: compact,img-right # サーバクライアントモデル (復習) <div class=footnote> <small><small> (脚注) サーバクライアントモデルが抽象化しているのは図の(1)(3)にあたります。 (2)(4)は技術の詳細/各論で、ここは様々です </small></small> </div>  <small> - (クライアントが)<b>依頼</b>し、(サーバが)<b>処理結果を返す</b>。 <b>世の中ほぼ何でもコレで説明可</b> - 例:レストラン、コンビニ、買い物、ポータル、メール、スマートフォンの動作全般 - 例:WWW(右図) <small> - (1) URL( http://b2902900.cloud.fml.org/ )をブラウザでクリックすると - (2) 【WWWサーバの内側の動作】 URL右端の/を/index.htmlと解釈しindex.htmlの中身を返す - (3) WWWサーバはブラウザにコンテンツ(index.html)を送り返します - (4) ブラウザは受け取ったコンテンツを解釈して表示します(レンダリング) </small> </small> --- class: col-2,compact # WWW サーバの動作 (HTTP/1.0 の動作説明) <div class=footnote> <small><small> (脚注1) この演習「手動HTTP」は3年生のときにやりましたね? このあと動画だけ見ます。 ?の人は各自で復習してください <br> (脚注2) listen(2)の2は引数ではなく、Unix マニュアルの第2章「システムコール」に書いてあるから読めという意味です </small></small> </div> <small> - WWW サーバはリクエストを待つ <small> - ポート番号は 80, プロトコルはTCP - 専門用語では「80/tcp で listen(2)」 </small> - クライアント(WWWブラウザ)〜サーバ間にTCPの通信回路を確立(詳細は後日) - <B>クライアントからサーバに「このURIのデータをください」とリクエスト(ここからがHTTP)</B> <small> - サーバクライアントモデル - サーバ = WWWサーバ - クライアント = WWWブラウザ </small> <wbr> - サーバからクライアントに返答 <small> - 「HTTP ヘッダ + データ本体」を返す - **ヘッダ**には制御情報が書かれます - ヘッダとデータ本体の区切りとして空行を1行挿入します (これはメールと同じRFC822準拠フォーマット) </small> <!-- HTTP の図 -->  </small> --- class: img-right,compact # WWW サーバの動作 (サーバの内側をもうすこし詳細に)  <small> - WWW サーバは要求を待っている - (1) クライアントからサーバに接続し「このURIをください」と要求 - `GET /index.html HTTP/1.0`は「/index.htmlをください」という要求で、 HTTP/1.0はプロトコル番号の指定 - (2) WWWサーバ内の動作 - URIから対象のコンテンツが/index.htmlであることを割り出す - サーバのコンテンツ領域を検索しindex.htmlファイルを探しだす - ファイルからデータを読み込む - (3) サーバからクライアントに返答 - HTTP ヘッダ + データ本体(index.html) </small> <div class=digest-end-01></div> --- class: col-2,compact # 【参考】 デモおよび演習で使うコマンドについて <div class=footnote> <small><small> (脚注1) 「厳選Unixコマンド 第2版」のtelnet節を参照してください。 -> <A HREF="https://distribution.techbooks.fml.org/"> https://distribution.techbooks.fml.org/ </A> <br> (脚注2) AWSでは Macのひとはtelnetのかわりにncコマンドで試してください、例: nc localhost 80 </small></small> </div> <small> ``` telnet ホスト telnet ホスト ポート番号 ``` - telnetを使い手動でプロトコルを再現できます、デバッグの基本です - telnet というコマンドは本来リモートログインするためのコマンドですが、 オプションで任意のポート番号を引数に取れます - 任意のポート番号へアクセスし手動でプロトコルを人間が再現できます - ホスト名のlocalhostはホスト自身を意味しています(詳細は後日) <wbr> - ただし、このようなことが出来るのは、 歴史のあるTCPアプリケーションの一部に限られます - 1970〜1980年代からある代表的なアプリケーション群で、 このような人間デバッグ操作が可能です - 1ビットで十分なのに、 わざわざ可読性のあるテキストで命令をやりとりするのはデータ量の無駄です。 デバッグ要素が強いといえます </small> <div class=digest-begin-02></div> --- class: compact,center # 【復習】HTTP/1.0のデモ <iframe width="679" height="394" src="https://www.youtube.com/embed/hq-CTEZK1-k?rel=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> 埋め込みが動作しない方は[こちら](https://www.youtube.com/embed/hq-CTEZK1-k?rel=0) --- class: col-2,compact # ステートレスプロトコル, ステートフルプロトコル <div class=footnote> <small><small> </small></small> </div> <small> - <B>stateless</B> protocol (例: HTTP 1.0) - サーバに要求、データを受信 - 一回ずつ終了、つまり「状態」がない(ステートレス) - HTTP/1.0ではブラウザで表示する部品の数だけ取りにいく - 右図の例: index.html 背景画像 ... - (もちろん、あれば広告なども) - <B>statefull</B> protocol (例: POP, SMTP) - 現在の状態を追跡、状態によって挙動も変わりうる。 メールの受信を例にとると、認証前後で挙動が異なる (次節以降を参照) </small>  <div class=digest-end-02></div> --- name: www-src-examples class: title, smokescreen, shelf, no-footer # <small>【参考資料】<br>WWWサーバのソースコードの概略</small> <div class=footnote> <small><small> (脚注)【参考】パートは試験の範囲外です </small></small> </div> --- class: compact # <small>【参考】 listenしてデータIO (C言語)</small> ``` struct sockaddr_in sa; // サーバのIPアドレスとポート番号を格納する構造体 int listen_socket, fd; // ソケット // TCP/IP の socket (出入り口)を作成, 作成後オプション設定 listen_socket = socket(PF_INET, SOCK_STREAM, IPPROTO_IP); setsockopt(listen_socket, SOL_SOCKET, SO_REUSEADDR, &sopt, sizeof(sopt)); // socket とアドレス情報 sa を結びつける(だから bind システムコール) bind(listen_socket, (struct sockaddr *)&sa, sizeof(sa)); // 作成した socket で待ち受ける(listen) listen(listen_socket, SOMAXCONN); for(;;) { // 待受して無限ループ,ここでは省略したがデータの送受信はforkした子プロセスが行い,親は待つループを続行 fd = accept(listen_socket, (struct sockaddr *)&src_addr, &len);// リクエストを受け取る、それまで待つ(停止) recv(fd, buf, buflen,....); // データを受け取る send(fd, buf, buflen,....); // データを送信する } ``` --- class: img-right,compact # <small>【参考】 WWWサーバのソースコード(C言語)</small>  <small> - [micro_httpd](http://www.acme.com/software/micro_httpd/) - 300行程度でWWWサーバの本質的なところが分かります! ただlistenする部分は無いので、すべてが分かるわけではありません - 図中の(2)部分だけをC言語で書くとどうなるか?を理解するなら300行で十分ということ - 図中の(1)(3)部分はOS(Unix)の機能を利用しています (inetdから起動する前提です。 詳細はUnixオペレーティングシステムの話になるので,割愛します) </small> --- class: col-2,compact # <small>【参考】 WWWサーバのソースコード(C言語)</small> <div class=footnote> <small><small> (脚注) NCSA = イリノイ大学 米国立スーパーコンピュータ応用研究所。 元々は、 スーパーコンピュータを提供する5施設の一つですが、 最初のモダンなWWWブラウザMosaicの開発で有名です。 ソースコードの系譜は、NCSA Mosaic -> Netscape Navigator -> Mozilla Firefox となります。 初期のWWWブラウザについては、 説著のqiita記事を参照 -> <A HREF="https://qiita.com/fmlorg/items/c97f7289a74f6e60334c"> Ep.001「1993/04 世界は色づいた」 </A> </small></small> </div> <small> - [mini_httpd](http://www.acme.com/software/mini_httpd/) - 4600行でWWWサーバとしての基本機能はすべて備えています - <B>コードリーディングの素材としては、これが適切</B>でしょう - [thttpd](https://www.acme.com/software/thttpd/) - シンプルで小さく移植性のあるセキュアなWWWサーバ。 <B>実用性のある最小</B>のもの - 11000行なので、なんとか読めるでしょう - <B>WWWサーバとして必要十分</B>な機能がありますが、 拡張性を求めるなら apache <wbr> - 実用的にはapacheとnginxですが大きすぎて勉強の素材としては不適切でしょう - [apache](https://httpd.apache.org/)(発音:あぱっち) - NCSA httpd に起源をもつ最も古いサーバ - 2.x系はスレッド駆動型の設計 - モジュールによる拡張機能が豊富 - [nginx](https://www.nginx.org/) (発音:えんじんえっくす) - 非同期通信型の設計 - [リバースプロキシサーバ](https://exercises-aws.fml.org/ja/appendix/www/nginx/) として有名 </small> --- class: compact # <small>【参考】 listenしてhello worldを返す (Go言語)</small> <small> ``` package main import ( "fmt" "net/http" ) func handler(w http.ResponseWriter, req *http.Request) { // "変数 型宣言"の順に書く流派 fmt.Fprintf(w, "hello world") } func main() { http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil) } ``` - 【参考】 [Go言語でWWWサーバをつくる](https://exercises-aws.fml.org/ja/appendix/golang/) (秋学期のAWS構築ガイドより) </small> --- class: compact # <small>【参考】 listenする (言語Python3)</small> <small> ``` #!/usr/bin/env python3 import http.server import socketserver port = 8080 handler = http.server.SimpleHTTPRequestHandler with socketserver.TCPServer(("", port), handler) as httpd: httpd.serve_forever() ``` - 8080/tcp で listen している WWW サーバ - 接続を受け付けますが、何も返事を返してくれません;-) - それにしてもブラックボックス過ぎて裏側が何だか分からないですね;_; - 演習? hello worldとか返すようにhandlerを書いてみるのもよいものですね? - 【参考】 [PythonでWWWサーバを作る](https://exercises-aws.fml.org/ja/appendix/python/) (秋学期のAWS構築ガイドより) </small> --- class: title, smokescreen, shelf, no-footer # 電子メール<br>- アプリケーション層の例(2) - --- class: img-right,compact # メール関連プロトコル <div class=footnote> <small><small> (脚注) 今どき暗号モード(XXXP over TLS)の方を使いますが、 プロトコルの動作を説明することが目的なので、素の方をやります </small></small> </div> <!-- 構成図: メールのやりとりの概要 -->  <small> - HTTP/1.0より少し複雑なstatefullの例 - メールの送信(図の(1)),転送(図の(2)) - SMTP = Simple Mail Transfer Protocol - 25/tcp が伝統のポート番号で、 サーバ間メール転送(図の(2))のデフォルト - 587/tcpはMail Submission(送信,図(1)) - メールをPCに取込む(図の(3))プロトコル - メールソフト(メールリーダ)の裏側 - POP3 - Post Office Protocol - 110/tcp - IMAP4 - Internet Message Access Protocol - 143/tcp </small> --- class: img-right,compact # POP3 全体構成 <div class=footnote> <small><small> (脚注1)POP3のほうが単純なので、こちらから先にやります <br> (脚注2) ブラウザ(webmail)やスマホのアプリも裏側では IMAP4 でアクセスしています。 Webmailがメインでアプリは表示しているだけですという場合はRESTかもしれません。 このへんはアプリの設計思想次第でしょう </small></small> </div> <!-- 構成図: メールのやりとりの概要 --> <!--  -->  <small> - 図の一番左の部分 - 図の(2):メールサーバがメールを受信 - 受信したメール群はメールサーバに保存されています。 メールの保存場所がメールスプール(spool) - メールサーバと同じホスト上で、POPサーバも動いています - ユーザはPOP3(もしくはIMAP4)プロトコルでサーバからメールを取り込みます(図の(3)) </small> --- class: col-2,compact # POP3 動作の詳細 <div class=footnote> <small><small> (脚注1)+で始まる一連の行は、サーバからの応答 <br> (脚注2)クライアントから「4文字のコマンド 引数」を送信 <br> (脚注3) // C言語風のコメントをつけておきます </small></small> </div> <small> - POP3 - 最初は挨拶 - ログイン(**認証**) - ユーザ名とパスワードを送信 -> 本人であることを証明 - 本人であることを確認後 - メールを取得 - メールを削除 - 本人であることを確認できない時は? - 何もできません - ログアウトできるだけ - ログアウト <wbr> ``` +OK Qpopper (version 4.0.5) at // 挨拶 メールサーバ starting. ...略... .. 省略 ... USER ユーザ名 // ログイン +OK Password required for ユーザ名. PASS パスワード // パスワード +OK ユーザ名 has 1 visible... // 認証OK RETR 1 // メール1番を取得 ... 略(メール本体が表示) ... +OK 434 octets DELE 1 // メール1番を削除 +OK Message 1 has been deleted. ... 略 ... QUIT // 終了 +OK Pop server at メールサーバ signing off. ``` </small> --- class: col-2,compact # POP3でメールを受信するデモ <div class=footnote> <small><small> (脚注1)+で始まる一連の行は、サーバからの応答 <br> (脚注2)クライアントから「4文字のコマンド 引数」を送信 </small></small> </div> <small> ``` +OK Dovecot ... // サーバからの挨拶 USER ユーザ名 // ログイン PASS パスワード // パスワード STAT // 統計情報を表示 LIST // メール一覧を表示 RETR 1 // メール1番を取得 DELE 1 // メール1番を削除 QUIT // 終了 ``` <iframe width="679" height="394" src="https://www.youtube.com/embed/OfdR9YwiOU8?rel=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> 埋め込みが動作しない方は[こちら](https://www.youtube.com/embed/OfdR9YwiOU8?rel=0) </small> --- class: img-right,compact # SMTP 全体構成 <div class=footnote> <small><small> (脚注) 587/tcpは人間用、25/tcpはシステム用といった使い分けができるように、あえて別ポートにした運用がのぞましい <br> システム用submissionの例: 客先に納品したサーバからログをメールで送信したい場合。 メールサーバで25/tcpのフィルタを書き、このサーバからのみ25/tcpを受け付け、 一般ユーザはは587/tcpを使う </small></small> </div> <!-- 構成図: メールのやりとりの概要 --> <!--  -->  <small> - 図の(2)がメール転送(mail transfer) - 伝統の25/tcpを使います - 図の(1)が(ユーザからの)メール送信 - mail submission。 <B>submissionではユーザを認証して不正アクセスを防ぐ必要</B>があります - SPAM送信サーバとして悪用されないように、自組織のユーザだけが送信可 - 使うポートは25/tcpもしくは587/tcp </small> --- class: col-2,compact # SMTP 動作の詳細 <div class=footnote> <small><small> (脚注) // C言語風のコメントをつけておきます </small></small> </div> <small> - SMTP - 最初は挨拶 - 送信者を指定 - 送信先を指定 - 必要なら複数指定可 - 一度に指定できるメールアドレスは一つなので、 必要な回数だけ繰り返します - 複数指定も、ふつう上限があります(念のためのSPAM対策) - 上限は1000人くらいが普通ではないかと - メールを送信 - ログアウト <wbr> <small> ``` 220 〜.fml.org ESMTP Postfix // サーバからの挨拶 EHLO client.nuinui.net 250-mta.fml.org ... 略 ... 250 8BITMIME MAIL FROM:<fukachan@fml.org> // 送信者 250 Ok RCPT TO:<rudo@nuinui.onet> // 送信先 250 Ok DATA // データ転送開始 354 End data with <CR><LF>.<CR><LF> メール本文をここで送信 . 250 Ok: queued as 9BB9F86640 QUIT // 終了 221 Bye ``` </small> </small> --- class: col-2,compact # SMTPでメールを送信するデモ(ビデオ) ``` 220 〜.fml.org ESMTP Postfix // サーバからの挨拶 MAIL FROM:<fukachan@fml.org> // 送信者 RCPT TO:<rudo@nuinui.onet> // 送信先 DATA // データ転送開始 QUIT // 終了 ``` <iframe width="679" height="394" src="https://www.youtube.com/embed/dCSryiMkEfM?rel=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> 埋め込みが動作しない方は[こちら](https://www.youtube.com/embed/dCSryiMkEfM?rel=0) --- class: title, smokescreen, shelf, no-footer # 参考資料<br>メールサーバのソフトウエア紹介 <div class=footnote> <small><small> (脚注)【参考】パートは試験の範囲外です </small></small> </div> --- class: compact # 【参考】 メールソフトウエア <small> - コードを読むならPostfixがおすすめです - メールサーバのソフトウエア (登場順) - Sendmail - もっとも初期からあるメールサーバで、 互換の基準、いまは商用サポートあり - モノリシックアーキテクチャ - バグが多かったしな... - (90年代末にPostfixがリリースされた時にSendmailは捨てました) - qmail - 高速でセキュアなのは確かですが、 DJB(作者)の設計思想では運用しづらい。 DJB教に入信しないと...(数学屋とは馬があわない:-) - Exim - Debian/Linuxのデフォルトなので運用されているサーバ数は多いらしい - Postfix - 作者W.Venemaは Postfix以前にtcp_wrappersやSATAN、 またFIRSTの運営などセキュリティ分野で知られた人です (高エネルギー物理出身ですけどね:-) - モデュラーアーキテクチャの勉強にもおすすめです </small> --- class: center,compact # 【参考】 Postfixの(だいぶ簡略化した)内部構造 <div class=footnote> <small><small> (脚注) だいぶ複雑なので説明は省略しますが、 概略は、ぼくの本の第37〜38章を参照 -> "fml バイブル" (大学図書館にあります) </small></small> </div>  --- name: wholesight class: title, smokescreen, shelf, no-footer # DNS Part I 全体像と用語 <div class=footnote> <small><small> </small></small> </div> <div class=digest-begin-01></div> --- class: img-right,compact # WWWの動作(DNS込み)  <small> - 今まではDNSを省略していました(図(3)(4)のみ) - URI例: http://porta.mc.chitose.ac.jp/portal2/ - 右図がDNSを含めたHTTPの動作です。 ブラウザにURIを指示すると - (1) ブラウザはURIに含まれるサーバ名portal.mc.chitose.ac.jpの IPアドレスをDNSサーバに問い合わせます - (2) DNSサーバはブラウザにIPアドレス=210.128.52.45を回答 - (3) ブラウザは210.128.52.45と通信を始めます (ここからは前節までに解説したとおり) - このIPアドレスを検索する仕組みを**DNS**と呼んでいます。 <b>本節はDNS(図の(1)(2))の解説です</B> </small> --- class: img-right,compact # DNS = Domain Name System (Service) <div class=footnote> <small><small> (脚注) ディレクトリサービス(DS)の典型例が電話帳(e.g. タウンページ)です。 認証システムもユーザとパスワードの一覧という電話帳似のデータを持つので DS です。 例: Active Directory, OpenLDAP(-> 後継? 389-ds?) </small></small> </div>  <small> - Domain Name System (Service)の略 - **ディレクトリサービス**の一種 - 文字列からIPアドレスを検索する仕組みが代表例です: DNSの検索例 - portal.mc.chitose.ac.jpドメインのIPアドレスを知りたい - IPアドレス210.128.52.45に対応するサーバ(のドメイン)名が知りたい - user@photon.chitose.ac.jp宛メールの送信先(メールサーバ名)を知りたい - photon.chitose.ac.jpについて管理しているDNSサーバを知りたい </small> --- class: img-right,compact # あらゆるサービスが裏でDNSを使っています <div class=footnote> <small><small> 右図: portal.mc.chitose.ac.jp にアクセスしている様子。 <br> ブラウザは、裏で (1)(2)DNSを使ってIPアドレスを割り出し、 (3)(4)そのIP(210.128.52.45)へアクセスします </small></small> </div class=footnote>  <small> - プログラムにとっては、すべて**数字**ですが - **OSの内部**では、通信先の指定を**数字=IPアドレス**で行っています (例: 210.128.52.45) - ユーザ利便性はドメインの方がよいはず - ユーザがIPアドレスでインターネットにアクセスするのは現実的ではありません - 何十個も数字を覚えらません - 英語に近い表記を使いたい - 例: `https://portal.mc.chitose.ac.jp/` - 例: `username@photon.chitose.ac.jp` </small> --- class: col-2,compact # DNS関連の重要用語まとめ <div class=footnote> <small><small> (脚注1)業界人はdotを発音しませんが、あうんの呼吸で理解してね (脚注2)Googleのchubbyも地球規模ですな... </small></small> </div class=footnote> <small> - **DNS** - Domain Name System (Service) - インターネットの基盤技術 - 地球規模の**分散システム**の成功例 - **UDP**ベースの数少ない例 - **ドメイン名** - **.**(発音はdot)区切の文字列 - chitose.ac.jp - **FQDN** (Fully Qualified Domain Name) - ホストの完全なドメイン名 - 階層をすべて表記したもの - portal.mc.chitose.ac.jp - g201pc001.pc.chitose.ac.jp <wbr> - **木構造**をしたデータベース - 格納している情報を**レコード**と呼ぶ - 例:Aレコード(IPアドレス) - **ネームサーバ** (歴史的にはコレ) - 最近はDNSサーバと言うことも多い - スライドは**DNSサーバ**に統一 - **名前解決**(name resolution) - ネームサーバから情報を取得することで、 この動作をするソフトウエアが**リゾルバ**(resolver) - 例:ドメイン名からIPアドレスを取得 </small> --- class: compact # ドメイン名 <div class=footnote> <small><small> <wbr> (脚注) 用法上の注意: ドメインとドメイン名の使い分けはRFCも曖昧で断言しづらい...;_; 領土のような意味合いに力点がある場合にドメインを使っているように読めますが、 同じ意味で使っているようにみえる場合もあり... <br> ドメイン名をドメインと呼ぶ例: TLD(後述), サブドメイン <br> たとえばportal.mc.chitose.ac.jpの場合、(一番左の) ホストの役割を説明するportal部分をホスト名と呼ぶ風習がありますが、 <b>コンピュータを識別するための名前(ホスト名)にはFQDNを使うべき</b>です </small></small> </div> <small> - ドット`.` 区切りの文字列 - 使える文字は、英数字とハイフン(**-**)です (大文字小文字は区別しません) - 階層構造を表現しています(後述) - 例: URL: http://portal.mc.chitose.ac.jp/ - 例: メールアドレス b2902900@photon.chitose.ac.jp - photon.chitose.ac.jp がドメイン名 - b2902900 部分はユーザ名。 <b>大文字小文字は区別したほうが良い</b>でしょう。 区別するかしないかは微妙な話題で、 メールサーバとOSの実装依存ですが、 厳しい方(Unix)に合わせるのが安全です </small> --- class: compact # ドメインの階層構造(全体とTLD) <small> - ドット`.` 区切りの文字列 - 階層構造は「**ホスト名.組織.組織種別.国名**」のように並ぶ。より大きな単位が右側 - 例: chitose.ac.jp - chitose (千歳、この場合は大学名) - ac (高等教育機関,academic) - jp (日本,TLD) - TLD (top level domain) ... 一番大きな単位(ドメイン名の一番右側) - 各TLDごとに登録を管理する組織(レジストラ,民間企業)があります - 基本は二文字の国名: jp (日), uk (英), us (米国,USA)ですが、アメリカ特例枠あり - アメリカ特例枠 ... (インターネット初期から存在する)us をつけないアメリカのドメイン - .com .net .org が有名 - 1990年代後半に一般開放したため、ドメイン取得者がアメリカ人とは限りません - 慣習的に<b>「ソフトウエア名(OSS).org」</b> 例: fml.org (このサーバ:-) - .edu .gov .mil はアメリカでのみ利用しているドメイン - その他も(気づくと)新TLDが登場して収拾がついていない感じ...、例: 目的別? info tel、地域? asia </small> --- class: compact # 【参考】ドメインの例 <small> | TLD | 2LD | 属性 | 例 | |-----|---------|------------------------|-------------------------------------------| | net | | ネットワーク | nuinui.net | | com | | 営利企業 | amazon.com zoom.com(zoom.usへ転送) | | org | | 任意団体(ソフト名) | netbsd.org debian.org postfix.org fml.org | | edu | | アメリカの高等学術機関 | mit.edu | | gov | | アメリカ政府 | www.whitehouse.gov | | mil | | アメリカ軍 | af.ml (US空軍) | | | | | | | us | | | zoom.us | | | | | | | jp | ac | 日本国内の高等教育機関 | chitose.ac.jp | | | co | 民間の営利企業 | toyota.co.jp amazon.co.jp | | | go | 政府関係 | mext.go.jp | | | ed | 教育機関 | sapporonishi.hokkaido-c.ed.jp | | | lg | 地方自治体 | pref.hokkaido.lg.jp | | | 名前 | なし | toyota.jp amazon.jp(co.jpへ転送) | </small> --- class: img-right,compact # ドメインの階層は木構造 <div class=footnote> <small><small> (脚注) 正しいドメイン名は一番右に.がつきますが、 面倒(?)なので、たいてい一番右の.を省略して書くことが多いです (例: portal.mc.chitose.ac.jp.) </small></small> </div>  <small> - 各TLDごとに管理 - 各TLDごとにレジストラ(+ レジストラへの登録代行業者)がいます - jpドメインは[JPRS](https://www.jprs.co.jp/)(2002/04/01-)です。 なお2002/03/31までは[JPNIC](https://www.nic.ad.jp/)でした - DNSは図のように木構造と考えられます - 数学のグラフ理論由来で、接点はnode、端はleaf(葉)、線はedge(枝)と呼ばれます。 一番上には**「.」**で表現される**root(根)ノード**があるという想定です - DNSの検索(query)とは、一番上の**rootノードから枝を下っていくこと**です </small> <div class=digest-end-01></div> --- class: img-right,compact # ドメインの木構造とゾーンとドメイン <div class=footnote> <small><small> (脚注) このあたりがDNSサーバの実務(ゾーンファイルには何を書くのか?)に一番関係する部分でしょう。よくわかってないと間違った設定をして、あなたのドメインがインターネットから消えたりしますね:-) とはいえ、 たいていDNSは自爆系で他人には迷惑かからないので、 ぜひドメインとって自分で(bindとかnsdを生)設定してみるといいよね </small></small> </div>  <small> - DNSは無数のゾーンに分割され管理されています。**委任された管理単位をゾーン**と呼びます - JPRSは(ルートの管理組織から)jpゾーン全体の管理を委任されています - さらに小さな単位の ad.jp ac.jp co.jp なども管理しています - **大学はJPRSからchitose.ac.jpゾーンの管理を委任されています(図の網掛け部分**) - ゾーンの名称には一番上のノード名chitose.ac.jpを使います - ゾーン内の、 より小さな管理単位であるphoton.chitose.ac.jpやmc.chitose.ac.jpも管理しています。 なお、photonやmcなどは**サブドメイン**と呼ばれます </small> --- class: img-right,compact # ドメインの木構造とゾーンとドメインとDNSサーバ <div class=footnote> <small><small> (脚注1) 各ノードにドメイン名が対応するのだから、 各ノードに各ドメイン担当のDNSサーバ群を配置するのが素直に感じられますが、 サーバの台数を増やすのも管理が面倒なので、 ゾーンごとに2〜3台が普通 <br> (脚注2) (a)JPRSのDNSサーバはjpとac.jp他 (b)大学のDNSサーバはchitose.ac.jpおよびmc.chitose.ac.jp を担当 </small></small> </div>  <small> - 各ゾーンにはDNSサーバ群があります - 障害に備え複数(最低2)台のサーバ <br> (メインのサーバをprimary,予備機をsecondaryと呼ぶ**ならわし**) - 定期的にサーバ間でデータを同期しています。 同期の際のデータ転送は**TCP**です </small> --- class: img-right,compact # ドメインの階層とクエリ <div class=footnote> <small><small> (脚注) (中間試験の範囲ではないので)具体的な動作を説明しないため、モヤモヤするとおもいますが、 クエリの動作の実際は Part II で実演するので、気になる人は、そちらも見ててください。 </small></small> </div class=footnote>  <small> - DNSの問い合わせ動作が**クエリ(query)** - **正引き**: ドメイン名->IPアドレス - **逆引き**: IPアドレス->ドメイン名 - この問い合わせ(のデータ転送)は**UDP** - パケットが何度も往復するので**動作が軽いことは重要**です (詳細は Part II) - 一方、前頁で述べたように、 DNSサーバ(primaryとsecondary)間の設定の同期では**信頼性**が重要なので、 データ転送に**TCP**を使っています - この**TCPとUDPの使い分けに注目** - クエリの際は木構造を一番上のルートから下にたどっていきます (詳細は Part II) </small> --- class: img-right,compact # 世界規模の分散システムとしてのDNS <div class=footnote> <small><small> (脚注1) (インターネットのご先祖の時代の)初期にはファイル方式でしたが、破綻は見えていたので1980年代前半にDNSへ移行しました (脚注2) 非常に多くのDNSサーバの自律的な分散と協調を期待したシステムです。 DNS管理者たちのスキルと善意に依存とも言う;-) 自信がない人はDNSサービス(SaaS)を買うのが推奨です (脚注3) でも、プロを目指す人は試験に出ない範囲も勉強してほしい </small></small> </div class=footnote>  <small> - 木構造を階層的に多数のゾーンに分け、 各ゾーンが自分(および自分以下の階層)を管理することで、 インターネットの名前空間を一極集中ではなく**小さな管理単位**の集合体として再編成しています - DNSは、世界中に分散した無数のDNSサーバ群からなる**分散システム**で、 世界規模で実に約40年動きつづけています </small> --- name: resolver class: title, smokescreen, shelf, no-footer # DNS Part II 【参考】リゾルバの実際 <div class=footnote> <small><small> 余力がありそうな、やりますが、なんとなく無理そうな気がします。 この場合、試験範囲からは削除。 <br> ちなみに、リゾルバのデモ動画を見ながら、おなじようにコマンドを叩くのが理解の早道だと思います。 </small></small> </div> --- name: how-browser-resolve class: img-right,compact # WWWの動作(DNS込み)(再掲)  <small> - 前述の図をもう一度 - 右図の(1)(2) - (1) ブラウザはURIに含まれるサーバ名portal.mc.chitose.ac.jpの IPアドレスをDNSサーバに問い合わせます - (2) DNSサーバはブラウザにIPアドレス=210.128.52.45を回答 - (3)(4)はブラウザがHTTPでコンテンツを取りにいく様子 - この(1)(2)の裏側を解説します - 正確にはOSの「DNSクエリをおこなうライブラリ関数」 + (右図の)「DNSサーバとインターネット上のDNSサーバ群との間のやりとり」からなる </small> --- class: img-right,compact # 前図(2)の裏側, このあとのデモの概略 <div class=footnote> <small><small> (脚注) ルートサーバ群のどれに問い合わせるか?はDNSソフトウエアに依存するでしょう。 ただし、常識的に考えれば、次のどちらかのロジックではないかと思います (a)サーバ群に均等に問い合わせる(roundrobin) (b)とりあえず一番近いサーバ(日本ならm)を使うが、応答が遅い場合は他のサーバへ切り替え (random? roundrobin?) </small></small> </div>  <small> - 各ゾーンは直下のゾーンを管理するDNSサーバの情報を持っています - portal.mc.chitose.ac.jp検索時(デモ参照) - ルートサーバへの問い合わせ - ルートサーバはjpゾーンのDNSサーバに問い合わせよと回答 - jpのDNSサーバはchitose.ac.jpゾーンのDNSサーバについて知っており、 そちらに問い合わせよと回答 - chitose.ac.jpはportalのIPアドレスを知っているので、アドレスを回答 </small> --- class: img-right,compact # DNSの問い合わせと木構造(再掲)  <small> - 前述のように、DNSの検索とは木構造を**.**(root)から下っていくことです - 右図にはデモで登場する各ゾーンのDNSサーバ群が書き込まれています - 実際には、各ゾーンに複数のサーバがあり、 全サーバが同じデータをもっているので、 どのサーバに問い合わせても結果は同じです - (以下の説明およびデモでは名前順の先頭のサーバを使っています) </small> --- class: img-right,compact # DNSの問い合わせ(1): 正引きの例 <div class=footnote> <small><small> (脚注1) (いまどきDHCPばかりで、OS設定経験者のほうが少数でしょうが) OSの「DNSサーバの設定」という項目で指定するべき情報が full service resolverのIPアドレスです (脚注2) Googleの8.8.8.8などのPublic DNSもfull service resolverですが、 分散システムであることが重要なインターネットの理念に逆らっていると批判あり </small></small> </div class=footnote>  <small> - 図(1)の裏側(a)〜(f)を解説します - 例: ドメインportal.mc.chitose.ac.jpのAレコードを問い合わせる - クライアントのソフトウエア(例:WWWブラウザ)はリゾルバ関数を呼び出します (歴史的にはライブラリlibresolv.a)。これは通常stub resolverという役割をしていて、 一番身近な full service resolver へ(1)問い合わせを送り(2)返事を待ちます - 実際に検索の仕事をするのは full service resolver です(右図中央下のサーバ) </small> --- class: img-right,compact # DNSの問い合わせ(a)(b): 正引きの例  <small> - 出発点は木構造の一番上**.**(root)ゾーンへの問い合わせです - **.**(root)の情報をもつDNSサーバ群をルートサーバと呼んでいます。 これは世界各国に分散して設置している13台のサーバです - この情報は、出荷設定でOSに埋め込まれています (この情報が無いとDNSの検索が始められない) - ここではルートサーバとしてA.ROOT-SERVERS.NET.を使うとします - (a)ルートサーバに問い合わせを送ります - (b)ルートサーバから 「自分は知らない。 JPゾーンについてはJPRSのサーバ(a.dns.jp)に聞きなさい、IPアドレスは〜」 と返事をもらいます </small> --- class: img-right,compact # DNSの問い合わせ(c)(d): 正引きの例  <small> - (c)再度a.dns.jpに問い合わせを行います - (d)a.dns.jpからは 「自分は知らない。 CHITOSE.AC.JPゾーンについてはmcgn01.chitose.ac.jpに聞きなさい、IPアドレスは〜」 と返事をもらいます - a.dns.jpはJPドメインとAC.JPドメイン両方の情報を管理しているので、 (ノードの階層順に2回問い合わせそうですが、1回分は省略されて) いっきにCHITOSE.AC.JPゾーンのDNSサーバ情報を教えてもらえます </small> --- class: img-right,compact # DNSの問い合わせ(e)(f): 正引きの例  <small> - (e)再度mcgns01.chitose.ac.jpに問い合わせを行います - (f)このサーバはmc.chitose.ac.jpゾーンも管理しているので、 いっきに答えまでたどりつき 「portal.mc.chitose.ac.jpのIPアドレスは210.128.52.45です」 と返事をもらいます(前頁と同様の理屈) - (2)full service resolverは、 問い合わせてきたクライアントに210.128.52.45という返事を返します - (3)(4)このあとHTTPの処理がはじまります </small> --- class: center,compact # デモ: ルートサーバ <iframe width="667" height="386" src="https://www.youtube.com/embed/P1nKBS7BrUo?rel=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> --- class: compact # デモで使うコマンドの説明 <small> - DNSサーバに問い合わせをするdigコマンド ``` dig @DNSサーバ ドメイン名 [RR] 例: RR省略時は正引き dig @210.128.52.11 portal.mc.chitose.ac.jp 例: メールサーバの問い合わせ(RRがMX) dig @210.128.52.11 photon.chitose.ac.jp mx ``` - 類似のDNSを引くコマンドに**nslookup**と**host**があります - プロは**dig**を好んで使っている雰囲気がありますね - いずれのコマンドもBINDという最初期からあるDNSサーバソフトウエアの一部です - **nslookup**は多くのOSでサポートされていて、 UnixでもWindowsでも、たいてい使えるはずです </small> --- class: center,compact # デモ: 正引き <iframe width="667" height="386" src="https://www.youtube.com/embed/3PXVb-S_CN0?rel=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> --- class: compact # リソースレコード <small> - ドメインに関連付けられた情報を**リソースレコード(RR)**と呼びます <br> (略して**レコード**と呼ぶことも多いです) - **正引き**とは**ドメイン名から該当するIPアドレスを取得する**ことで、 これは該当する**Aレコード**の検索になります。 サーバが答えを知らない場合たとえば「jpドメインはa.dns.jpに聞け」 と回答をしますが、 ここで答える情報が(jpドメインの)**NSレコード** - **逆引き**とは**IPアドレスからドメイン名を探す**ことで**PTRレコード**の検索 (正引きの逆) | リソースレコード | 値 | 備考 | |------------------|--------------------------|--------------------------------------| | A | IPアドレス | Aレコードの検索が正引き | | PTR | ドメイン名 | PTRレコードの検索が逆引き | | MX | メールサーバ | メールの送信先サーバの検索 | | NS | DNSサーバ | ゾーンを管理しているDNSサーバの情報 | | TXT | テキスト(任意のテキスト) | 例: [SPF](/slides/network/tcpip/app_dns/#SPF) | <small> 表:代表的なDNSレコード </small> </small> --- class: img-right,compact # 逆引きの木構造とクエリ  <small> - **arpa**という仮想TLDを用意し木構造を作ります (図中一番右の縦1列) - 正引きと同様に**.**(root)から下る検索 - メリットは、正引きと同じしくみがそのまま使えることです - 関数、木構造、設定ファイルなど - デメリットは、DNS管理者が設定を書くときに頭を使うことだけです - 大学側で管理しているドメインは**52.128.210.in-addr.arpa.**です - 問い合わせるドメイン名は**45.52.128.210.in-addr.arpa.**になります - 一番右側の列を下から上に読むと、この文字列になりますよね? </small> --- class: center,compact # デモ: 逆引き <iframe width="667" height="386" src="https://www.youtube.com/embed/nFHnGIpUw0Y?rel=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> --- class: img-right,compact # MXレコードの検索  <small> - 手順は正引きと同じで、問い合わせるものがMXレコードになるだけです - 例: photon.chitose.ac.jpのMXレコードを知りたい - 問い合わせ先のドメインにMXレコードという情報があれば、それを返します - photon.chitose.ac.jpの場合 photon-chitose-ac-jp.mail.eo.outlook.com. というサーバ名(Office365のサーバ名)が返されます - メールを送信する側は、このサーバにメールをSMTPで送ります </small> --- class: center,compact # デモ: MXレコード <iframe width="667" height="386" src="https://www.youtube.com/embed/a-wkhusE8F0?rel=0" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe> --- class: col-2,compact # UDP の意義, TCP の使いどころ <small> - 本節で見たように、 一回の問い合わせだけで、パケットが4往復(1)(2)(a)〜(f)します。 場合によっては、もっとたくさんの往復がありえます - HTTP(TCPアプリケーションの代表例)とは、だいぶ挙動が違います - HTTPはWWWサーバと対向で様々なサイズのデータを返しうるのに対し - DNSでは相手が複数、短い問い合わせ(小サイズ)を何度も行います - DNSは処理速度も要求されます - DNSは静的で冗長性が高いシステムです。 同じ情報を持ったDNSサーバ群が運用されており、どのサーバに問い合わせても大丈夫です - DNSの問い合わせはUDPという転送方式をデフォルトで使います。 ただし不具合や大量の答えが返る際にはTCPへ移行することがあります - 問い合わせに不具合がある際は、 再び問い合わせるなり、 タイムアウト後に別のDNSサーバへ問い合わせるなりは、 resolverが制御します - こういった (TCPアプリとは挙動が異なる)処理を、 **プログラム作成者(user)がすべてコントロールするためUDPで作られている**と言えます - (再掲)各ゾーンには複数のDNSサーバがあり、 同じ**設定情報**を持ちますが、 確実な転送を行うため、 そのサーバ間の**コピーはTCP**です </small> --- class: col-2,compact # まとめ <small> - Domain Name System (Service) - アプリにドメイン名名前空間の情報を取得する仕組みを提供します - 名前解決, リゾルバ - 正引き,逆引き,メールの送信先 - 特徴 - インターネットの基盤技術 - 分散システムの大成功例 - UDPベースの数少ない例 - ドメイン - **.**区切の文字列 - FQDN (Fully Qualified Domain Name) - portal.mc.chitose.ac.jp <wbr> - 木構造をしたデータベース - 各自の管理(を委任された)部分がゾーンで、 各ゾーンは複数のドメイン名を持ちえます - 各ノード(=ドメイン名)には複数のレコードが対応しえます。例: - IPアドレス(Aレコード), ドメイン名(PTR), メール転送先(MX), ドメイン管理情報(NS) - 検索は、木構造を**.**(root)ノードからリーフへ下っていくことにあたります - 転送方式 - クエリはUDP、場合によってはTCP - サーバ間のコピーはTCP </small> --- name: references class: title, smokescreen, shelf, no-footer # DNS Part III 【参考】 ロードバランス,SPF <div class=footnote> <small><small> (脚注)【参考】パートは試験の範囲外です </small></small> </div> --- class: col-2,compact # DNSサーバの冗長化構成 <div class=footnote> <small><small> (脚注) メインのサーバを primary DNS server (name server)、 二台目以降のコピーをもつサーバを secondary DNS server (name server)と呼びます。 ちなみに何台あってもsecondaryです </small></small> </div> <small> - DNSサーバの冗長化は元々想定されているので、 単に複数台のDNSサーバを用意します - 1台がメイン(primary)です - それ以外のサーバ(secondary)は定期的にメインのサーバから情報をコピーします - DNSの情報更新は稀なので、一時間に一回確認するといったペースで十分です <wbr> - 問い合わせはクライアント側のfull service resolverの実装依存ですが - たいていは均等になるようNSレコードの順に聞いてくるはずです (roundrobin) - 例えば、a.dns.jpに尋ねたら、次の問い合わせはb.dns.jpといった具合に... </small> --- class: col-2,compact # DNSサーバのロードバランス <div class=footnote> <small><small> (脚注1) 特定のクライアントAがアクセスするサーバは、どちらか一つです。 サービス提供側からみた時に 「多数のクライアントからのアクセスが分散して嬉しい」という意味です (脚注2) 秋学期OSの[「高信頼化」](https://lectures.fml.org/slides/os/internal/highavail/)を参照 </small></small> </div class=footnote> <small> - クライアントはDNSサーバに均等に問い合わせるはずという性質を利用します - 各DNSサーバに違う内容のレコードを用意することで、サービスを冗長化することが出来ます - たとえば**portalサーバが二台(.45 と .46)ある場合**、 右表のようにDNSサーバを設定しておけば、 多数のユーザの問い合わせが、なんとなくDNSサーバ1と2に分散され、 portalサーバへのアクセスも分散されます (長い時間でみれば統計的に均等なアクセス、つまり**ロードバランス**が実現されます) <wbr> | DNSサーバ | portalのAレコード(返事) | |------------------|---------------------------------| | DNSサーバ1 | portalのアドレスは210.128.52.45 | | DNSサーバ2 | portalのアドレスは210.128.52.46 | - ロードバランスの原始的なテクニック - 設定ファイルをDNSサーバごとに個別管理しないといけないのが面倒ですが、 - それ以外にも、明らかな欠陥がありますけどね... (さて、それは何でしょう?:-) </small> --- class: col-2,compact name: SPF # メールの認証: SPF (TXTレコードの応用) <div class=footnote> <small><small> (脚注) DKIMおよびDMARCは省略しますが、最低限SPFは設定したい。 DKIMは非対称鍵暗号ベースで送信者の正当性を確認する技術、 DMARCはSPFとDKIMをさらに補強する技術 </small></small> </div> <small> - メール送信サーバの正当性を検証する - メールで利用するドメインのTXTリソースレコードにSPF情報を書きます - SPFは**正しい送信サーバのIPアドレス**の情報です。 このサーバ以外から送られてきたらSPAMメールのはず - 受信側メールサーバがSPFを調べ受け取りを判断します(図中(2)の受信部分) - SPAMの場合、 メールのドメイン名から調べたSPFのサーバと送信元サーバ情報が異なるので、 受信を拒否 ``` [図右側のサーバがあるドメインに設定するSPFの例] v=spf1 ip4:210.128.52.0/24 mx ptr ~all ``` </small> 