Slide 1

Slide 1 text

NAOMASA MATSUBAYASHI ࡞ͬͯཧղ͢Δ WireGuard

Slide 2

Slide 2 text

͜͜ʹ8JSF(VBSEެࣜαΠτͷը૾ΛషΔ WireGuard®͸࠷ઌ୺ͷ҉߸Λ࢖ͬͯ࡞ΒΕͨۃΊͯγϯϓϧͳ͕Βߴ଎Ͱۙ୅తͳVPNͰ͢ɻ https://www.wireguard.com/ ৽͍͠-71/ͷख๏ -JOVYͱ͔Ͱ࢖͑Δ

Slide 3

Slide 3 text

WireGuard®͸࠷ઌ୺ͷ҉߸Λ࢖ͬͯ࡞ΒΕͨۃΊͯγϯϓϧͳ͕Βߴ଎Ͱۙ୅తͳVPNͰ͢ɻ ຊମ StrongSwan OpenSSL ߹ܭ WireGuard 26,130 ෆཁ ෆཁ 26,130 OpenVPN 111,612 ෆཁ 366,769 478,381 SoftEarther 422,714 ෆཁ 366,769 789,483 xl2tpd+IPSec 12,151 566,150 366,769 945,070 xfrm+IPSec 32,925 566,150 366,769 965,844 71/ͷ֤ख๏ͷ೥݄೔࣌఺ͷ ࠷৽ͷ҆ఆ൛ͷιʔείʔυͷߦ਺ ܻҰͭҧ͏

Slide 4

Slide 4 text

WireGuard®͸࠷ઌ୺ͷ҉߸Λ࢖ͬͯ࡞ΒΕͨۃΊͯγϯϓϧͳ͕Βߴ଎Ͱۙ୅తͳVPNͰ͢ɻ Curve25519ͷପԁۂઢDHʹΑΔೝূͱ伴ڞ༗ ύʔϑΣΫτϑΥϫʔυηΩϡϦςΟΛ༗͢ ରশ҉߸͸Chacha20-Poly1305 BLAKE2sΛ࢖ͬͨHKDFʹΑΔରশ҉߸ͷ伴ੜ੒ φ΢͍ φ΢͍ φ΢͍ φ΢͍ φ΢͍ φ΢͍

Slide 5

Slide 5 text

͜͜ʹ8JSF(VBSEͷ࿦จͷ 1FSGPSNBODFͷਤΛషΔ WireGuard®͸࠷ઌ୺ͷ҉߸Λ࢖ͬͯ࡞ΒΕͨۃΊͯγϯϓϧͳ͕Βߴ଎Ͱۙ୅తͳVPNͰ͢ɻ Donenfeld, J., WireGuard: next generation kernel network tunnel. In: 24th Annual Network and Distributed System Security Symposium, NDSS 2017, San Diego, California, USA (2017) ΑΓҾ༻ طଘͷख๏ͱൺֱͯ͠ ߴ͍εϧʔϓοτ ௿͍ϨΠςϯγ Whitepaper: https://www.wireguard.com/papers/wireguard.pdf

Slide 6

Slide 6 text

WireGuardΛ࢖ͬͯΈΑ͏

Slide 7

Slide 7 text

$ wget -q https://git.zx2c4.com/WireGuard/snapshot/ WireGuard-0.0.20180625.tar.xz $ tar xf WireGuard-0.0.20180625.tar.xz $ cd WireGuard-0.0.20180625/src/ $ make … LD [M] /usr/src/hoge/WireGuard-0.0.20180625/src/wireguard.o Building modules, stage 2. MODPOST 1 modules CC /usr/src/hoge/WireGuard-0.0.20180625/src/wireguard.mod.o LD [M] /usr/src/hoge/WireGuard-0.0.20180625/src/wireguard.ko … LD /usr/src/hoge/WireGuard-0.0.20180625/src/tools/wg # make install ΠϯετʔϧΨΠυhttps://www.wireguard.com/install/

Slide 8

Slide 8 text

LD [M] /usr/src/hoge/WireGuard-0.0.20180625/src/wireguard.o Building modules, stage 2. MODPOST 1 modules CC /usr/src/hoge/WireGuard-0.0.20180625/src/wireguard.mod.o LD [M] /usr/src/hoge/WireGuard-0.0.20180625/src/wireguard.ko … LD /usr/src/hoge/WireGuard-0.0.20180625/src/tools/wg # make install WireGuardʹϢʔβۭؒσʔϞϯ͸ͳ͍ શͯΧʔωϧۭؒͰॲཧ͞ΕΔ ΧʔωϧϞδϡʔϧ ΧʔωϧϞδϡʔϧʹioctl౤͛ͨΓ 伴ϖΞͭͬͨ͘Γ͢ΔϢʔβۭؒπʔϧ

Slide 9

Slide 9 text

WireGuardΛ࢖ͬͯΈΑ͏ $ wg genkey >private.key $ wg pubkey public.key $ cat private.key uMJnQnuscHiWTtIpMoDwVtOkoGgs4UQMRZaScCYPM1A= $ cat public.key kdOAXmxE4XwwoO+QbXLcTSRMp+TXfW8SOgW69DRURS0= $ vim wireguard.conf $ cat wireguard.conf [Interface] PrivateKey = uMJnQnuscHiWTtIpMoDwVtOkoGgs4UQMRZaScCYPM1A= ListenPort = 51820 [Peer] PublicKey = 3K0qbsP8IzGZaHmwAyxQ8z/gRla9rSbL17RoLQi6hAk= Endpoint = example.com:51820 AllowedIPs = 192.168.2.2/32 ൿີ伴ͱެ։伴Λ࡞Δ ର޲ͷϗετͷެ։伴 ࣗ෼ͷൿີ伴 ର޲ͷϗετͷΞυϨεͱϙʔτ ௨৴Λ଴ͪड͚Δϙʔτ

Slide 10

Slide 10 text

WireGuardΛ࢖ͬͯΈΑ͏ $ modprobe wireguard $ ip link add dev wg0 type wireguard $ ip address add dev wg0 192.168.2.1 peer 192.168.2.2 $ wg setconf wg0 wireguard.conf $ ip link set up dev wg0 ৽͍͠8JSF(VBSEσόΠεXHΛ࡞Δ ΞυϨεͱ伴Λ༩͑Δ σόΠεΛى͜͢ ͜ͷઃఆΛVPNΛுΔ྆ଆͷϗετͰߦ͏

Slide 11

Slide 11 text

$ ping -c 5 192.168.2.2 PING 192.168.2.2 (192.168.2.2) 56(84) bytes of data. 64 bytes from 192.168.2.2: icmp_seq=1 ttl=64 time=18.3 ms 64 bytes from 192.168.2.2: icmp_seq=2 ttl=64 time=8.64 ms 64 bytes from 192.168.2.2: icmp_seq=3 ttl=64 time=8.84 ms 64 bytes from 192.168.2.2: icmp_seq=4 ttl=64 time=8.80 ms 64 bytes from 192.168.2.2: icmp_seq=5 ttl=64 time=8.82 ms --- 192.168.2.2 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4007ms rtt min/avg/max/mdev = 8.644/10.698/18.378/3.841 ms VPN׬੒

Slide 12

Slide 12 text

port 11194 proto udp6 dev tap0 ca privnet/ca.crt cert privnet/server.crt key privnet/server.key dh privnet/dh.pem server-bridge 192.168.0.250 255.255.255.0 192.168.0.10 192.168.0.249 push "redirect-gateway def1” client-to-client keepalive 10 120 user nobody/ group nobody persist-key persist-tun status openvpn-status.log verb 3 link-mtu 1500 mssfix fragment 1280 cipher AES-256-GCM ncp-ciphers AES-256-GCM tls-version-min 1.2 tls-cipher TLS-ECDHE-ECDSA-WITH-AES-256-GCM-SHA384:TLS-ECDHE- RSA-WITH-AES-256-GCM-SHA384 reneg-sec 60 [Interface] PrivateKey = uMJnQnuscHiWTtIpMoDwVtOkoGgs4UQMRZaScCYPM1A= ListenPort = 51820 [Peer] PublicKey = 3K0qbsP8IzGZaHmwAyxQ8z/gRla9rSbL17RoLQi6hAk= Endpoint = example.com:51820 AllowedIPs = 192.168.2.2/32 ͳΜͯ؆୯ͳΜͰ͠ΐ͏ Α͋͘ΔOpenVPNͷઃఆ WireGuardͷઃఆ

Slide 13

Slide 13 text

ͦͷVPN͸ຊ౰ʹ҆શ͔

Slide 14

Slide 14 text

ୈࡾऀ͕௨৴Λݟ͍ͯͨͱͯ͠΋ ಺༰͕όϨͯ͸ͳΒͳ͍ ҉߸Խ

Slide 15

Slide 15 text

ϝοηʔδΛૹΔ૬ख͕ҙਤͨ͠૬खͰ͋ΔࣄΛ ֬ೝͰ͖ͳ͚Ε͹ͳΒͳ͍ ೝূ "MJDF #PCʹͳΓ͢·͢ ߈ܸऀ #PC

Slide 16

Slide 16 text

ड͚औͬͨϝοηʔδ͕ҙਤͨ͠૬ख͔Βͷ ΋ͷͰ͋ΔࣄΛ֬ೝͰ͖ͳ͚Ε͹ͳΒͳ͍ վ᜵ݕ஌ "MJDF "MJDFʹͳΓ͢·͢ ߈ܸऀ #PC

Slide 17

Slide 17 text

҉߸Խʹ࢖͏伴͸௨৴૬खҎ֎ʹόϨͳ͍Α͏ʹ ڞ༗͞Εͳ͚Ε͹ͳΒͳ͍ ౪ௌऀʹݟ͑ͳ͍伴ڞ༗

Slide 18

Slide 18 text

௕ظؒಉ͡伴͕࢖ΘΕΔͱ伴͕όϨΔՄೳੑ͕ߴ͘ͳΔ ҉߸Խʹ࢖͏伴͸ఆظతʹมߋ͞Εͳ͚Ε͹ͳΒͳ͍ 伴ͷϩʔςʔγϣϯ ΋͔ͯ͠͠:

Slide 19

Slide 19 text

ϗετͷূ໌ॻͷൿີ伴͕ޙ͔Β࿙Εͯ΋ ௨৴Λه࿥͍ͯͨ͠ୈࡾऀʹ಺༰͕όϨͯ͸ͳΒͳ͍ ύʔϑΣΫτϑΥϫʔυηΩϡϦςΟ ? ޙ೔

Slide 20

Slide 20 text

伴Λ஌Βͳ͍ୈࡾऀ͔ΒͷେྔͷΞΫηεʹΑͬͯ ༰қʹਖ਼نͷϢʔβ͕઀ଓͰ͖ͳ͍ঢ়ଶʹؕͬͯ͸ͳΒͳ͍ DoS߈ܸ଱ੑ

Slide 21

Slide 21 text

͜Ε͸҆શͳͷ͔ͳ Ͱ͔͗ͯ͢ Α͘Θ͔ΒΜ γϯϓϧͳख๏ Ҏ্ͷػೳ͸੬ऑੑ͕ແ͍ࣄΛݕূ͠΍͍͢Α͏ʹ Ͱ͖Δ͚ͩ؆ܿͳํ๏Ͱ࣮ݱ͞Ε͍ͯΔࣄ͕๬·͍͠

Slide 22

Slide 22 text

҉߸Խʹ࢖͏伴͸௨৴૬खҎ֎ʹόϨͳ͍Α͏ʹ ڞ༗͞Εͳ͚Ε͹ͳΒͳ͍ ϝοηʔδΛૹΔ૬ख͕ҙਤͨ͠૬खͰ͋ΔࣄΛ ֬ೝͰ͖ͳ͚Ε͹ͳΒͳ͍ 伴ڞ༗ʹ࢖ΘΕͨൿີ伴͕ޙ͔Β࿙Εͯ΋ ௨৴Λه࿥͍ͯͨ͠ୈࡾऀʹ಺༰͕όϨͯ͸ͳΒͳ͍ ͚ͩ͜͜ͳΒ੩తͳ伴Λ࢖͏Diffie-HellmanͰୡ੒Ͱ͖Δ ͚ͩ͜͜ͳΒҰ࣌తͳ伴Λ࢖͏Diffie-HellmanͰୡ੒Ͱ͖Δ 1ͭͷ伴ϖΞͰ͸3ͭͷ৚݅શͯΛຬͨ͢ࣄ͕Ͱ͖ͳ͍

Slide 23

Slide 23 text

ࢲ͸͜Μͳํ๏Ͱ 伴ڞ༗͕Ͱ͖·͢ ͜ͷํ๏Ͱ伴ڞ༗͠·͠ΐ͏ 伴ͷૉͰ͢ 伴ͷૉͰ͢ ͋ͳ͕ͨຊ෺ͳΒ ͜ΕΛ෮߸Ͱ͖ΔഺͰ͢ ͋ͳ͕ͨຊ෺ͳΒ ͜ΕΛ෮߸Ͱ͖ΔഺͰ͢ ڞ௨伴Λ खʹೖΕͨ ڞ௨伴Λ खʹೖΕͨ IPSec IKE Phase1ͷϋϯυγΣΠΫ Ұ࣌తͳ伴Λ࢖͏ ڞ௨伴ͱ ੩తͳ伴Λ࢖͏ ࢖༻͢Δ ҉߸ٕज़ΛܾΊΔ

Slide 24

Slide 24 text

͋ͳ͕ͨຊ෺ͳΒ ͜ΕΛ෮߸Ͱ͖ΔഺͰ͢ ੩తͳ伴Λ࢖͏ ͜ΜͳઃఆͰ௨৴Ͱ͖·͢ ͜ͷઃఆͰ௨৴͠·͠ΐ͏ Phase1ͷ ڞ௨伴Λ࢖͏ ڞ௨伴Λ खʹೖΕͨ ڞ௨伴Λ खʹೖΕͨ ͞ΒʹIKE Phase2Ͱ௨৴༻ͷڞ௨伴ͱ ௨৴ํ๏ͷબ୒͕ߦΘΕͯ Α͏΍͘ύέοτΛྲྀͤΔঢ়ଶʹͳΔ

Slide 25

Slide 25 text

͋ͳ͕ͨຊ෺ͳΒ ͜ΕΛ෮߸Ͱ͖ΔഺͰ͢ ੩తͳ伴Λ࢖͏ ͜ΜͳઃఆͰ௨৴Ͱ͖·͢ ͜ͷઃఆͰ௨৴͠·͠ΐ͏ Phase1ͷ ڞ௨伴Λ࢖͏ ڞ௨伴Λ खʹೖΕͨ ڞ௨伴Λ खʹೖΕͨ ϋϯυγΣΠΫ͕௕͍ͷͰ ୹࣌ؒͰRekey͢Δ৔߹͸͜ͷ෦෼͔Β΍Γ௚͢

Slide 26

Slide 26 text

Ҏ্ͷػೳ͸੬ऑੑ͕ແ͍ࣄΛݕূ͠΍͍͢Α͏ʹ Ͱ͖Δ͚ͩ؆ܿͳํ๏Ͱ࣮ݱ͞Ε͍ͯΔࣄ͕๬·͍͠ ௕ظؒಉ͡伴͕࢖ΘΕΔͱ伴͕όϨΔՄೳੑ͕ߴ͘ͳΔ ҉߸Խʹ࢖͏伴͸ఆظతʹมߋ͞Εͳ͚Ε͹ͳΒͳ͍ ͜ͷ2ͭΛಉ࣌ʹຬͨͨ͢Ίʹ͸ ϋϯυγΣΠΫΛ୹ͯ͘͠ ॳճͱ伴ͷϩʔςʔγϣϯͰηογϣϯ伴ΛಘΔखॱΛ ׬શʹಉ͡ʹ͍ͨ͠

Slide 27

Slide 27 text

ୡ੒͠ͳ͚Ε͹ͳΒͳ͍΋ͷ ௨৴ํ๏ɺ࢖༻͢Δ҉߸ٕज़ͷܾఆͱ ੩త伴Diffie-HellmanʹΑΔ௨৴૬खͷೝূͱ Ұ࣌伴Diffie-HellmanʹΑΔηογϣϯ伴ͷੜ੒Λ 1ԟ෮ͷ௨৴Ͱߦ͏

Slide 28

Slide 28 text

௨৴ํ๏ɺ࢖༻͢Δ҉߸ٕज़ͷܾఆͱ ੩త伴Diffie-HellmanʹΑΔ௨৴૬खͷೝূͱ Ұ࣌伴Diffie-HellmanʹΑΔηογϣϯ伴ͷੜ੒Λ 1ԟ෮ͷ௨৴Ͱߦ͏ ୡ੒͠ͳ͚Ε͹ͳΒͳ͍΋ͷ ࢖༻Ͱ͖Δ௨৴ํ๏ͱ҉߸ٕज़͕ 1छྨ͔͠ͳ͚Ε͹͜ͷ෦෼͸ෆཁ ͜ͷ෦෼ΛҰؾʹͰ͖Ε͹࣮ݱͰ͖Δ

Slide 29

Slide 29 text

1-RTTϋϯυγΣΠΫ΁ͷಓ

Slide 30

Slide 30 text

ఆ਺a ࣄલʹܾΊͨૉ਺c ఆ਺b ఆ਺ac ఆ਺bc abc abc ͸ac=f(a,c)ʹରͯ͠a=g(ac,c)ͱͳΔؔ਺g͕཭ࢄର਺໰୊ʹͳΔΑ͏ͳؔ਺ ূ໌ॻͱͯ͠ެ։ ࣄલ ௨৴࣌ ී௨ͷ੩త伴Diffie-Hellman伴ڞ༗ ,%' ,%'

Slide 31

Slide 31 text

͸xc=f(x,c)ʹରͯ͠x=g(xc,c)ͱͳΔؔ਺g͕཭ࢄର਺໰୊ʹͳΔΑ͏ͳؔ਺ ࣄલ ௨৴࣌ ී௨ͷҰ࣌伴Diffie-Hellman伴ڞ༗ ཚ਺x ࣄલʹܾΊͨૉ਺c ཚ਺y cx cy cxy cxy ,%' ,%'

Slide 32

Slide 32 text

୯७ʹ2ͭͷDiffie-HellmanΛߦ͏͚ͩͩͱ Ұ࣌伴Λѱҙ͋Δୈࡾऀʹॻ͖׵͑ΒΕΔ Aliceͷ੩త伴 AliceͷҰ࣌伴 Aliceͷ੩త伴 ୈࡾऀͷҰ࣌伴 Alice Bob ѱҙ͋Δୈࡾऀ

Slide 33

Slide 33 text

Noise Protocol Framework ఆ਺a ࣄલʹܾΊͨૉ਺c ఆ਺b ఆ਺ac ఆ਺bc cx cy ূ໌ॻͱͯ͠ެ։ ࣄલ ௨৴࣌ ཚ਺x ཚ਺y abc bcx acy cxy bcx cxy abc acy ,%' ,%'

Slide 34

Slide 34 text

ఆ਺a ࣄલʹܾΊͨૉ਺c ఆ਺b ఆ਺ac ఆ਺bc cx cy ূ໌ॻͱͯ͠ެ։ ࣄલ ௨৴࣌ ཚ਺x ཚ਺y abc bcx acy cxy bcx cxy abc acy ,%' ,%' ΦϨϯδͷ෦෼͸ WireGuardΛઃఆ͢Δࡍʹ৯΂ͤͨ͞ ϐΞͷެ։伴ʹ૬౰͢Δ ͭ·ΓVPNΛઃఆ͢Δஈ֊Ͱߦ͓ͬͯ͘෦෼ Noise Protocol Framework

Slide 35

Slide 35 text

ఆ਺a ࣄલʹܾΊͨૉ਺c ఆ਺b ఆ਺ac ఆ਺bc cx cy ূ໌ॻͱͯ͠ެ։ ࣄલ ௨৴࣌ ཚ਺x ཚ਺y abc bcx acy cxy bcx cxy abc acy ,%' ,%' ੨ͷ෦෼͸௨৴Λ։࢝͢Δࡍʹߦ͏ cxͱcyͷަ׵1౓͚ͩͳͷͰ1ԟ෮ͷ௨৴Ͱߦ͑Δ Noise Protocol Framework

Slide 36

Slide 36 text

ఆ਺a ࣄલʹܾΊͨૉ਺c ఆ਺b ఆ਺ac ఆ਺bc cx cy ূ໌ॻͱͯ͠ެ։ ࣄલ ௨৴࣌ ཚ਺x ཚ਺y abc bcx acy cxy bcx cxy abc acy ,%' ,%' 2ͭͷ伴ϖΞ͔Β4ͭͷ஋͕ڞ༗͞ΕΔ abc=੩త伴Diffie-Hellmanʹ૬౰ cxy=Ұ࣌伴Diffie-Hellmanʹ૬౰ Noise Protocol Framework

Slide 37

Slide 37 text

ఆ਺a ࣄલʹܾΊͨૉ਺c ఆ਺b ఆ਺ac ఆ਺bc cx cy ূ໌ॻͱͯ͠ެ։ ࣄલ ௨৴࣌ ཚ਺x ཚ਺y abc bcx acy cxy bcx cxy abc acy ,%' ,%' ڵຯਂ͍ಇ͖Λ͢Δͷ͕bcx Noise Protocol Framework

Slide 38

Slide 38 text

ఆ਺a ࣄલʹܾΊͨૉ਺c ఆ਺b ఆ਺ac ఆ਺bc cx cy ূ໌ॻͱͯ͠ެ։ ࣄલ ௨৴࣌ ཚ਺x ཚ਺y abc bcx acy cxy bcx cxy abc acy ,%' ,%' ఆ਺bΛ͍࣋ͬͯͳ͍ͱbcxΛ࡞Δ͜ͱ͕Ͱ͖ͳ͍ cxΛૹͬͯbcxΛབྷΊͨ伴Λ࡞ΕΔ΍ͭ͸ؒҧ͍ͳ͘bͷ࣋ͪओ Noise Protocol Framework

Slide 39

Slide 39 text

Noise Protocol Framework ఆ਺a ࣄલʹܾΊͨૉ਺c ఆ਺b ఆ਺ac ఆ਺bc cx cy ূ໌ॻͱͯ͠ެ։ ࣄલ ௨৴࣌ ཚ਺x ཚ਺y abc bcx acy cxy bcx cxy abc acy ,%' ,%' aͷओͱbͷओ͚͕ͩڞ༗Ͱ͖Δ஋ ͨͩ͠aͱb͸ޙ͔ΒόϨΔՄೳੑ͕͋Δ xͷओͱyͷओ͚͕ͩڞ༗Ͱ͖Δ஋ ͦΕ͕ҙਤͨ͠௨৴૬ख͔͸Θ͔Βͳ͍ xͷओͱbͷओ͚͕ͩڞ༗Ͱ͖Δ஋ yͷओͱaͷओ͚͕ͩڞ༗Ͱ͖Δ஋ 4ͭͷ஋શͯΛڞ༗Ͱ͖ΔͳΒ͹ aͷओ=xͷओ ͔ͭ bͷओ=yͷओ

Slide 40

Slide 40 text

"MJDF #PC ࠓAlice͕Bobʹରͯ͠ WireGuardͷηογϣϯ։࢝ͷཁٻΛ౤͛Α͏ͱ͍ͯ͠Δͱ͢Δ ಧ͚͍ͨύέοτ͕͋Δ ηογϣϯΛ։͍࢝ͨ͠ͳ

Slide 41

Slide 41 text

Alice͸ cx ͱ bcx͔Β࡞ͬͨ伴Ͱ҉߸Խͨࣗ͠਎ͷެ։伴ac ΛBobʹૹ৴ Bob͸ bcxΛٻΊͯAlice͔ΒૹΒΕ͖ͯͨެ։伴acΛ෮߸͠ Aliceͷ੩తެ։伴ͱ߹͏ࣄΛ֬ೝ͔ͯ͠Βabc acy cxyΛٻΊΔ cy ͱ 4ͭͷ஋͔Β࡞ͬͨ伴Ͱ҉߸Խۭͨ͠จࣈྻ ΛAliceʹૹ৴ 4ͭͷ஋͔Β࡞ͬͨ伴͔Βૹ৴伴ͱड৴伴Λ࡞Δ Alice͸ abc acy cxyΛٻΊΔ 4ͭͷ஋ͰBob͔ΒૹΒΕ͖ۭͯͨจࣈྻΛ෮߸Ͱ͖ΔࣄΛ֬ೝ 4ͭͷ஋͔Β࡞ͬͨ伴͔Βૹ৴伴ͱड৴伴Λ࡞Δ

Slide 42

Slide 42 text

Initiator Hello 0x01 (1όΠτ) Reserved (3όΠτ) ૹ৴ऀID (4όΠτ) Alice͕ηογϣϯ͝ͱʹϢχʔΫͳ஋Λࢦఆ͢Δ AliceͷҰ࣌తެ։伴 (cx) (32όΠτ) Aliceͷ੩తެ։伴ΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (32όΠτ+16όΠτ) TAI64NͰද͞Εͨݱࡏ࣌ࠁΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (12όΠτ+16όΠτ) mac1 (16όΠτ) mac2 (16όΠτ)

Slide 43

Slide 43 text

Initiator Hello 0x01 (1όΠτ) Reserved (3όΠτ) ૹ৴ऀID (4όΠτ) Alice͕ηογϣϯ͝ͱʹϢχʔΫͳ஋Λࢦఆ͢Δ AliceͷҰ࣌తެ։伴 (cx) (32όΠτ) Aliceͷ੩తެ։伴ΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (32όΠτ+16όΠτ) TAI64NͰද͞Εͨݱࡏ࣌ࠁΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (12όΠτ+16όΠτ) mac1 (16όΠτ) mac2 (16όΠτ) ͜ͷϋϯυγΣΠΫཁٻʹର͢Δฦ౴΍ ηογϣϯཱ֬ޙʹBob͔ΒૹΒΕͯ͘Δύέοτ͸ ͜͜Ͱࢦఆͨ͠IDѼʹૹΒΕͯ͘Δ

Slide 44

Slide 44 text

Initiator Hello 0x01 (1όΠτ) Reserved (3όΠτ) ૹ৴ऀID (4όΠτ) Alice͕ηογϣϯ͝ͱʹϢχʔΫͳ஋Λࢦఆ͢Δ AliceͷҰ࣌తެ։伴 (cx) (32όΠτ) Aliceͷ੩తެ։伴ΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (32όΠτ+16όΠτ) TAI64NͰද͞Εͨݱࡏ࣌ࠁΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (12όΠτ+16όΠτ) mac1 (16όΠτ) mac2 (16όΠτ) Alice͕௨৴Λ։࢝͢Δͱ͖ʹ ཚ਺Λൿີ伴ͱͯ͠࡞ͬͨެ։伴 Diffie-HellmanͰ௨৴ʹ৐Δ஋͸ୈࡾऀʹݟ͑ͯ΋ྑ͍ҝ ͜ͷ஋͸҉߸Խ͞ΕͣʹૹΒΕΔ

Slide 45

Slide 45 text

Initiator Hello 0x01 (1όΠτ) Reserved (3όΠτ) ૹ৴ऀID (4όΠτ) Alice͕ηογϣϯ͝ͱʹϢχʔΫͳ஋Λࢦఆ͢Δ AliceͷҰ࣌తެ։伴 (cx) (32όΠτ) Aliceͷ੩తެ։伴ΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (32όΠτ+16όΠτ) TAI64NͰද͞Εͨݱࡏ࣌ࠁΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (12όΠτ+16όΠτ) mac1 (16όΠτ) mac2 (16όΠτ) Bobͷ੩తެ։伴ͱAliceͷҰ࣌తൿີ伴Λֻ͚ͯ࡞ͬͨ伴(bcx)Ͱ Aliceͷ੩తެ։伴Λ҉߸Խͯ͠BobʹૹΔ

Slide 46

Slide 46 text

Initiator Hello 0x01 (1όΠτ) Reserved (3όΠτ) ૹ৴ऀID (4όΠτ) Alice͕ηογϣϯ͝ͱʹϢχʔΫͳ஋Λࢦఆ͢Δ AliceͷҰ࣌తެ։伴 (cx) (32όΠτ) Aliceͷ੩తެ։伴ΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (32όΠτ+16όΠτ) TAI64NͰද͞Εͨݱࡏ࣌ࠁΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (12όΠτ+16όΠτ) mac1 (16όΠτ) mac2 (16όΠτ) Aliceͷ੩తൿີ伴ͱBobͷ੩తެ։伴Λֻ͚ͯ࡞ͬͨ伴Ͱ λΠϜελϯϓΛ҉߸Խͯ͠BobʹૹΔ Bob͸ૹΒΕ͖ͯͨཁٻͷλΠϜελϯϓ͕ աڈʹAlice͔Βड͚औͬͨࣄ͕͋ΔλΠϜελϯϓҎԼͷ৔߹ ཁٻΛແࢹ͢Δ (ϋϯυγΣΠΫ࣌ͷϦϓϨΠ߈ܸͷճආ) λΠϜελϯϓ͸୯ௐ૿Ճ͍ͯ͠Ε͹ྑ͘ ਖ਼֬ͳ࣌ؒΛද͍ͯ͠Δඞཁ͸ͳ͍

Slide 47

Slide 47 text

Initiator Hello 0x01 (1όΠτ) Reserved (3όΠτ) ૹ৴ऀID (4όΠτ) Alice͕ηογϣϯ͝ͱʹϢχʔΫͳ஋Λࢦఆ͢Δ AliceͷҰ࣌తެ։伴 (cx) (32όΠτ) Aliceͷ੩తެ։伴ΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (32όΠτ+16όΠτ) TAI64NͰද͞Εͨݱࡏ࣌ࠁΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (12όΠτ+16όΠτ) mac1 (16όΠτ) mac2 (16όΠτ) WireGuardʹରͯ͠ෛՙΛ͔͚Δछྨͷ߈ܸΛ ճආ͢ΔͨΊͷ΋ͷ ৄࡉ͸ޙड़

Slide 48

Slide 48 text

C := HASH( “Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s" ); H := HASH( C ∥ "WireGuard v1 zx2c4 [email protected]" ); H := HASH( H ∥ Bobͷ੩తެ։伴 ); AliceͷҰ࣌తൿີ伴ɺҰ࣌తެ։伴ͷϖΞΛ࡞੒; C := KDF( C, AliceͷҰ࣌తެ։伴 ); H := HASH( H ∥ AliceͷҰ࣌తެ։伴 ); ( C, AEADͷ伴 ) := KDF( C, DH( AliceͷҰ࣌తൿີ伴, Bobͷ੩తެ։伴 )); ҉߸Խ͞ΕͨAliceͷ੩తެ։伴 := AEAD_ENC( AEADͷ伴, 0, Aliceͷ੩తެ։伴, H ); H := HASH( H ∥ ҉߸Խ͞ΕͨAliceͷ੩తެ։伴 ); ( C, AEADͷ伴 ) := KDF( C, DH( Aliceͷ੩తൿີ伴, Bobͷ੩తެ։伴 ) ); ҉߸Խ͞Εͨݱࡏ࣌ࠁ := AEAD_ENC( AEADͷ伴, 0, ݱࡏ࣌ࠁ, H ); H := HASH( H ∥ ҉߸Խ͞Εͨݱࡏ࣌ࠁ ); InitiatorHello( ++ηογϣϯID, AliceͷҰ࣌తެ։伴, ҉߸Խͨ͠Aliceͷ੩తެ։伴, ҉߸Խ͞Εͨݱࡏ࣌ࠁ ); bcx abc Alice͕InitiatorHelloΛ࡞Δखॱ

Slide 49

Slide 49 text

C := HASH( “Noise_IKpsk2_25519_ChaChaPoly_BLAKE2s" ); H := HASH( C ∥ "WireGuard v1 zx2c4 [email protected]" ); H := HASH( H ∥ Bobͷ੩తެ։伴 ); C := KDF( C, ૹΒΕ͖ͯͨҰ࣌తެ։伴 ); H := HASH( H ∥ ૹΒΕ͖ͯͨҰ࣌తެ։伴 ); ( C, AEADͷ伴 ) := KDF( C, DH( Bobͷ੩తൿີ伴, ૹΒΕ͖ͯͨҰ࣌తެ։伴 )); Aliceͷ੩తެ։伴 := AEAD_DEC( AEADͷ伴, 0, ૹΒΕ͖ͯͨ҉߸Խ͞Εͨ੩తެ։伴, H ); Aliceͷ੩తެ։伴͕Peerͷઃఆʹଘࡏ͢ΔࣄΛ֬ೝ; H := HASH( H ∥ ૹΒΕ͖ͯͨ҉߸Խ͞Εͨ੩తެ։伴 ); ( C, AEADͷ伴 ) := KDF( C, DH( Bobͷ੩తൿີ伴, Aliceͷ੩తެ։伴 ) ); ݱࡏ࣌ࠁ := AEAD_DEC( AEADͷ伴, 0, ҉߸Խ͞Εͨݱࡏ࣌ࠁ, H ); ݱࡏ࣌ࠁ͕աڈʹAlice͔Βड͚औͬͨݱࡏ࣌ࠁͷ࠷େ஋ΑΓେ͖͍ࣄΛ֬ೝ; H := HASH( H ∥ ҉߸Խ͞Εͨݱࡏ࣌ࠁ ); bcx abc InitiatorHelloΛड͚औͬͨBob͕CͱHΛಉظ͢Δखॱ

Slide 50

Slide 50 text

Responder Hello 0x02 (1όΠτ) Reserved (3όΠτ) ड৴ऀID (4όΠτ) Bob͕ηογϣϯ͝ͱʹϢχʔΫͳ஋Λࢦఆ͢Δ ૹ৴ऀID (4όΠτ) Alice͕ࢦఆ͖ͯͨ͠ηογϣϯ͝ͱʹϢχʔΫͳ஋ BobͷҰ࣌తެ։伴 (cy) (32όΠτ) ۭจࣈྻΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (16όΠτ) mac1 (16όΠτ) mac2 (16όΠτ)

Slide 51

Slide 51 text

Responder Hello 0x02 (1όΠτ) Reserved (3όΠτ) ड৴ऀID (4όΠτ) Bob͕ηογϣϯ͝ͱʹϢχʔΫͳ஋Λࢦఆ͢Δ ૹ৴ऀID (4όΠτ) Alice͕ࢦఆ͖ͯͨ͠ηογϣϯ͝ͱʹϢχʔΫͳ஋ BobͷҰ࣌తެ։伴 (cy) (32όΠτ) ۭจࣈྻΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (16όΠτ) mac1 (16όΠτ) mac2 (16όΠτ) ηογϣϯཱ֬ޙʹAlice͔ΒૹΒΕͯ͘Δύέοτ͸ ͜͜Ͱࢦఆͨ͠IDѼʹૹΒΕͯ͘Δ

Slide 52

Slide 52 text

Responder Hello 0x02 (1όΠτ) Reserved (3όΠτ) ड৴ऀID (4όΠτ) Bob͕ηογϣϯ͝ͱʹϢχʔΫͳ஋Λࢦఆ͢Δ ૹ৴ऀID (4όΠτ) Alice͕ࢦఆ͖ͯͨ͠ηογϣϯ͝ͱʹϢχʔΫͳ஋ BobͷҰ࣌తެ։伴 (cy) (32όΠτ) ۭจࣈྻΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (16όΠτ) mac1 (16όΠτ) mac2 (16όΠτ) ͜ͷϨεϙϯεΛड͚औͬͨAlice͸ ͜ͷ஋ΛݟΔࣄͰͲͷInitiator Helloʹର͢Δ ฦ౴͕ฦ͖ͬͯͨͷ͔ΛࣝผͰ͖Δ

Slide 53

Slide 53 text

Responder Hello 0x02 (1όΠτ) Reserved (3όΠτ) ड৴ऀID (4όΠτ) Bob͕ηογϣϯ͝ͱʹϢχʔΫͳ஋Λࢦఆ͢Δ ૹ৴ऀID (4όΠτ) Alice͕ࢦఆ͖ͯͨ͠ηογϣϯ͝ͱʹϢχʔΫͳ஋ BobͷҰ࣌తެ։伴 (cy) (32όΠτ) ۭจࣈྻΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (16όΠτ) mac1 (16όΠτ) mac2 (16όΠτ) Bob͕Alice͔ΒInitiator HelloΛड͚औͬͨͱ͖ʹ ཚ਺Λൿີ伴ͱͯ͠࡞ͬͨެ։伴 Diffie-HellmanͰ௨৴ʹ৐Δ஋͸ୈࡾऀʹݟ͑ͯ΋ྑ͍ҝ ͜ͷ஋͸҉߸Խ͞ΕͣʹૹΒΕΔ

Slide 54

Slide 54 text

Responder Hello 0x02 (1όΠτ) Reserved (3όΠτ) ड৴ऀID (4όΠτ) Bob͕ηογϣϯ͝ͱʹϢχʔΫͳ஋Λࢦఆ͢Δ ૹ৴ऀID (4όΠτ) Alice͕ࢦఆ͖ͯͨ͠ηογϣϯ͝ͱʹϢχʔΫͳ஋ BobͷҰ࣌తެ։伴 (cy) (32όΠτ) ۭจࣈྻΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (16όΠτ) mac1 (16όΠτ) mac2 (16όΠτ) Initiator helloΛड͚औͬͨ࣌఺ͰBob͸ҎԼͷ伴Λ஌͍ͬͯΔ Aliceͷ੩తެ։伴(ac) AliceͷҰ࣌తެ։伴(cx) Bobͷ੩తൿີ伴(b) BobͷҰ࣌తൿີ伴(y) ͜ΕΒ4ͭͷ஋Ͱ࡞ͬͨ伴ͰۭจࣈྻΛ҉߸Խͯ͠BobʹૹΔ ͜ΕΒͷ伴Λ࢖ͬͯ4ͭͷ஋ abc acy bcx cxy ΛٻΊΔ͜ͱ͕Ͱ͖Δ

Slide 55

Slide 55 text

Responder Hello 0x02 (1όΠτ) Reserved (3όΠτ) ड৴ऀID (4όΠτ) Bob͕ηογϣϯ͝ͱʹϢχʔΫͳ஋Λࢦఆ͢Δ ૹ৴ऀID (4όΠτ) Alice͕ࢦఆ͖ͯͨ͠ηογϣϯ͝ͱʹϢχʔΫͳ஋ BobͷҰ࣌తެ։伴 (cy) (32όΠτ) ۭจࣈྻΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (16όΠτ) mac1 (16όΠτ) mac2 (16όΠτ) Responder helloΛड͚औͬͨ࣌఺ͰAlice͸ҎԼͷ伴Λ஌͍ͬͯΔ Bobͷ੩తެ։伴(bc) BobͷҰ࣌తެ։伴(cy) Aliceͷ੩తൿີ伴(a) AliceͷҰ࣌తൿີ伴(x) Chacha20-Poly1305͸ೝূ෇͖҉߸ͳͷͰฏจ͕ۭจࣈྻͰ΋ 伴͕Ұக͠ͳ͍ͱ෮߸͸ࣦഊ͢Δ ͜ΕΒͷ伴Λ࢖ͬͯ4ͭͷ஋ abc acy bcx cxy ΛٻΊΔ͜ͱ͕Ͱ͖Δ

Slide 56

Slide 56 text

Responder Hello 0x02 (1όΠτ) Reserved (3όΠτ) ड৴ऀID (4όΠτ) Bob͕ηογϣϯ͝ͱʹϢχʔΫͳ஋Λࢦఆ͢Δ ૹ৴ऀID (4όΠτ) Alice͕ࢦఆ͖ͯͨ͠ηογϣϯ͝ͱʹϢχʔΫͳ஋ BobͷҰ࣌తެ։伴 (cy) (32όΠτ) ۭจࣈྻΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (16όΠτ) mac1 (16όΠτ) mac2 (16όΠτ) WireGuardʹରͯ͠ෛՙΛ͔͚Δछྨͷ߈ܸΛ ճආ͢ΔͨΊͷ΋ͷ ৄࡉ͸ޙड़

Slide 57

Slide 57 text

BobͷҰ࣌తൿີ伴ɺҰ࣌తެ։伴ͷϖΞΛ࡞੒; C := KDF( C, BobͷҰ࣌తެ։伴 ); H := HASH( H ∥ BobͷҰ࣌తެ։伴 ); C := KDF( C, DH( BobͷҰ࣌తൿີ伴, AliceͷҰ࣌ެ։伴 )); C := KDF( C, DH( BobͷҰ࣌తൿີ伴, Aliceͷ੩తެ։伴 )); ( C, t, AEADͷ伴 ) := KDF( C, PSK ); H := HASH( H ∥ t ); ҉߸Խ͞Εۭͨจࣈྻ := AEAD_ENC( AEADͷ伴, 0, "", H ); H := HASH( H ∥ ҉߸Խ͞Εۭͨจࣈྻ ); ResponderHello( ++ηογϣϯID, BobͷҰ࣌తެ։伴, ҉߸Խۭͨ͠จࣈྻ ); cxy acy Bob͕ResponderHelloΛ࡞Δखॱ ࣄલʹڞ༗ͨ͠ύεϫʔυ͕͋Δ৔߹ ͜͜ʹಥͬࠐΉ

Slide 58

Slide 58 text

C := KDF( C, BobͷҰ࣌తެ։伴 ); H := HASH( H ∥ BobͷҰ࣌తެ։伴 ); C := KDF( C, DH( AliceͷҰ࣌తൿີ伴, BobͷҰ࣌ެ։伴 )); C := KDF( C, DH( Aliceͷ੩తൿີ伴, BobͷҰ࣌ެ։伴 )); ( C, t, AEADͷ伴 ) := KDF( C, PSK ); H := HASH( H ∥ t ); ҉߸Խ͞Εۭͨจࣈྻ := AEAD_DEC( AEADͷ伴, 0, ૹΒΕ͖ͯͨ҉߸Խ͞Εۭͨจࣈྻ, H ); H := HASH( H ∥ ҉߸Խ͞Εۭͨจࣈྻ ); cxy acy ResponderHelloΛड͚औͬͨBob͕CͱHΛಉظ͢Δखॱ ͜ͷ࣌఺ͰAliceͱBobͷC͸ಉ͡஋ʹͳΔ ࣄલʹڞ༗ͨ͠ύεϫʔυ͕͋Δ৔߹ ͜͜ʹಥͬࠐΉ ( Alice͕ύέοτͷૹ৴ʹ࢖͏伴, Bob͕ύέοτͷૹ৴ʹ࢖͏伴 ) = KDF( C, "" ); ͋ͱ͸C͔Βύέοτͷ҉߸Խʹ࢖͏伴Λ࡞Δ

Slide 59

Slide 59 text

ύέοτΛૹΖ͏

Slide 60

Slide 60 text

Transport Data 0x04 (1όΠτ) Reserved (3όΠτ) ड৴ऀID (4όΠτ) ύέοτΛड͚औΔଆ͕Ͳͷηογϣϯͷύέοτͳͷ͔Λࣝผ͢Δҝͷ஋ Χ΢ϯλ (8όΠτ) ಉҰηογϣϯͰύέοτΛ1ݸૹ৴͢Δͨͼʹ1ͮͭ૿͍͑ͯ͘஋ ύέοτΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (҉߸Խલͷύέοτ௕+16όΠτ)

Slide 61

Slide 61 text

Transport Data 0x04 (1όΠτ) Reserved (3όΠτ) ड৴ऀID (4όΠτ) ύέοτΛड͚औΔଆ͕Ͳͷηογϣϯͷύέοτͳͷ͔Λࣝผ͢Δҝͷ஋ Χ΢ϯλ (8όΠτ) ಉҰηογϣϯͰύέοτΛ1ݸૹ৴͢Δͨͼʹ1ͮͭ૿͍͑ͯ͘஋ ύέοτΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (҉߸Խલͷύέοτ௕+16όΠτ) ϋϯυγΣΠΫ࣌ʹ૬खʹૹͬͨηογϣϯΛࣝผ͢Δ஋ ड৴ଆ͸͜ͷ஋Λݟͯ Ͳͷڞ༗伴Λ࢖ͬͯ෮߸͢Ε͹ྑ͍͔Λ஌Δ

Slide 62

Slide 62 text

Transport Data 0x04 (1όΠτ) Reserved (3όΠτ) ड৴ऀID (4όΠτ) ύέοτΛड͚औΔଆ͕Ͳͷηογϣϯͷύέοτͳͷ͔Λࣝผ͢Δҝͷ஋ Χ΢ϯλ (8όΠτ) ಉҰηογϣϯͰύέοτΛ1ݸૹ৴͢Δͨͼʹ1ͮͭ૿͍͑ͯ͘஋ ύέοτΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (҉߸Խલͷύέοτ௕+16όΠτ) ύέοτΛ Chacha20-Poly1305Ͱ҉߸Խ͢Δࡍʹ࢖ͬͨΧ΢ϯλͷ஋

Slide 63

Slide 63 text

Transport Data 0x04 (1όΠτ) Reserved (3όΠτ) ड৴ऀID (4όΠτ) ύέοτΛड͚औΔଆ͕Ͳͷηογϣϯͷύέοτͳͷ͔Λࣝผ͢Δҝͷ஋ Χ΢ϯλ (8όΠτ) ಉҰηογϣϯͰύέοτΛ1ݸૹ৴͢Δͨͼʹ1ͮͭ૿͍͑ͯ͘஋ ύέοτΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (҉߸Խલͷύέοτ௕+16όΠτ) Chacha20-Poly1305Ͱ҉߸Խ͞Εͨύέοτຊମ WireGuardͷMTU͸Transport Dataͷύέοτͷશ௕͕ ҉߸Խ͞ΕͨύέοτΛૹΔ௨৴࿏ͷMTUΛ௒͑ͳ͍஋ʹ͢Δ

Slide 64

Slide 64 text

ύέοτ௕͕ฏจͷঢ়ଶͰ16όΠτͷ੔਺ഒʹͳ͍ͬͯͳ͍৔߹ ύσΟϯάΛ௥Ճͯ͠16όΠτͷ੔਺ഒʹ͢Δ ݩͷύέοτͷ௕͕͞Θ͔ΒΜ! 4500 001f c6a1 0000 4001 2ce9 c0a8 0301 c0a8 0302 0000 9c37 61c2 0005 0001 02 00 0000 0000 + ҉߸Խ 237a a852 4cce a5a5 5dcc b2ee 0f82 1abc 4a02 5301 2551 56fc 7b7a e660 40a7 178b d460 5aff… ෮߸ 4500 001f c6a1 0000 4001 2ce9 c0a8 0301 c0a8 0302 0000 9c37 61c2 0005 0001 0200 0000 0000 TransportDataʹ͸ݩͷύέοτͷ௕͞͸ॻ͔Ε͍ͯͳ͍

Slide 65

Slide 65 text

4500 001f c6a1 0000 4001 2ce9 c0a8 0301 c0a8 0302 0000 9c37 61c2 0005 0001 02 00 0000 0000 + ҉߸Խ 237a a852 4cce a5a5 5dcc b2ee 0f82 1abc 4a02 5301 2551 56fc 7b7a e660 40a7 178b d460 5aff… ෮߸ 4500 001f c6a1 0000 4001 2ce9 c0a8 0301 c0a8 0302 0000 9c37 61c2 0005 0001 0200 0000 0000 4500 001f c6a1 0000 4001 2ce9 c0a8 0301 c0a8 0302 ෮߸ͨ͠ύέοτͷઌ಄ʹ͋Δͷ͸*1ϔομ *1ϔομͷόΠτ໨ʹ͋Δͷ͸ ύέοτͷશ௕ 8JSF(VBSE͸ΧϓηϧԽͨ͠ύέοτͷத͔Β ύέοτ௕ΛऔΓग़ͯ͠ύσΟϯάΛ෼཭͢Δ

Slide 66

Slide 66 text

伴Λϩʔςʔτ͠Α͏

Slide 67

Slide 67 text

"MJDF #PC *OJUJBUPS )FMMP 3FTQPOEFS )FMMP 5SBOTQPSU %BUB 5SBOTQPSU %BUB 5SBOTQPSU %BUB *OJUJBUPS )FMMP 3FTQPOEFS )FMMP Alice͸120ඵຖʹInitiatorHelloΛ΍Γ௚͢

Slide 68

Slide 68 text

"MJDF #PC *OJUJBUPS )FMMP 3FTQPOEFS )FMMP 5SBOTQPSU %BUB 5SBOTQPSU %BUB 5SBOTQPSU %BUB 5SBOTQPSU %BUB *OJUJBUPS )FMMP 3FTQPOEFS )FMMP 5SBOTQPSU %BUB 180ඵܦաͨ͠ηογϣϯ伴͸ഁغ͢Δ ৽͍͠InitiatorHelloͷޙ΋1ͭલͷ伴͕60ඵ΄Ͳੜ͖͍ͯΔͷͰ 伴ڞ༗ͷ׬ྃΛ଴ͨͣʹσʔλΛૹΓଓ͚Δ͜ͱ͕Ͱ͖Δ

Slide 69

Slide 69 text

ϦϓϨΠ߈ܸʹඋ͑Δ

Slide 70

Slide 70 text

"MJDF #PC ͋ ͋ ѱҙ͋Δୈࡾऀ͕Alice͕ૹͬͨύέοτΛ ͦͷ··BobʹૹΔͱBob͸ͦΕΛ෮߸Ͱ͖ͯ͠·͏ "MJDFʹͳΓ͢·͢ ߈ܸऀ ͋͋

Slide 71

Slide 71 text

"MJDF #PC ͋ ͋ ͜ΕΛ๷͙ʹ͸աڈʹड͚औͬͨࣄ͕͋ΔΧ΢ϯλͷ ࠷େ஋ΛԼճΔΧ΢ϯλͷϝοηʔδΛແࢹ͢Ε͹ྑ͍ "MJDFʹͳΓ͢·͢ ߈ܸऀ ͋ 1ͷύέοτ͸ ΋͏ड͚औ͔ͬͨΒ ͬͪ͜͸ِ෺͔ ͕

Slide 72

Slide 72 text

"MJDF #PC ͋ ͍ ͏ ͑ ͓ ͋ ͏ ͓ ͍ WireGuardͷϝοηʔδ͸UDPͰૹΒΕΔҝ ϝοηʔδ͸ॱং͕มΘͬͨΓແ͘ͳͬͨΓ͢Δ ͜ͷύέοτ͕ ٘ਜ਼ʹͳΔ

Slide 73

Slide 73 text

RFC6479 IPsec Anti-Replay Algorithm without Bit Shifting IPSec΋ಉ͡໰୊Λ๊͍͑ͯΔҝ ͜͏ͨ͠߈ܸΛճආ͢Δҝͷ֦ு͕RFCʹͳ͍ͬͯΔ WireGuard΋ಉ͡ํ๏ͰϦϓϨΠ߈ܸΛճආ͢Δ

Slide 74

Slide 74 text

RFC6479 IPsec Anti-Replay Algorithm without Bit Shifting ࡁ ࡁ ະ ະ ࡁ ະ ະ ະ ࡁ ະ ະ ະ ະ ະ ະ ະ ط஌ͷ࠷৽ ϦϯάόοϑΝΛ࢖ͬͯ ड͚औͬͨ͜ͱ͕͋ΔΧ΢ϯλͷ஋ͷ࠷େ஋पลͷ ஋ͷड͚औΓঢ়گΛ͓֮͑ͯ͘ গʑॱ൪͕ೖΕସΘͬͯಧ͍ͯ΋ ॏෳ͢Δύέοτ͚ͩΛ஄͘͜ͱ͕Ͱ͖Δ

Slide 75

Slide 75 text

RFC6479 IPsec Anti-Replay Algorithm without Bit Shifting ར఺ ड͚औͬͨશͯͷύέοτͷΧ΢ϯλΛ͓֮͑ͯ͘͜ͱͳ͘ ॱ൪͕ೖΕସΘΔՄೳੑ͕͋Δύέοτͷྻ͔Β ॏෳ͢ΔύέοτΛݟ͚ͭग़͢͜ͱ͕Ͱ͖Δ ܽ఺ ύέοτͷॱ൪͕߽շʹೖΕସΘ͍ͬͯΔͱ ࣮ࡍʹ͸ॏෳ͕ͳ͔ͬͨͱͯ͠΋ ड͚औΓΛڋ൱͞ΕΔύέοτ͕ੜ͡Δ

Slide 76

Slide 76 text

DoS߈ܸΛ͔Θͤ

Slide 77

Slide 77 text

Alice͸ cx ͱ bcx͔Β࡞ͬͨ伴Ͱ҉߸Խͨࣗ͠਎ͷެ։伴 ΛBobʹૹ৴ Bob͸ bcxΛٻΊͯAlice͔ΒૹΒΕ͖ͯͨެ։伴Λ෮߸͠ Aliceͷ੩తެ։伴ͱ߹͏ࣄΛ֬ೝ͔ͯ͠Βabc acy cxyΛٻΊΔ cy ͱ 4ͭͷ஋͔Β࡞ͬͨ伴Ͱ҉߸Խۭͨ͠จࣈྻ ΛAliceʹૹ৴ 4ͭͷ஋͔Β࡞ͬͨ伴͔Βૹ৴伴ͱड৴伴Λ࡞Δ Alice͸ abc acy cxyΛٻΊΔ 4ͭͷ஋ͰBob͔ΒૹΒΕ͖ۭͯͨจࣈྻΛ෮߸Ͱ͖ΔࣄΛ֬ೝ 4ͭͷ஋͔Β࡞ͬͨ伴͔Βૹ৴伴ͱड৴伴Λ࡞Δ

Slide 78

Slide 78 text

Alice͸ cx ͱ bcx͔Β࡞ͬͨ伴Ͱ҉߸Խͨࣗ͠਎ͷެ։伴 ΛBobʹૹ৴ Bob͸ bcxΛٻΊͯAlice͔ΒૹΒΕ͖ͯͨެ։伴Λ෮߸͠ Aliceͷ੩తެ։伴ͱ߹͏ࣄΛ֬ೝ͔ͯ͠Βabc acy cxyΛٻΊΔ cy ͱ 4ͭͷ஋͔Β࡞ͬͨ伴Ͱ҉߸Խۭͨ͠จࣈྻ ΛAliceʹૹ৴ 4ͭͷ஋͔Β࡞ͬͨ伴͔Βૹ৴伴ͱड৴伴Λ࡞Δ Alice͸ abc acy cxyΛٻΊΔ 4ͭͷ஋ͰBob͔ΒૹΒΕ͖ۭͯͨจࣈྻΛ෮߸Ͱ͖ΔࣄΛ֬ೝ 4ͭͷ஋͔Β࡞ͬͨ伴͔Βૹ৴伴ͱड৴伴Λ࡞Δ ௨৴૬ख͕Կऀ͔Λ൑அ͢ΔҝʹbͱcxΛֻ͚Δඞཁ͕͋Δ Curve25519ͷੵ͸҉߸Ͱ࢖ΘΕΔପԁۂઢͷதͰ͸଎͍ํ͕ͩ ͦΕͰ΋InitiatorHelloΛେྔʹૹΒΕΔͱड৴ଆͷCPU͕΋ͨͳ͍

Slide 79

Slide 79 text

Initiator Hello 0x01 (1όΠτ) Reserved (3όΠτ) ૹ৴ऀID (4όΠτ) Alice͕ηογϣϯ͝ͱʹϢχʔΫͳ஋Λࢦఆ͢Δ AliceͷҰ࣌తެ։伴 (cx) (32όΠτ) Aliceͷ੩తެ։伴ΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (32όΠτ+16όΠτ) TAI64NͰද͞Εͨݱࡏ࣌ࠁΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (12όΠτ+16όΠτ) mac1 (16όΠτ) mac2 (16όΠτ) Initiator HelloͱResponderHelloͷmac1ʹ mac1ΑΓલͷ಺༰ͷ伴෇͖ϋογϡΛ͚ͭΔ mac1 = MAC( HASH( "mac1----" ∥ ௨৴૬खͷ੩తެ։伴 ), mac1ΑΓલͷ௨৴಺༰ ); ϋογϡͷ伴ʹ͸௨৴૬खͷ੩తެ։伴Λ࢖͏ ੩తެ։伴͸VPNͷઃఆ࣌ʹୈࡾऀʹ࿙ΕΔՄೳੑ͕͋Δ͕ ͦͷ͔࣌Βͣͬͱݟ͍ͯͨୈࡾऀҎ֎͸ਖ਼͍͠mac1Λ࡞Εͳ͍

Slide 80

Slide 80 text

Cookie Reply 0x03 (1όΠτ) Reserved (3όΠτ) ड৴ऀID (4όΠτ) ύέοτΛड͚औΔଆ͕Ͳͷηογϣϯͷύέοτͳͷ͔Λࣝผ͢Δҝͷ஋ nonce (24όΠτ) cookieͷ҉߸Խʹ࢖ͬͨnonceͷ஋ cookieΛXChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (16όΠτ+16όΠτ) ߴෛՙͳ࣌ʹInitiatorHelloΛड͚औͬͨBob͸ AliceʹResponderHelloͷ୅ΘΓʹCookieReplyΛ౤͛Δ

Slide 81

Slide 81 text

cookie = MAC( 2෼ຖʹมԽ͢Δཚ਺, InitiatorHelloͷૹ৴ݩIPΞυϨεͱϙʔτ ); nonce = 24όΠτͷཚ਺; ҉߸Խ͞Εͨcookie = XAEAD_ENC( HASH( “cookie--" ∥ ௨৴૬खͷ੩తެ։伴 ), nonce, cookie, InitiatorHelloͷmac1 ); ૹ৴ݩIPΞυϨεͱϙʔτ͔ΒcookieΛ࡞Δ cookie͸MACΛ௨͢ҝड͚औͬͨଆͰվ᜵͸Ͱ͖ͳ͍ cookieͷ҉߸Խʹ࢖ΘΕΔ੩తެ։伴ɺnonceɺmac1͸ ͍ͣΕ΋௨৴Λ౪ௌ͍ͯ͠Δୈࡾऀʹݟ͑Δҝ ͜ͷ҉߸Խʹ͸cookieΛӅ͢ྗ͸ͳ͍͕ ಉҰͷInitiatorHelloʹରͯ͠Cookie Reply͕ෳ਺ඈΜͰ͍Δঢ়گͷ ݕग़ΛՄೳʹ͢Δ໾ׂ͕͋Δ(Cookie ReplyͷϦϓϨΠ߈ܸͷճආ)

Slide 82

Slide 82 text

Initiator Hello 0x01 (1όΠτ) Reserved (3όΠτ) ૹ৴ऀID (4όΠτ) Alice͕ηογϣϯ͝ͱʹϢχʔΫͳ஋Λࢦఆ͢Δ AliceͷҰ࣌తެ։伴 (cx) (32όΠτ) Aliceͷ੩తެ։伴ΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (32όΠτ+16όΠτ) TAI64NͰද͞Εͨݱࡏ࣌ࠁΛChacha20-Poly1305Ͱ҉߸Խͨ͠΋ͷ (12όΠτ+16όΠτ) mac1 (16όΠτ) mac2 (16όΠτ) mac2 = MAC( 2෼Ҏ಺ʹड͚औͬͨcookie, mac2ΑΓલͷ௨৴಺༰ ); InitiatorHello࣌ɺ2෼Ҏ಺ʹड͚औͬͨcookie͕͋Δ৔߹͸ mac2ΑΓલͷ௨৴಺༰ͷ伴෇͖ϋογϡΛ͚ͭΔ

Slide 83

Slide 83 text

ૹΒΕ͖ͯͨmac2ͱखݩͰܭࢉͨ͠mac2͕߹Θͳ͍ Մೳੑ1:cookieͷݩʹͳΔཚ਺͕੾ΓସΘΔ͘Β͍͕࣌ؒܦաͨ͠ Մೳੑ2:௨৴૬ख͸ਖ਼௚ͳୈࡾऀͰ͋Δ Մೳੑ1:௨৴૬ख͸ຊ෺Ͱ͋Δ Մೳੑ2:௨৴૬ख͸ιʔεΞυϨεΛ࠮শ͢ΔୈࡾऀͰ͋Δ ૹΒΕ͖ͯͨmac2ͱखݩͰܭࢉͨ͠mac2͕߹͏ ΋͏Ұ౓cookie reply ͍ͣΕʹͯ͠΋ಛఆͷιʔεΞυϨεʹͳ͍ͬͯΔҝ IPϕʔεͷଳҬ੍ݶΛ͔͚ͯ InitiatorHelloͷ಺༰ͷνΣοΫʹਐΉ

Slide 84

Slide 84 text

࣮૷ͯ͠ΈΑ͏ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 85

Slide 85 text

ΦϦδφϧͷWireGuard͸ΧʔωϧۭؒͰ࣮૷͞Ε͍ͯΔ͕ ҉߸ͷ࣮૷͕ἧ͍ͬͯΔϢʔβۭؒͷํ͕࣮૷͢Δͷ͸ָ Curve25519ͷ৐ࢉ BLAKE2s IETF Chacha20-Poly1305 XChacha20-Poly1305 ҉߸࿦తٖࣅཚ਺ੜ੒ث libsodiumΛ࢖༻ libsodiumΛ࢖༻ Crypto++Λ࢖༻ libsodiumΛ࢖༻ libsodiumΛ࢖༻ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 86

Slide 86 text

template< typename Out, typename CookieType > void initiator_hello_phase1( kx_state &stat, Out &out, const wg_key_type &self_static_private, const wg_key_type &self_static_public, const wg_key_type &remote_static_public, uint32_t self_spi, const CookieType &cookie ) { wg_key_type kdf_key; wg_key_type aead_key; wg_key_type mac_key; wg_tai64n_type self_timestamp; dh_generate( stat.self_ephemeral_private, stat.self_ephemeral_public ); get_initial_chain_key( stat.chain_key ); get_initial_hash_key( stat.hash_key, stat.chain_key ); kdf( stat.chain_key ).update( stat.self_ephemeral_public ).get( stat.chain_key ); hash().update( stat.hash_key, remote_static_public ).get( stat.hash_key ); hash().update( stat.hash_key, stat.self_ephemeral_public ).get( stat.hash_key ); dh( kdf_key, stat.self_ephemeral_private, remote_static_public ); kdf( stat.chain_key ).update( kdf_key ).get( stat.chain_key, aead_key ); out.resize( wg_kx1_len, 0u ); auto encrypted_static = make_svv( out.data(), wg_kx1_encrypted_static_offset, wg_encrypted_static_len ); aead_enc( encrypted_static, aead_key, 0ull, self_static_public, stat.hash_key ); hash().update( stat.hash_key, encrypted_static ).get( stat.hash_key ); dh( kdf_key, self_static_private, remote_static_public ); kdf( stat.chain_key ).update( kdf_key ).get( stat.chain_key, aead_key ); timestamp( std::back_inserter( self_timestamp ) ); auto encrypted_timestamp = make_svv( out.data(), wg_kx1_encrypted_tai64n_offset, wg_encrypted_tai64n_len ); aead_enc( encrypted_timestamp, aead_key, 0ull, self_timestamp, stat.hash_key ); hash().update( stat.hash_key, encrypted_timestamp ).get( stat.hash_key ); out[ 0 ] = 0x01; namespace karma = boost::spirit::karma; karma::generate( std::next( out.begin(), wg_kx1_self_spi_offset ), karma::little_dword, self_spi ); InitiatorHelloΛ࡞Δ Ұ࣌伴ϖΞ(xͱcx)Λ࡞ͬͯ chain_key(C)ͱhash_key(H)ΛॳظԽ͢Δ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 87

Slide 87 text

template< typename Out, typename CookieType > void initiator_hello_phase1( kx_state &stat, Out &out, const wg_key_type &self_static_private, const wg_key_type &self_static_public, const wg_key_type &remote_static_public, uint32_t self_spi, const CookieType &cookie ) { wg_key_type kdf_key; wg_key_type aead_key; wg_key_type mac_key; wg_tai64n_type self_timestamp; dh_generate( stat.self_ephemeral_private, stat.self_ephemeral_public ); get_initial_chain_key( stat.chain_key ); get_initial_hash_key( stat.hash_key, stat.chain_key ); kdf( stat.chain_key ).update( stat.self_ephemeral_public ).get( stat.chain_key ); hash().update( stat.hash_key, remote_static_public ).get( stat.hash_key ); hash().update( stat.hash_key, stat.self_ephemeral_public ).get( stat.hash_key ); dh( kdf_key, stat.self_ephemeral_private, remote_static_public ); kdf( stat.chain_key ).update( kdf_key ).get( stat.chain_key, aead_key ); out.resize( wg_kx1_len, 0u ); auto encrypted_static = make_svv( out.data(), wg_kx1_encrypted_static_offset, wg_encrypted_static_len ); aead_enc( encrypted_static, aead_key, 0ull, self_static_public, stat.hash_key ); hash().update( stat.hash_key, encrypted_static ).get( stat.hash_key ); dh( kdf_key, self_static_private, remote_static_public ); kdf( stat.chain_key ).update( kdf_key ).get( stat.chain_key, aead_key ); timestamp( std::back_inserter( self_timestamp ) ); auto encrypted_timestamp = make_svv( out.data(), wg_kx1_encrypted_tai64n_offset, wg_encrypted_tai64n_len ); aead_enc( encrypted_timestamp, aead_key, 0ull, self_timestamp, stat.hash_key ); hash().update( stat.hash_key, encrypted_timestamp ).get( stat.hash_key ); out[ 0 ] = 0x01; namespace karma = boost::spirit::karma; karma::generate( std::next( out.begin(), wg_kx1_self_spi_offset ), karma::little_dword, self_spi ); ࣗ෼ͷҰ࣌తൿີ伴(x)ͱ૬खͷ੩తެ։伴(bc)ͰbcxΛ࡞Γ bcxΛKDFʹ௨ͯ͠࡞ͬͨ伴Ͱ ࣗ෼ͷ੩తެ։伴(ac)Λ҉߸Խ͢Δ InitiatorHelloΛ࡞Δ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 88

Slide 88 text

hash().update( stat.hash_key, stat.self_ephemeral_public ).get( stat.hash_key ); dh( kdf_key, stat.self_ephemeral_private, remote_static_public ); kdf( stat.chain_key ).update( kdf_key ).get( stat.chain_key, aead_key ); out.resize( wg_kx1_len, 0u ); auto encrypted_static = make_svv( out.data(), wg_kx1_encrypted_static_offset, wg_encrypted_static_len ); aead_enc( encrypted_static, aead_key, 0ull, self_static_public, stat.hash_key ); hash().update( stat.hash_key, encrypted_static ).get( stat.hash_key ); dh( kdf_key, self_static_private, remote_static_public ); kdf( stat.chain_key ).update( kdf_key ).get( stat.chain_key, aead_key ); timestamp( std::back_inserter( self_timestamp ) ); auto encrypted_timestamp = make_svv( out.data(), wg_kx1_encrypted_tai64n_offset, wg_encrypted_tai64n_len ); aead_enc( encrypted_timestamp, aead_key, 0ull, self_timestamp, stat.hash_key ); hash().update( stat.hash_key, encrypted_timestamp ).get( stat.hash_key ); out[ 0 ] = 0x01; namespace karma = boost::spirit::karma; karma::generate( std::next( out.begin(), wg_kx1_self_spi_offset ), karma::little_dword, self_spi ); std::copy( stat.self_ephemeral_public.begin(), stat.self_ephemeral_public.end(), std::next( out.begin(), wg_kx1_ephemeral_offset ) ); constexpr static char label_mac1[] = "mac1----"; auto mac1_message = make_svv( out.data(), 0, wg_kx1_mac1_message_len ); auto mac1 = make_svv( out.data(), wg_kx1_mac1_offset, wg_mac_len ); hash().update( label_mac1, label_mac1 + strlen( label_mac1 ) ).update( remote_static_public ).get( mac_key ); mac( mac_key ).update( mac1_message ).get( mac1 ); stat.mac1.resize( mac1.size() ); std::copy( mac1.begin(), mac1.end(), stat.mac1.begin() ); if( !cookie.empty() ) { auto mac2_message = make_svv( out.data(), 0, wg_kx1_mac2_message_len ); auto mac2 = make_svv( out.data(), wg_kx1_mac2_offset, wg_mac_len ); mac( cookie ).update( mac2_message ).get( mac2 ); } clear_key( kdf_key ); clear_key( aead_key ); ࣗ෼ͷ੩తൿີ伴(a)ͱ૬खͷ੩తެ։伴(bc)ͰabcΛ࡞Γ abcΛKDFʹ௨ͯ͠࡞ͬͨ伴Ͱ λΠϜελϯϓΛ҉߸Խ͢Δ InitiatorHelloΛ࡞Δ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 89

Slide 89 text

out.resize( wg_kx1_len, 0u ); auto encrypted_static = make_svv( out.data(), wg_kx1_encrypted_static_offset, wg_encrypted_static_len ); aead_enc( encrypted_static, aead_key, 0ull, self_static_public, stat.hash_key ); hash().update( stat.hash_key, encrypted_static ).get( stat.hash_key ); dh( kdf_key, self_static_private, remote_static_public ); kdf( stat.chain_key ).update( kdf_key ).get( stat.chain_key, aead_key ); timestamp( std::back_inserter( self_timestamp ) ); auto encrypted_timestamp = make_svv( out.data(), wg_kx1_encrypted_tai64n_offset, wg_encrypted_tai64n_len ); aead_enc( encrypted_timestamp, aead_key, 0ull, self_timestamp, stat.hash_key ); hash().update( stat.hash_key, encrypted_timestamp ).get( stat.hash_key ); out[ 0 ] = 0x01; namespace karma = boost::spirit::karma; karma::generate( std::next( out.begin(), wg_kx1_self_spi_offset ), karma::little_dword, self_spi ); std::copy( stat.self_ephemeral_public.begin(), stat.self_ephemeral_public.end(), std::next( out.begin(), wg_kx1_ephemeral_offset ) ); constexpr static char label_mac1[] = "mac1----"; auto mac1_message = make_svv( out.data(), 0, wg_kx1_mac1_message_len ); auto mac1 = make_svv( out.data(), wg_kx1_mac1_offset, wg_mac_len ); hash().update( label_mac1, label_mac1 + strlen( label_mac1 ) ).update( remote_static_public ).get( mac_key ); mac( mac_key ).update( mac1_message ).get( mac1 ); stat.mac1.resize( mac1.size() ); std::copy( mac1.begin(), mac1.end(), stat.mac1.begin() ); if( !cookie.empty() ) { auto mac2_message = make_svv( out.data(), 0, wg_kx1_mac2_message_len ); auto mac2 = make_svv( out.data(), wg_kx1_mac2_offset, wg_mac_len ); mac( cookie ).update( mac2_message ).get( mac2 ); } clear_key( kdf_key ); clear_key( aead_key ); clear_key( mac_key ); } mac1Λܭࢉ InitiatorHelloΛ࡞Δ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 90

Slide 90 text

aead_enc( encrypted_timestamp, aead_key, 0ull, self_timestamp, stat.hash_key ); hash().update( stat.hash_key, encrypted_timestamp ).get( stat.hash_key ); out[ 0 ] = 0x01; namespace karma = boost::spirit::karma; karma::generate( std::next( out.begin(), wg_kx1_self_spi_offset ), karma::little_dword, self_spi ); std::copy( stat.self_ephemeral_public.begin(), stat.self_ephemeral_public.end(), std::next( out.begin(), wg_kx1_ephemeral_offset ) ); constexpr static char label_mac1[] = "mac1----"; auto mac1_message = make_svv( out.data(), 0, wg_kx1_mac1_message_len ); auto mac1 = make_svv( out.data(), wg_kx1_mac1_offset, wg_mac_len ); hash().update( label_mac1, label_mac1 + strlen( label_mac1 ) ).update( remote_static_public ).get( mac_key ); mac( mac_key ).update( mac1_message ).get( mac1 ); stat.mac1.resize( mac1.size() ); std::copy( mac1.begin(), mac1.end(), stat.mac1.begin() ); if( !cookie.empty() ) { auto mac2_message = make_svv( out.data(), 0, wg_kx1_mac2_message_len ); auto mac2 = make_svv( out.data(), wg_kx1_mac2_offset, wg_mac_len ); mac( cookie ).update( mac2_message ).get( mac2 ); } clear_key( kdf_key ); clear_key( aead_key ); clear_key( mac_key ); } 2෼Ҏ಺ʹड͚औͬͨcookie͕͋Ε͹ mac2΋ܭࢉ InitiatorHelloΛ࡞Δ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 91

Slide 91 text

void responder_hello( key_state &key, Out &out, const wg_key_type &self_static_private, const wg_key_type &self_static_public, const wg_key_type &remote_static_public, uint32_t self_spi, const CookieType &cookie, const In &in ) { if( in.size() != wg_kx1_len ) throw invalid_packet(); if( in[ 0 ] != 0x01 ) throw invalid_packet(); auto encrypted_static = make_svv( in.data(), wg_kx1_encrypted_static_offset, wg_encrypted_static_len ); auto encrypted_timestamp = make_svv( in.data(), wg_kx1_encrypted_tai64n_offset, wg_encrypted_tai64n_len ); auto remote_ephemeral_public = make_svv( in.data(), wg_kx1_ephemeral_offset, wg_ephemeral_len ); wg_key_type kdf_key, aead_key, chain_key, hash_key, incoming_remote_static_public; wg_key_type self_ephemeral_private,; wg_key_type q( wg_key_len, 0u ); wg_key_type t, empty, mac_key, calculated_kx1_mac1; wg_tai64n_type remote_timestamp; wg_key_type calculated_kx1_mac1; namespace qi = boost::spirit::qi; uint32_t remote_spi; qi::parse( std::next( in.begin(), wg_kx1_self_spi_offset ), std::next( in.begin(), wg_kx1_self_spi_offset + wg_spi_len ), qi::little_dword, remote_spi ); auto kx1_mac1_message = make_svv( in.data(), 0, wg_kx1_mac1_message_len ); auto incoming_kx1_mac1 = make_svv( in.data(), wg_kx1_mac1_offset, wg_mac_len ); constexpr static char label_mac1[] = "mac1----"; hash().update( label_mac1, label_mac1 + strlen( label_mac1 ) ).update( self_static_public ).get( mac_key ); mac( mac_key ).update( kx1_mac1_message ).get( calculated_kx1_mac1 ); if( !std::equal( calculated_kx1_mac1.begin(), calculated_kx1_mac1.end(), incoming_kx1_mac1.begin(), incoming_kx1_mac1.end() ) ) throw invalid_packet(); get_initial_chain_key( chain_key ); get_initial_hash_key( hash_key, chain_key ); mac1͕ਖ਼͍͠ࣄΛ֬ೝ InitiatorHelloΛड͚औΔ

Slide 92

Slide 92 text

auto kx1_mac1_message = make_svv( in.data(), 0, wg_kx1_mac1_message_len ); auto incoming_kx1_mac1 = make_svv( in.data(), wg_kx1_mac1_offset, wg_mac_len ); constexpr static char label_mac1[] = "mac1----"; hash().update( label_mac1, label_mac1 + strlen( label_mac1 ) ).update( self_static_public ).get( mac_key ); mac( mac_key ).update( kx1_mac1_message ).get( calculated_kx1_mac1 ); if( !std::equal( calculated_kx1_mac1.begin(), calculated_kx1_mac1.end(), incoming_kx1_mac1.begin(), incoming_kx1_mac1.end() ) ) throw invalid_packet(); get_initial_chain_key( chain_key ); get_initial_hash_key( hash_key, chain_key ); kdf( chain_key ).update( remote_ephemeral_public ).get( chain_key ); hash().update( hash_key, self_static_public ).get( hash_key ); hash().update( hash_key, remote_ephemeral_public ).get( hash_key ); dh( kdf_key, self_static_private, remote_ephemeral_public ); kdf( chain_key ).update( kdf_key ).get( chain_key, aead_key ); out.resize( wg_kx2_len, 0u ); if( !aead_dec( incoming_remote_static_public, aead_key, 0ull, encrypted_static, hash_key ) ) throw invalid_packet(); hash().update( hash_key, encrypted_static ).get( hash_key ); dh( kdf_key, self_static_private, remote_static_public ); kdf( chain_key ).update( kdf_key ).get( chain_key, aead_key ); if( !aead_dec( remote_timestamp, aead_key, 0ull, encrypted_timestamp, hash_key ) ) throw invalid_packet(); hash().update( hash_key, encrypted_timestamp ).get( hash_key ); out.resize( wg_kx2_len, 0u ); auto self_ephemeral_public = make_svv( out.data(), wg_kx2_ephemeral_offset, wg_ephemeral_len ); auto encrypted_empty = make_svv( out.data(), wg_kx2_encrypted_empty_offset, wg_encrypted_empty_len ); dh_generate( self_ephemeral_private, self_ephemeral_public ); kdf( chain_key ).update( self_ephemeral_public ).get( chain_key ); hash().update( hash_key, self_ephemeral_public ).get( hash_key ); ૹΒΕ͖ͯͨ஋(cx)Λ࢖ͬͯ chain_key(C)ͱhash_key(H)ΛॳظԽ͢Δ InitiatorHelloΛड͚औΔ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 93

Slide 93 text

throw invalid_packet(); get_initial_chain_key( chain_key ); get_initial_hash_key( hash_key, chain_key ); kdf( chain_key ).update( remote_ephemeral_public ).get( chain_key ); hash().update( hash_key, self_static_public ).get( hash_key ); hash().update( hash_key, remote_ephemeral_public ).get( hash_key ); dh( kdf_key, self_static_private, remote_ephemeral_public ); kdf( chain_key ).update( kdf_key ).get( chain_key, aead_key ); out.resize( wg_kx2_len, 0u ); if( !aead_dec( incoming_remote_static_public, aead_key, 0ull, encrypted_static, hash_key ) ) throw invalid_packet(); hash().update( hash_key, encrypted_static ).get( hash_key ); dh( kdf_key, self_static_private, remote_static_public ); kdf( chain_key ).update( kdf_key ).get( chain_key, aead_key ); if( !aead_dec( remote_timestamp, aead_key, 0ull, encrypted_timestamp, hash_key ) ) throw invalid_packet(); hash().update( hash_key, encrypted_timestamp ).get( hash_key ); out.resize( wg_kx2_len, 0u ); auto self_ephemeral_public = make_svv( out.data(), wg_kx2_ephemeral_offset, wg_ephemeral_len ); auto encrypted_empty = make_svv( out.data(), wg_kx2_encrypted_empty_offset, wg_encrypted_empty_len ); dh_generate( self_ephemeral_private, self_ephemeral_public ); kdf( chain_key ).update( self_ephemeral_public ).get( chain_key ); hash().update( hash_key, self_ephemeral_public ).get( hash_key ); dh( kdf_key, self_ephemeral_private, remote_ephemeral_public ); kdf( chain_key ).update( kdf_key ).get( chain_key ); dh( kdf_key, self_ephemeral_private, remote_static_public ); kdf( chain_key ).update( kdf_key ).get( chain_key ); kdf( chain_key ).update( q ).get( chain_key, t, aead_key ); hash().update( hash_key, t ).get( hash_key ); aead_enc( encrypted_empty, aead_key, 0ull, empty, hash_key ); InitiatorHelloΛड͚औΔ ࣗ෼ͷ੩తൿີ伴(b)ͱड͚औͬͨҰ࣌తެ։伴(cx)ͰbcxΛ࡞Γ bcxΛKDFʹ௨ͯ͠࡞ͬͨ伴Ͱ ૬खͷ੩తެ։伴(ac)Λ෮߸ग़དྷΔࣄΛ֬ೝ͢Δ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 94

Slide 94 text

dh( kdf_key, self_static_private, remote_ephemeral_public ); kdf( chain_key ).update( kdf_key ).get( chain_key, aead_key ); out.resize( wg_kx2_len, 0u ); if( !aead_dec( incoming_remote_static_public, aead_key, 0ull, encrypted_static, hash_key ) ) throw invalid_packet(); hash().update( hash_key, encrypted_static ).get( hash_key ); dh( kdf_key, self_static_private, remote_static_public ); kdf( chain_key ).update( kdf_key ).get( chain_key, aead_key ); if( !aead_dec( remote_timestamp, aead_key, 0ull, encrypted_timestamp, hash_key ) ) throw invalid_packet(); hash().update( hash_key, encrypted_timestamp ).get( hash_key ); out.resize( wg_kx2_len, 0u ); auto self_ephemeral_public = make_svv( out.data(), wg_kx2_ephemeral_offset, wg_ephemeral_len ); auto encrypted_empty = make_svv( out.data(), wg_kx2_encrypted_empty_offset, wg_encrypted_empty_len ); dh_generate( self_ephemeral_private, self_ephemeral_public ); kdf( chain_key ).update( self_ephemeral_public ).get( chain_key ); hash().update( hash_key, self_ephemeral_public ).get( hash_key ); dh( kdf_key, self_ephemeral_private, remote_ephemeral_public ); kdf( chain_key ).update( kdf_key ).get( chain_key ); dh( kdf_key, self_ephemeral_private, remote_static_public ); kdf( chain_key ).update( kdf_key ).get( chain_key ); kdf( chain_key ).update( q ).get( chain_key, t, aead_key ); hash().update( hash_key, t ).get( hash_key ); aead_enc( encrypted_empty, aead_key, 0ull, empty, hash_key ); hash().update( hash_key, encrypted_empty ).get( hash_key ); out[ 0 ] = 0x02; namespace karma = boost::spirit::karma; karma::generate( std::next( out.begin(), wg_kx2_self_spi_offset ), karma::little_dword, self_spi ); karma::generate( std::next( out.begin(), wg_kx2_remote_spi_offset ), karma::little_dword, remote_spi ); auto kx2_mac1_message = make_svv( out.data(), 0, wg_kx2_mac1_message_len ); InitiatorHelloΛड͚औΔ ࣗ෼ͷ੩తൿີ伴(b)ͱ૬खͷ੩తެ։伴(ac)ͰabcΛ࡞Γ abcΛKDFʹ௨ͯ͠࡞ͬͨ伴Ͱ λΠϜελϯϓΛ෮߸ग़དྷΔࣄΛ֬ೝ͢Δ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 95

Slide 95 text

throw invalid_packet(); hash().update( hash_key, encrypted_timestamp ).get( hash_key ); out.resize( wg_kx2_len, 0u ); auto self_ephemeral_public = make_svv( out.data(), wg_kx2_ephemeral_offset, wg_ephemeral_len ); auto encrypted_empty = make_svv( out.data(), wg_kx2_encrypted_empty_offset, wg_encrypted_empty_len ); dh_generate( self_ephemeral_private, self_ephemeral_public ); kdf( chain_key ).update( self_ephemeral_public ).get( chain_key ); hash().update( hash_key, self_ephemeral_public ).get( hash_key ); dh( kdf_key, self_ephemeral_private, remote_ephemeral_public ); kdf( chain_key ).update( kdf_key ).get( chain_key ); dh( kdf_key, self_ephemeral_private, remote_static_public ); kdf( chain_key ).update( kdf_key ).get( chain_key ); kdf( chain_key ).update( q ).get( chain_key, t, aead_key ); hash().update( hash_key, t ).get( hash_key ); aead_enc( encrypted_empty, aead_key, 0ull, empty, hash_key ); hash().update( hash_key, encrypted_empty ).get( hash_key ); out[ 0 ] = 0x02; namespace karma = boost::spirit::karma; karma::generate( std::next( out.begin(), wg_kx2_self_spi_offset ), karma::little_dword, self_spi ); karma::generate( std::next( out.begin(), wg_kx2_remote_spi_offset ), karma::little_dword, remote_spi ); auto kx2_mac1_message = make_svv( out.data(), 0, wg_kx2_mac1_message_len ); auto kx2_mac1 = make_svv( out.data(), wg_kx2_mac1_offset, wg_mac_len ); hash().update( label_mac1, label_mac1 + strlen( label_mac1 ) ).update( remote_static_public ).get( mac_key ); mac( mac_key ).update( kx2_mac1_message ).get( kx2_mac1 ); if( !cookie.empty() ) { auto mac2_message = make_svv( out.data(), 0, wg_kx2_mac2_message_len ); auto mac2 = make_svv( out.data(), wg_kx2_mac2_offset, wg_mac_len ); mac( cookie ).update( mac2_message ).get( mac2 ); } kdf( chain_key ).update( empty ).get( key.receive_key, key.send_key ); ResponderHelloΛ࡞Δ Ұ࣌伴ϖΞ(yͱcy)Λ࡞ͬͯ 4ͭͷ஋ͷ͏ͪ·ͩٻΊ͍ͯͳ͍acyͱcxyΛٻΊΔ 4ͭͷ஋શͯΛKDFʹ௨ͯ͠ಘͨ伴Ͱ ۭจࣈྻΛ҉߸Խ͢Δ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 96

Slide 96 text

hash().update( hash_key, t ).get( hash_key ); aead_enc( encrypted_empty, aead_key, 0ull, empty, hash_key ); hash().update( hash_key, encrypted_empty ).get( hash_key ); out[ 0 ] = 0x02; namespace karma = boost::spirit::karma; karma::generate( std::next( out.begin(), wg_kx2_self_spi_offset ), karma::little_dword, self_spi ); karma::generate( std::next( out.begin(), wg_kx2_remote_spi_offset ), karma::little_dword, remote_spi ); auto kx2_mac1_message = make_svv( out.data(), 0, wg_kx2_mac1_message_len ); auto kx2_mac1 = make_svv( out.data(), wg_kx2_mac1_offset, wg_mac_len ); hash().update( label_mac1, label_mac1 + strlen( label_mac1 ) ).update( remote_static_public ).get( mac_key ); mac( mac_key ).update( kx2_mac1_message ).get( kx2_mac1 ); if( !cookie.empty() ) { auto mac2_message = make_svv( out.data(), 0, wg_kx2_mac2_message_len ); auto mac2 = make_svv( out.data(), wg_kx2_mac2_offset, wg_mac_len ); mac( cookie ).update( mac2_message ).get( mac2 ); } kdf( chain_key ).update( empty ).get( key.receive_key, key.send_key ); kdf_key.resize( wg_key_len ); clear_key( kdf_key ); clear_key( aead_key ); clear_key( mac_key ); clear_key( q ); clear_key( t ); clear_key( self_ephemeral_private ); clear_key( chain_key ); clear_key( hash_key ); ResponderHelloΛ࡞Δ macΛ͚ͭͯ׬੒ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 97

Slide 97 text

template< typename In > void initiator_hello_phase2( key_state &key, const wg_key_type &self_static_private, const wg_key_type &self_static_public, const wg_key_type &/*remote_static_public*/, uint32_t /*self_spi*/, kx_state &stat, const In &in ) { if( in.size() != wg_kx2_len ) throw invalid_packet(); if( in[ 0 ] != 0x02 ) throw invalid_packet(); namespace qi = boost::spirit::qi; uint32_t remote_spi; qi::parse( std::next( in.begin(), wg_kx1_self_spi_offset ), std::next( in.begin(), wg_kx1_self_spi_offset + wg_spi_len ), qi::little_dword, remote_spi ); auto encrypted_empty = make_svv( in.data(), wg_kx2_encrypted_empty_offset, wg_encrypted_empty_len ); auto remote_ephemeral_public = make_svv( in.data(), wg_kx2_ephemeral_offset, wg_ephemeral_len ); wg_key_type kdf_key, aead_key, t, empty, calculated_kx2_mac1, mac_key; wg_key_type q( wg_key_len, 0u ); auto kx2_mac1_message = make_svv( in.data(), 0, wg_kx2_mac1_message_len ); auto incoming_kx2_mac1 = make_svv( in.data(), wg_kx2_mac1_offset, wg_mac_len ); constexpr static char label_mac1[] = "mac1----"; hash().update( label_mac1, label_mac1 + strlen( label_mac1 ) ).update( self_static_public ).get( mac_key ); mac( mac_key ).update( kx2_mac1_message ).get( calculated_kx2_mac1 ); if( !std::equal( calculated_kx2_mac1.begin(), calculated_kx2_mac1.end(), incoming_kx2_mac1.begin(), incoming_kx2_mac1.end() ) ) throw invalid_packet(); kdf( stat.chain_key ).update( remote_ephemeral_public ).get( stat.chain_key ); hash().update( stat.hash_key, remote_ephemeral_public ).get( stat.hash_key ); dh( kdf_key, stat.self_ephemeral_private, remote_ephemeral_public ); kdf( stat.chain_key ).update( kdf_key ).get( stat.chain_key ); dh( kdf_key, self_static_private, remote_ephemeral_public ); kdf( stat.chain_key ).update( kdf_key ).get( stat.chain_key ); ResponderHelloΛड͚औΔ mac1͕ਖ਼͍͠ࣄΛ֬ೝ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 98

Slide 98 text

constexpr static char label_mac1[] = "mac1----"; hash().update( label_mac1, label_mac1 + strlen( label_mac1 ) ).update( self_static_public ).get( mac_key ); mac( mac_key ).update( kx2_mac1_message ).get( calculated_kx2_mac1 ); if( !std::equal( calculated_kx2_mac1.begin(), calculated_kx2_mac1.end(), incoming_kx2_mac1.begin(), incoming_kx2_mac1.end() ) ) throw invalid_packet(); kdf( stat.chain_key ).update( remote_ephemeral_public ).get( stat.chain_key ); hash().update( stat.hash_key, remote_ephemeral_public ).get( stat.hash_key ); dh( kdf_key, stat.self_ephemeral_private, remote_ephemeral_public ); kdf( stat.chain_key ).update( kdf_key ).get( stat.chain_key ); dh( kdf_key, self_static_private, remote_ephemeral_public ); kdf( stat.chain_key ).update( kdf_key ).get( stat.chain_key ); kdf( stat.chain_key ).update( q ).get( stat.chain_key, t, aead_key ); hash().update( stat.hash_key, t ).get( stat.hash_key ); if( !aead_dec( empty, aead_key, 0ull, encrypted_empty, stat.hash_key ) ) throw invalid_packet(); hash().update( stat.hash_key, encrypted_empty ).get( stat.hash_key ); kdf( stat.chain_key ).update( empty ).get( key.send_key, key.receive_key ); clear_key( kdf_key ); clear_key( aead_key ); clear_key( mac_key ); clear_key( q ); clear_key( t ); clear_key( stat.self_ephemeral_private ); clear_key( stat.self_ephemeral_public ); clear_key( stat.chain_key ); clear_key( stat.hash_key ); } ResponderHelloΛड͚औΔ ࣗ෼ͷ੩తൿີ伴(a)ͱड͚औͬͨҰ࣌తൿີ伴(cy)ͰacyΛ࡞Δ ࣗ෼ͷҰ࣌తൿີ伴(x)ͱड͚औͬͨҰ࣌తൿີ伴(cy)ͰcxyΛ࡞Δ 4ͭͷ஋શͯΛKDFʹ௨ͯ͠ಘͨ伴Ͱ ۭจࣈྻΛ෮߸ग़དྷΔࣄΛ֬ೝ͢Δ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 99

Slide 99 text

hash().update( stat.hash_key, remote_ephemeral_public ).get( stat.hash_key ); dh( kdf_key, stat.self_ephemeral_private, remote_ephemeral_public ); kdf( stat.chain_key ).update( kdf_key ).get( stat.chain_key ); dh( kdf_key, self_static_private, remote_ephemeral_public ); kdf( stat.chain_key ).update( kdf_key ).get( stat.chain_key ); kdf( stat.chain_key ).update( q ).get( stat.chain_key, t, aead_key ); hash().update( stat.hash_key, t ).get( stat.hash_key ); if( !aead_dec( empty, aead_key, 0ull, encrypted_empty, stat.hash_key ) ) throw invalid_packet(); hash().update( stat.hash_key, encrypted_empty ).get( stat.hash_key ); kdf( stat.chain_key ).update( empty ).get( key.send_key, key.receive_key ); clear_key( kdf_key ); clear_key( aead_key ); clear_key( mac_key ); clear_key( q ); clear_key( t ); clear_key( stat.self_ephemeral_private ); clear_key( stat.self_ephemeral_public ); clear_key( stat.chain_key ); clear_key( stat.hash_key ); } ResponderHelloΛड͚औΔ InitiatorHelloͱResponderHelloͰڞ༗ͨ͠chain_key(C)Λ KDFʹ௨ͯ͠ηογϣϯ伴Λ࡞Δ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 100

Slide 100 text

template< typename Out, typename In > void encrypt_data( Out &packet, const key_state &key, In &&plain ) { const auto packet_size = plain.size() / 16 * 16 + ( plain.size() % 16 ? 16 : 0 ); packet.clear(); packet.resize( packet_size + wg_aead_hash_len + wg_counter_len + wg_spi_len + wg_header_len, 0u ); packet[ 0 ] = 0x04; namespace karma = boost::spirit::karma; karma::generate( std::next( packet.begin(), wg_transport_remote_spi_offset ), karma::little_dword, key.remote_kxid ); karma::generate( std::next( packet.begin(), wg_transport_counter_offset ), karma::little_qword, key.tx_count ); plain.resize( packet_size, 0u ); wg_key_type empty; auto encrypted = make_svv( packet.data(), wg_transport_packet_offset, packet_size + wg_aead_hash_len ); aead_enc( encrypted, key.send_key, key.tx_count, plain, empty ); } ύέοτΛૹΔ ύέοτΛηογϣϯΩʔͰ҉߸Խ͢Δ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 101

Slide 101 text

template< typename Out, typename In > bool decrypt_data( Out &plain, key_state &key, const In &packet ) { if( packet.size() < wg_transport_packet_offset + wg_aead_hash_len ) return false; if( packet[ 0 ] != 0x04 ) return false; namespace qi = boost::spirit::qi; uint64_t counter = 0; qi::parse( std::next( packet.begin(), wg_transport_counter_offset ), std::next( packet.begin(), wg_transport_counter_offset + wg_counter_len ), qi::little_qword, counter ); wg_key_type empty; auto encrypted = make_svv( packet.data(), wg_transport_packet_offset, packet.size() - wg_transport_packet_offset ); if( !aead_dec( plain, key.receive_key, counter, encrypted, empty ) ) return false; if( plain.size() >= 4u ) { uint16_t length = 0; qi::parse( std::next( plain.begin(), 2 ), std::next( plain.begin(), 4 ), qi::big_word, length ); if( plain.size() < length ) return false; plain.resize( length ); } return true; } ύέοτΛड͚औΔ ύέοτΛηογϣϯΩʔͰ෮߸͢Δ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 102

Slide 102 text

class tunnel { public: tunnel( const std::string &devname ) : fd( 0 ) { ifreq ifr; if( ( fd = open("/dev/net/tun", O_RDWR) ) < 0 ) { std::string device_file_path( "/dev/" ); device_name = devname.empty() ? std::string( "tun0" ) : devname; device_file_path += device_name; if( ( fd = open( device_file_path.c_str(), O_RDWR ) ) < 0 ) throw unable_to_open_tunnel(); } else { memset( &ifr, 0, sizeof( ifr ) ); ifr.ifr_flags = IFF_TUN|IFF_NO_PI; if( !devname.empty() ) strncpy( ifr.ifr_name, devname.c_str(), IFNAMSIZ ); if( ioctl( fd, TUNSETIFF, (void *) &ifr ) < 0 ) { close( fd ); throw unable_to_open_tunnel(); } device_name = ifr.ifr_name; } } tunnel( const tunnel& ) = delete; tunnel( tunnel&& ) = delete; tunnel &operator=( const tunnel& ) = delete; tunnel &operator=( tunnel&& ) = delete; ~tunnel() { ͜ΕΛLinuxͷτϯωϧσόΠεʹܨ͙ https://github.com/Fadis/userspace_wireguard ιʔείʔυ

Slide 103

Slide 103 text

$ ip address add dev tun0 192.168.3.2 peer 192.168.3.1 $ ip link set tun0 mtu 1420 $ ip link set tun0 up $ ping -c 5 192.168.3.1 PING 192.168.3.1 (192.168.3.1) 56(84) bytes of data. 64 bytes from 192.168.3.1: icmp_seq=1 ttl=64 time=9.35 ms 64 bytes from 192.168.3.1: icmp_seq=2 ttl=64 time=9.50 ms 64 bytes from 192.168.3.1: icmp_seq=3 ttl=64 time=9.08 ms 64 bytes from 192.168.3.1: icmp_seq=4 ttl=64 time=9.44 ms 64 bytes from 192.168.3.1: icmp_seq=5 ttl=64 time=9.31 ms --- 192.168.3.1 ping statistics --- 5 packets transmitted, 5 received, 0% packet loss, time 4006ms rtt min/avg/max/mdev = 9.080/9.340/9.508/0.180 ms (192.168.3.1ଆͰ͸ຊՈͷWireGuardσόΠε͕଴ͪड͚த) ͳΜͯ؆୯ͳϓϩτίϧͳΜͰ͠ΐ͏

Slide 104

Slide 104 text

00:43:13.196699 IP alice.example.com.51820 > bob.example.com.51820: UDP, length 148 0x0000: 4588 00b0 23ad 0000 4011 xxxx xxxx xxxx 0x0010: xxxx xxxx ca6c ca6c 009c 888f 0100 0000 0x0020: 2a7b ac07 6d64 422c e2d0 7eb5 5e9d a0aa 0x0030: 6231 c432 8724 d075 7985 8047 5b35 f43a 0x0040: 1e99 4f2b f2f0 d747 c6f9 4e51 0464 3e7c 0x0050: e943 c7a8 ec3b 9267 2f69 9751 eb79 2436 0x0060: a838 13ae 159e 314c 9f44 2bd8 6797 139e 0x0070: 7e4f a059 8eab c125 fca7 e071 6c4d 272e 0x0080: bde2 9471 21ce 8778 5570 9a76 6cf5 c2e4 0x0090: 4026 788d 74c4 6fd0 7bc9 26e2 c5c7 793c 0x00a0: 0000 0000 0000 0000 0000 0000 0000 0000 00:43:13.205687 IP bob.example.com.51820 > alice.example.com.51820: UDP, length 92 0x0000: 4588 0078 fd9f 0000 3711 xxxx xxxx xxxx 0x0010: xxxx xxxx ca6c ca6c 0064 77d7 0200 0000 0x0020: 361f 3634 2a7b ac07 0664 5105 54ea af29 0x0030: 01b5 5497 c882 e6f8 d1d9 ea95 10e9 035d 0x0040: 70a7 72a3 1206 295f 9749 4399 4eca 7f8f 0x0050: 3452 8ff1 ea91 bb54 29d5 5417 bdf3 6361 0x0060: 6fbc 4197 a17c cf98 0000 0000 0000 0000 0x0070: 0000 0000 0000 0000 00:43:13.205983 IP alice.example.com.51820 > bob.example.com.51820: UDP, length 128 0x0000: 4500 009c 23b6 0000 4011 xxxx xxxx xxxx 0x0010: xxxx xxxx ca6c ca6c 0088 887b 0400 0000 0x0020: 361f 3634 0000 0000 0000 0000 6265 0e85 0x0030: 0f77 6b8c 13fb 1c1e 42a0 626d ff07 b5bb 0x0040: 27bb ceb0 677b d98f bc6e 79b3 5318 87d6 0x0050: af39 daf1 c63e f843 19bc 2dd1 02b7 6cde 0x0060: c292 6cb2 254e 87f2 7b3a 788b c9ee 6a5b 0x0070: 5e68 7eb9 5741 b9dc 9d84 fd42 54ab bb17 0x0080: edf0 eae4 715b b097 def6 28e2 790e 73c1

Slide 105

Slide 105 text

00:43:13.196699 IP alice.example.com.51820 > bob.example.com.51820: UDP, length 148 0x0000: 4588 00b0 23ad 0000 4011 xxxx xxxx xxxx 0x0010: xxxx xxxx ca6c ca6c 009c 888f 0100 0000 0x0020: 2a7b ac07 6d64 422c e2d0 7eb5 5e9d a0aa 0x0030: 6231 c432 8724 d075 7985 8047 5b35 f43a 0x0040: 1e99 4f2b f2f0 d747 c6f9 4e51 0464 3e7c 0x0050: e943 c7a8 ec3b 9267 2f69 9751 eb79 2436 0x0060: a838 13ae 159e 314c 9f44 2bd8 6797 139e 0x0070: 7e4f a059 8eab c125 fca7 e071 6c4d 272e 0x0080: bde2 9471 21ce 8778 5570 9a76 6cf5 c2e4 0x0090: 4026 788d 74c4 6fd0 7bc9 26e2 c5c7 793c 0x00a0: 0000 0000 0000 0000 0000 0000 0000 0000 00:43:13.205687 IP bob.example.com.51820 > alice.example.com.51820: UDP, length 92 0x0000: 4588 0078 fd9f 0000 3711 xxxx xxxx xxxx 0x0010: xxxx xxxx ca6c ca6c 0064 77d7 0200 0000 0x0020: 361f 3634 2a7b ac07 0664 5105 54ea af29 0x0030: 01b5 5497 c882 e6f8 d1d9 ea95 10e9 035d 0x0040: 70a7 72a3 1206 295f 9749 4399 4eca 7f8f 0x0050: 3452 8ff1 ea91 bb54 29d5 5417 bdf3 6361 0x0060: 6fbc 4197 a17c cf98 0000 0000 0000 0000 0x0070: 0000 0000 0000 0000 00:43:13.205983 IP alice.example.com.51820 > bob.example.com.51820: UDP, length 128 0x0000: 4500 009c 23b6 0000 4011 xxxx xxxx xxxx 0x0010: xxxx xxxx ca6c ca6c 0088 887b 0400 0000 0x0020: 361f 3634 0000 0000 0000 0000 6265 0e85 0x0030: 0f77 6b8c 13fb 1c1e 42a0 626d ff07 b5bb 0x0040: 27bb ceb0 677b d98f bc6e 79b3 5318 87d6 0x0050: af39 daf1 c63e f843 19bc 2dd1 02b7 6cde 0x0060: c292 6cb2 254e 87f2 7b3a 788b c9ee 6a5b 0x0070: 5e68 7eb9 5741 b9dc 9d84 fd42 54ab bb17 0x0080: edf0 eae4 715b b097 def6 28e2 790e 73c1 ΦϨϯδ৭ͷ෦෼͕*1ϔομ ࢵ৭ͷ෦෼͕6%1ϔομ *OJUJBUPS)FMMP 3FTQPOEFS)FMMP 5SBOTQPSU%BUB ௨৴಺༰͸όϨͳ͍͚Ͳ WireGuardͰ௨৴͍ͯ͠Δࣄ͸όϨόϨ

Slide 106

Slide 106 text

·ͱΊ WireGuard͸ͱͯ΋γϯϓϧͳ͕Β VPN͕උ͑Δ΂͖Ұ௨ΓͷػೳΛඋ͑ͨ ৽͍͠L3VPNͷख๏ ͦͷ࢓༷͸ ௨৴ͷ֊૚ߏ଄ͷ؍఺͔ΒݟΔͱ៉ྷͰ͸ͳ͍͕ ߹ཧతͰ͋Δ