CubicLouve

Spring_MTの技術ブログ

SSL/TLSのシーケンスまとめ

TCP 3-way handshakeの復習 - CubicLouve

上記を踏まえた上でSSL/TLSのシーケンスをtcpdumpwiresharkで追ってみました。

まだ理解しきれていない部分があるので直すかも。

clientのコードはこちらから。

SpringMT/socket_test · GitHub

clientのコードは下記ページのものを使っています。

SSL/TLS でアクセスしてみよう (1)

流れ

1. クライアントからSYN(TCPと一緒)

22:41:54.444298 IP 192.168.100.101.51013 > nrt04s05-in-f18.1e100.net.https: Flags [S], seq 1497432669, win 65535, options [mss 1460,nop,wscale 4,nop,nop,TS val 946049109 ecr 0,sackOK,eol], length 0

2. サーバーから SYN + ACK(TCPと一緒)

22:41:54.609915 IP nrt04s05-in-f18.1e100.net.https > 192.168.100.101.51013: Flags [S.], seq 1784227309, ack 1497432670, win 42540, options [mss 1360,sackOK,TS val 3615605143 ecr 946049109,nop,wscale 7], length 0

3. クライアントから ACK(TCPと一緒)

22:41:54.609979 IP 192.168.100.101.51013 > nrt04s05-in-f18.1e100.net.https: Flags [.], ack 1, win 8256, options [nop,nop,TS val 946049273 ecr 3615605143], length 0

4. クライアントがClient Helloメッセージを送る

クライアントがサポート可能な暗号化/圧縮アルゴリズムを通知する

wiresharkでみてみると、CipherSpecsが送られている。

ここではフラグがPUSHになっている。(すぐに返せってことなのかな)

f:id:Spring_MT:20150103001633p:plain

22:41:54.611008 IP 192.168.100.101.51013 > nrt04s05-in-f18.1e100.net.https: Flags [P.], seq 1:131, ack 1, win 8256, options [nop,nop,TS val 946049274 ecr 3615605143], length 130

5. サーバーがACKを返し、さらにServer Helloを返す

使用する暗号アルゴリズムをServerHelloメッセージに格納しておくる。

今回はCipher Suite: TLS_RSA_WITH_RC4_128_SHA (0x0005)を使っていた。

この時点で証明書送ってそうだけどな。。。。

f:id:Spring_MT:20150103001656p:plain

22:41:54.769011 IP nrt04s05-in-f18.1e100.net.https > 192.168.100.101.51013: Flags [.], seq 1:1349, ack 131, win 341, options [nop,nop,TS val 3615605273 ecr 946049274], length 1348

22:41:54.769090 IP nrt04s05-in-f18.1e100.net.https > 192.168.100.101.51013: Flags [.], seq 1349:2697, ack 131, win 341, options [nop,nop,TS val 3615605273 ecr 946049274], length 1348

6. サーバーがCertificateを送る

サーバの証明書をCertificateメッセージに格納して送る。

f:id:Spring_MT:20150103001716p:plain

22:41:54.769249 IP nrt04s05-in-f18.1e100.net.https > 192.168.100.101.51013: Flags [P.], seq 2697:3172, ack 131, win 341, options [nop,nop,TS val 3615605273 ecr 946049274], length 475

7. クライアントがClient Key Exchange, Change Cipher Spec, Encrypted Handshake Messageを送る

クライアントが生成した、プリマスターシークレットをサーバーの公開鍵で暗号化して送信する。

f:id:Spring_MT:20150103001753p:plain

22:41:54.804024 IP 192.168.100.101.51013 > nrt04s05-in-f18.1e100.net.https: Flags [P.], seq 131:445, ack 3172, win 8192, options [nop,nop,TS val 946049465 ecr 3615605273], length 314

8. サーバーがChange Cipher Spec, Encrypted Handshake Messageを送る

新しい暗号化仕様の利用開始を通知。

f:id:Spring_MT:20150103001810p:plain

22:41:54.904878 IP nrt04s05-in-f18.1e100.net.https > 192.168.100.101.51013: Flags [P.], seq 3172:3219, ack 445, win 350, options [nop,nop,TS val 3615605439 ecr 946049465], length 47

9. 通信開始

ここからやっと通信開始 ここまでをSSL_connectがやっている。

SSL_connect - initiate the TLS/SSL handshake with an TLS/SSL server

参考文献

WiresharkでSSL通信の中身を覗いてみる - ろば電子が詰まっている

SSL/TLS の暗号アルゴリズムの決定メカニズムをパケットレベルで追いかけてみる - /dev/null blog

「不正アクセスを防止するSSL/TLS」最新記事一覧 - ITmedia Keywords

OpenSSLライブラリを使ってプログラミング(1) - 再帰の反復

raw パケット

https://gist.github.com/SpringMT/feeb955226df21a633ad

TCP 3-way handshakeの復習

3 way handshakeのおさらい

tcpdump の見方を勉強を見ながら自分でもやってみた。

ほとんど、上記のブログのままやってます。

clientとserverはこちらを使っています。

SpringMT/socket_test · GitHub

コネクション開始

1. SYN

クライアントからSYNを送る

時刻(HH:MM:SS.マイクロ秒) 送信元 > 送信先 Flags: フラグ seq: シーケンス番号 ack: ACK 番号 win: ウィンドウサイズ options: TCPのオプション lengh: 送信バイト数
15:59:33.795719 localhost.58710 > localhost.italk S(SYN(コネクション確立要求)) 2814860088 なし 65535 mss 16344,nop,wscale 4,nop,nop,TS val 927136454 ecr 0,sackOK,eol 0
15:59:33.795719 IP localhost.58710 > localhost.italk: Flags [S], seq 2814860088, win 65535, options [mss 16344,nop,wscale 4,nop,nop,TS val 927136454 ecr 0,sackOK,eol], length 0

2. SYN/ACK

サーバーからSYN + ACKを送る

時刻(HH:MM:SS.マイクロ秒) 送信元 > 送信先 Flags: フラグ seq: シーケンス番号 ack: ACK 番号 win: ウィンドウサイズ options: TCPのオプション lengh: 送信バイト数
15:59:33.795801 IP localhost.italk > localhost.58710 S.(SYN + ACK (接続許可)) 1552828466 2814860089(1のseq + 1) 65535 mss 16344,nop,wscale 4,nop,nop,TS val 927136454 ecr 927136454,sackOK,eol 0
15:59:33.795801 IP localhost.italk > localhost.58710: Flags [S.], seq 1552828466, ack 2814860089, win 65535, options [mss 16344,nop,wscale 4,nop,nop,TS val 927136454 ecr 927136454,sackOK,eol], length 0

3. ACK

クライアントからのACK

時刻(HH:MM:SS.マイクロ秒) 送信元 > 送信先 Flags: フラグ seq: シーケンス番号 ack: ACK 番号 win: ウィンドウサイズ options: TCPのオプション lengh: 送信バイト数
15:59:33.795801 localhost.58710 > localhost.italk . なし 1(本当は2のseq(1552828466) +1 tcpdumpの-Sオプションでfullの数字になる ) 9186 nop,nop,TS val 927136454 ecr 927136454 0
15:59:33.795814 IP localhost.58710 > localhost.italk: Flags [.], ack 1, win 9186, options [nop,nop,TS val 927136454 ecr 927136454], length 0

コネクションクローズ

1. クライアントがFIN + ACK送る

時刻(HH:MM:SS.マイクロ秒) 送信元 > 送信先 Flags: フラグ seq: シーケンス番号 ack: ACK 番号 win: ウィンドウサイズ options: TCPのオプション lengh: 送信バイト数
17:22:03.845002 IP localhost.61206 > localhost.italk F. 1 6 9186 nop,nop,TS val 932053925 ecr 932053925 0
17:22:03.845002 IP localhost.61206 > localhost.italk: Flags [F.], seq 1, ack 6, win 9186, options [nop,nop,TS val 932053925 ecr 932053925], length 0

2. サーバーがFIN + ACK返す

時刻(HH:MM:SS.マイクロ秒) 送信元 > 送信先 Flags: フラグ seq: シーケンス番号 ack: ACK 番号 win: ウィンドウサイズ options: TCPのオプション lengh: 送信バイト数
17:22:03.845253 IP localhost.italk > localhost.61206 F. 6(1の時のack番号) 2(1の時のseq + 1) 9186 nop,nop,TS val 932053925 ecr 932053925 0
17:22:03.845253 IP localhost.italk > localhost.61206: Flags [F.], seq 6, ack 2, win 9186, options [nop,nop,TS val 932053925 ecr 932053925], length 0

3. クライアントがFINに対するACK返す

時刻(HH:MM:SS.マイクロ秒) 送信元 > 送信先 Flags: フラグ seq: シーケンス番号 ack: ACK 番号 win: ウィンドウサイズ options: TCPのオプション lengh: 送信バイト数
17:22:03.845277 IP localhost.61206 > localhost.italk . なし 7(2の時のseq + 1) 9186 nop,nop,TS val 932053925 ecr 932053925 0
17:22:03.845277 IP localhost.61206 > localhost.italk: Flags [.], ack 7, win 9186, options [nop,nop,TS val 932053925 ecr 932053925], length 0

その他

Flagsの定義

Flags are some combination of S (SYN), F (FIN), P (PUSH), R  (RST), U (URG), W (ECN CWR), E (ECN-Echo) or `.' (ACK), or `none' if no flags are set.

なので、S.はSYN + ACK .はACKのみ

TCPのオプション

  • mss : 最大セグメント長 Max-segment-size
  • wscale : ウィンドウスケール
  • sackOK : Selective Acknowledgmentが有効
  • TS val ecr : valはタイムスタンプ ecrはecho reply 参照 rfc7323
  • nop : パディング No operation provides padding around other options
  • eol : オプションリストの終わり

参考文献

2.6 Examining tcpdump Output

sackOK? - 酔いどれコード

TSOPT ‐ 通信用語の基礎知識

基礎から学ぶWindowsネットワーク:第16回 信頼性のある通信を実現するTCPプロトコル(3) (1/4) - @IT

ソケットインターフェースと3-way handshake - niwaka diary

Geekなぺーじ:TCPを使う

福岡でおすすめのモツ鍋のお店

おすすめ

  • もつ幸

もつ幸 (もつこう) - 呉服町/もつ鍋 [食べログ]

美味しかった

  • 博多 表邸

博多 表邸 (はかた ひょうてい) - 薬院大通/魚介料理・海鮮料理 [食べログ]

刺身、イカとかも豊富なので、福岡の旨いものをまとめて食べたい場合はオススメ

ハズレ無し

  • やま中

やま中 本店 (やまなか) - 大橋/もつ鍋 [食べログ]

  • おおいし

おおいし 住吉店 - 渡辺通/もつ鍋 [食べログ]

越後屋 博多駅前本店 (えちごや) - 博多/もつ鍋 [食べログ]

店舗数多いから割りと行きやすい。

  • もつ料理 幸 大名店

もつ料理 幸 大名店 (サチ) - 薬院大通/もつ鍋 [食べログ]

ていうか福岡でモツ鍋食べたらだいたいハズレはない

合わせて読みたい

福岡でおすすめの水炊きの店を教えてもらった - CubicLouve

2014年の振り返り

軽く振り返ってみる

1月 〜 3月

このときはまだ色々何をするか悩んでいた時期。

1月はまだperl書いてた。

2月位からunityを触り始めた。

初めてクライアント側の開発して、色々刺激になった。

(IDE使ってみたり、初めて静的型付け言語使ったりとかとか)

4月 〜 6月

ここはまだunity触ってた。

自分のセンスの無さに絶望していた時期。

3Dとかもういやだ。

7月 〜 9月

ここでサーバー側に戻ってきた。

サーバー側のほうがしっくり来たのを覚えている。

9月に結婚した。

10月 〜 12月

引き続きサーバー側をやっていた。

ここでちょこちょこクライアント側にも再度手を出し始めた。

外には出してないけどやったこと

  • 社内rubygems作った
  • 社内アプリ配信サービス作った
  • 社内アイコン生成サイト作った
  • 課金周りの実装
  • 社内向けgemはそこそこ作った

まとめ

色々チャレンジした一年ではあった。

うーーん、クライアント側が苦手なわけではなく、多分ゲームの面白さとかを考えるのがセンスないことがわかったのが収穫かな。

来年は、クライアント側でも、下回りを中心に勉強する予定。

スペシャリスト氏に色々教えてもらおう。

サーバー側は一旦卒業したい。(去年も同じこと言ってた。)

追記

来年はたなくじ忘れずに!

一年後のキミへ

身欠きにしんを29日に買って仕込んでおけ! それだけだ!

以下はただ2014年のおせち料理のメモ

年末まとまった時間がとれたので、おせち料理を自作してみた。

30日に買い出しを行った。

完成品はこちら

f:id:Spring_MT:20150101150409j:plain

松前漬

スルメイカ 3枚
昆布 スルメと同量くらい
人参 1/2本

たれ
酒 300cc
醤油(関東濃い口) 150cc
みりん 150cc

31日

  1. 酒 300cc、醤油 150cc、みりん 150ccを火にかけひと煮立ちさせて冷ましておく
  2. スルメイカ、昆布はそのままキッチンバサミで5mm幅程度に切っておく(ここは適当)
  3. 人参は千切りにしておく
  4. 上記を全部混ぜる
  5. 半日位で混ぜなおす
  6. 出来上がり

29日から仕込んでもよかった。 数の子を入れる場合は、塩漬けの数の子を塩抜き(半日)するか、生の買ってくる(生の場合は塩漬けにするが、塩付け1日くらいかかるので、直前で準備だとつらい)

黒豆

黒豆 250g(丹波の黒豆高かったから、普通の北海道産の黒豆にした)

煮汁
砂糖 170g
水 800c
醤油(薄口醤油) 大さじ 1
塩 小さじ半分

30日

  1. 黒豆を流水で洗う
  2. 煮汁を合わせておいて、沸騰させる

31日

  1. 沸騰したら火を止めて、すぐに黒豆を投入
  2. 一晩寝かせる
  3. 圧力鍋で20分火を入れる(今回は弱でかけてしまった)
  4. ちょっと味の浸透が弱かったので、1回沸騰させて、煮込んだ

美味しくできました。

田作り

田作り 50g

たれ 
みりん 大さじ2
砂糖 大さじ1
醤油(関東 濃い口) 大さじ1
酒 大さじ 1

31日

  1. 田作りをかりかりになるまで煎る
  2. タレを合わせておいて、上の田作りに入れて煮込む
  3. 照りがでてきたら火を止めて完成

田作りは煎ったあと、冷やすといいらしいが今回はできなかった。(知らなかった)

なます

大根 1/2本(細いのだった)  
人参 1/3本

たれ
米酢 100cc
砂糖 40cc
だし 100cc

31日

  1. 大根と人参を千切りにする
  2. 千切りにした大根と人参を塩を振って水出しする
  3. 水がでたら、よく絞る
  4. たれを混ぜて完了

色どり的に 大根 1: 人参 3くらいが良さそうだった。

お煮しめ

里芋 大きめ4個(予め買っておこう!年末高すぎ)
ごぼう 1/2本
人参 2/3本
こんにゃく 一枚
しいたけ 8個
たけのこ 穂先だけのを2つ

だし3カップ半

出汁味付け用調味料
醤油(薄口) 大さじ4
醤油(濃い口) 大さじ1
酒 大さじ3
砂糖 大さじ2
みりん 大さじ1
塩 小さじ1/2

人参につける出汁
だし カップ1
砂糖 小さじ1
塩 1つまみ

30日

  1. 里芋を洗わずに皮をむいて、洗って半分にして下茹で(沸騰したお湯に10分くらい 面取りすればよかった)
  2. しいたけを水でもどしておく
  3. 蓮根の皮むき、飾り切り、酢水(深皿に水入れて、お酢を垂らす程度)につけておく(一晩つけていた)

31日

  1. ごぼうの皮むきして、蓮根とごぼうを下茹で(10分位)
  2. 人参を飾り切りして、塩入れて下茹で(10分くらい)
  3. 人参の出汁を沸騰させて、粗熱をとっておく
  4. ゆでた人参を人参の出汁に浸けて冷蔵庫にいれておく
  5. だし3カップ半で人参ときぬさや以外の具材を10分炊く
  6. 出汁味付け用調味料を入れて更に15分炊く

絹さやがあったら、人参と同じように下茹でして使う

ニシンの昆布巻き(現在進行中)

若干の失敗

身欠きにしんの仕込みを当日にやっている状態

身欠きにしん 4本
日高昆布 6枚

31日

  1. 身欠きにしんを米と一緒に水につける
  2. イマココ

現在進行中

来年やること

透明なビニールのカップ買っておく

Faradayでnet/httpのアダプターを使っている場合のHTTPリクエスト/レスポンスを見る

忘れそうなのでメモっておく。

require 'faraday'
module FaradayDebug
  def net_http_connection(env)
    http = super
    http.set_debug_output $stderr
    http
  end
end


module Faraday
  class Adapter
    class NetHttp                                                                                                                                 
      prepend FaradayDebug
    end
  end
end

これを書いて実行すれば、HTTPリクエスト/レスポンスをダンプできた。

Objective-Cのintとlongの最大値は同じという記事をみて

よくわからんかったので試してみた。

#import <Foundation/NSObject.h>
#import <stdio.h>

int main(void)
{
  int i = INT_MAX;
  NSLog(@"int i: %d", i);
  i++;
  NSLog(@"int i: %d", i);

  long l = (long)INT_MAX;
  NSLog(@"long l: %ld", l);
  l++;
  NSLog(@"long l: %ld", l);

  long long ll = (long long)INT_MAX;
  NSLog(@"long long ll: %lld", ll);
  ll++;
  NSLog(@"longlong ll: %lld", ll);                                                                                                

  return 0;
}
% clang -o long_test LongTest.mm -framework Foundation
% ./long_test
2014-12-08 21:00:57.396 long_test[79790:507] int i: 2147483647
2014-12-08 21:00:57.403 long_test[79790:507] int i: -2147483648
2014-12-08 21:00:57.403 long_test[79790:507] long l: 2147483647
2014-12-08 21:00:57.404 long_test[79790:507] long l: 2147483648
2014-12-08 21:00:57.404 long_test[79790:507] long long ll: 2147483647
2014-12-08 21:00:57.404 long_test[79790:507] longlong ll: 2147483648

あれれってなったけど、コンパイルするときのアーキテクチャのデフォルト変わったんじゃないかと思って

% clang -v
Apple LLVM version 6.0 (clang-600.0.56) (based on LLVM 3.5svn)
Target: x86_64-apple-darwin13.3.0
Thread model: posix

64ビットやないか。。。

まあ、変わったんだよね、、きっと

32ビットでコンパイルしてみると、

% clang -o long_test LongTest.mm -framework Foundation -arch i386
./long_test
2014-12-08 21:04:29.950 long_test[79849:507] int i: 2147483647
2014-12-08 21:04:29.952 long_test[79849:507] int i: -2147483648
2014-12-08 21:04:29.952 long_test[79849:507] long l: 2147483647
2014-12-08 21:04:29.952 long_test[79849:507] long l: -2147483648
2014-12-08 21:04:29.953 long_test[79849:507] long long ll: 2147483647
2014-12-08 21:04:29.953 long_test[79849:507] longlong ll: 2147483648

オーバーフローしましたね。

まあ、iOS、64ビット化がデフォになるとはいえ、大きい数字使うなら、longじゃなくて、long longつかったほうが無難なんですかね。