$30 off During Our Annual Pro Sale. View Details »

ネットワークのことを知るため ソフトウェアルータを 自作した話

kobatako
March 31, 2019

ネットワークのことを知るため ソフトウェアルータを 自作した話

kobatako

March 31, 2019
Tweet

More Decks by kobatako

Other Decks in Technology

Transcript

  1. ωοτϫʔΫͷ͜ͱΛ஌ΔͨΊ
    ιϑτ΢ΣΞϧʔλΛ
    ࣗ࡞ͨ͠࿩
    PHPerKaigi 2019
    2019/3/30ʢ౔ʣ
    খݪਸ׮

    View Slide

  2. ࣗݾ঺հ
    • ໊લ : খݪ ਸ׮ʢ͜͹Δ ͔ͨͻΖʣ
    • ॴଐ : גࣜձࣾFusic
    • ࢓ࣄ : PHPɺGolangɺAWS
    • झຯ : ElixirɺErlangɺΠϯϑϥ͍Ζ͍Ζ
    • Twitter : kobatako_

    View Slide

  3. ͸͡ΊʹͰ͕͢ɾɾɾ

    View Slide

  4. ωοτϫʔΫҙࣝͯ͠
    ·͔͢ʁ

    View Slide

  5. ωοτϫʔΫ޷͖Ͱ͔͢ʁ

    View Slide

  6. ωοτϫʔΫେ޷͖
    Ͱ͢ΑͶʁ

    View Slide

  7. ͦΜͳΈΜͳେ޷͖
    ωοτϫʔΫʹؔ͢Δ
    ࿩Λ͠·͢

    View Slide

  8. ΞδΣϯμ
    • ωοτϫʔΫͱϧʔλͷؔ܎
    • ϧʔλͷ࣮૷ʢErlangʣ
    • Ϟδϡʔϧͷ࣮૷ʢElixirʣ
    • ·ͱΊ

    View Slide

  9. ωοτϫʔΫͱϧʔλͷ
    ؔ܎

    View Slide

  10. Λཧղ͢ΔͨΊʹϧʔλ͕ԿΛ

    ΍͍ͬͯΔͷ͔

    View Slide

  11. σʔλʢύέοτʣΛ̎ͭҎ্ͷҟͳΔ
    ωοτϫʔΫؒΛதܧɺ
    ͦͷͨΊͷૹ৴ઌΛ൑அͯ͘͠ΕΔ

    View Slide

  12. σʔλʢύέοτʣΛ̎ͭҎ্ͷҟͳΔ
    ωοτϫʔΫؒΛதܧɺ
    ͦͷͨΊͷૹ৴ઌΛ൑அͯ͘͠ΕΔ

    View Slide

  13. ϧʔλ͸ωοτϫʔΫؒΛͭͳ͙

    View Slide

  14. ૹ৴ઌΛ൑அ = ϧʔςΟϯά

    View Slide

  15. ϧʔςΟϯάΛཧղ͢Ε͹
    ϧʔλͷ͜ͱ͕Θ͔Γ
    ωοτϫʔΫͷ͜ͱ΋
    ෼͔ͬͯ͘ΔͷͰ͸ɾɾɾ

    View Slide

  16. ϧʔςΟϯάͱ͸

    View Slide

  17. ϧʔςΟϯά
    • ύέοτΛૹ৴ઌͱͳΔϗετʹసૹ͢ΔͨΊ
    ࠷దͳܦ࿏Λબ୒͢Δ
    • IPΞυϨεΛར༻

    View Slide

  18. ϧʔςΟϯάʹؔ͢Δ΋ͷ
    • ϧʔςΟϯάςʔϒϧ
    • ϧʔτ৘ใ͕อଘ͞Ε͍ͯΔςʔϒϧ
    • ελςΟοΫϧʔςΟϯά
    • ؅ཧऀ͕௚઀ઃఆͨ͠ϧʔτ৘ใ
    • μΠφϛοΫϧʔςΟϯά
    • ϧʔςΟϯάϓϩτίϧ͔Βऔಘͨ͠ϧʔτ৘ใ

    View Slide

  19. ϧʔςΟϯάʹؔ͢Δ΋ͷ
    • ϧʔςΟϯάςʔϒϧͷྫ
    ৘ใݯ Ѽઌϧʔτ αϒωοτϚεΫ AD ϝτϦοΫ ωΫετϗοϓ ग़ྗIF
    C 192.168.0.0 255.255.255.0 0 0 - Eth0
    C 192.168.10.0 255.255.255.0 0 0 - Eth1
    S 192.168.30.0 255.255.255.0 1 0 192.168.10.1 Eth1
    R 192.168.40.0 255.255.255.0 120 1 192.168.0.1 Eth0
    R 192.168.40.0 255.255.255.0 120 4 192.168.10.1 Eth1

    View Slide

  20. ϧʔλͷ࣮૷
    ʢErlangʣ

    View Slide

  21. ࣮૷ͨ͠಺༰ʹ͍ͭͯ

    View Slide

  22. ॲཧϑϩʔ
    ύέοτͷड৴ -͕*1͔֬ೝ νΣοΫαϜͷ֬ೝ
    55-Λ 55-͕͔Ͳ͏͔֬ೝ νΣοΫαϜͷ࠶ܭࢉ
    ωΫετϗοϓͷ."$
    ΞυϨεͷऔಘ
    -ͷϔομʔΛ࡞੒ ύέοτΛૹ৴
    -ͷॲཧ
    ※ϧʔςΟϯάॲཧΛ૝ఆ
    ϧʔςΟϯάςʔϒϧ
    ͔Βϧʔτ৘ใΛऔಘ

    View Slide

  23. ॲཧϑϩʔ
    ύέοτͷड৴ -͕*1͔֬ೝ νΣοΫαϜͷ֬ೝ
    55-Λ 55-͕͔Ͳ͏͔֬ೝ νΣοΫαϜͷ࠶ܭࢉ
    ωΫετϗοϓͷ."$
    ΞυϨεͷऔಘ
    -ͷϔομʔΛ࡞੒ ύέοτΛૹ৴
    -ͷॲཧ
    ※ϧʔςΟϯάॲཧΛ૝ఆ
    ϧʔςΟϯάςʔϒϧ
    ͔Βϧʔτ৘ใΛऔಘ

    View Slide

  24. ͲͷΑ͏ʹͯ͠
    ϧʔςΟϯάςʔϒϧ͔Β
    ϧʔτ৘ใΛऔಘ͢Δͷ͔

    View Slide

  25. ܾΊΔͱ͖ͷ༏ઌॱ
    1. ϩϯήετϚον
    ૹ৴ઌIP͕ϧʔςΟϯάςʔϒϧͷѼઌϧʔτͰ࠷΋௕͘
    Ϛον͢Δϧʔτ৘ใ
    2. ADʢΞυϛχετϨʔςΟϒσΟελϯεʣ
    ৘ใݯͷ৴པੑ
    3. ϝτϦοΫ
    ࠷దܦ࿏Λબ୒͢ΔͨΊʹ࢖༻͞ΕΔ஋

    View Slide

  26. ܾΊΔͱ͖ͷ༏ઌॱ
    • ϩϯήετϚονͷྫ
    • ૹ৴ઌ͕192.168.10.1ʹରͯ͠ϧʔςΟϯάςʔϒϧ͕

    Լهͷ৔߹
    • ѼઌωοτϫʔΫ : 192.168.0.0/16
    • ѼઌωοτϫʔΫ : 192.168.10.0/24

    -> 192.168.10.0ͷѼઌϧʔτΛ࣋ͭϧʔτ৘ใ͕

    ࢀর͞ΕΔ
    ৘ใݯ Ѽઌϧʔτ αϒωοτϚεΫ AD ϝτϦοΫ ωΫετϗοϓ ग़ྗIF
    S 192.168.0.0 255.255.0.0 1 0 192.168.0.1 Eth0
    R 192.168.10.0 255.255.255.0 120 0 192.168.10.1 Eth1

    View Slide

  27. ܾΊΔͱ͖ͷ༏ઌॱ
    • ΞυϛχετϨʔςΟϒσΟελϯεʢADʣ
    • ৘ใݯͷ৴༻౓
    • ADͷ஋͕௿͍΋ͷ͕༏ઌ͞ΕΔ

    View Slide

  28. ܾΊΔͱ͖ͷ༏ઌॱ
    • ྫɿCiscoػثʹ͓͚ΔσϑΥϧτͷAD஋
    ߴ
    ௿
    ৘ใݯ σϑΥϧτͷAD஋
    ઀ଓ͞Ε͍ͯΔΠϯλʔϑΣΠε 0
    ελςΟοΫϧʔςΟϯά 1
    αϚϦʔϧʔτ 5
    ֎෦BGP 20
    IGRP 100
    OSPF 110
    RIP 120
    EGP 140
    ಺෦BGP 200
    ෆ໌ 255

    View Slide

  29. ܾΊΔͱ͖ͷ༏ઌॱ
    • ϝτϦοΫ
    • ҰͭͷϧʔςΟϯάϓϩτίϧͰෳ਺ܦ࿏Λ࣋ͭ৔߹ɺͦΕͧΕͷ

    ܦ࿏͝ͱͷ༏ઌ౓
    • খ͍͞ํ͕༏ઌ͞ΕΔ
    • ϧʔςΟϯάϓϩίτϧ͝ͱʹϝτϦοΫͷѻ͍ํ͕มΘͬͯ͘Δ
    • RIP : ϗοϓ਺
    • OSPF : ίετ

    View Slide

  30. ৘ใݯ Ѽઌϧʔτ αϒωοτϚεΫ AD ϝτϦοΫ ωΫετϗοϓ ग़ྗIF
    C 192.168.0.0 255.255.255.0 0 0 - Eth0
    C 192.168.10.0 255.255.255.0 0 0 - Eth1
    S 192.168.30.0 255.255.255.0 1 0 192.168.10.1 Eth1
    R 192.168.40.0 255.255.255.0 120 1 192.168.0.1 Eth0
    R 192.168.40.0 255.255.255.0 120 4 192.168.10.1 Eth1
    ܾΊΔͱ͖ͷ༏ઌॱ
    1. ϩϯήετϚον

    View Slide

  31. ৘ใݯ Ѽઌϧʔτ αϒωοτϚεΫ AD ϝτϦοΫ ωΫετϗοϓ ग़ྗIF
    C 192.168.0.0 255.255.255.0 0 0 - Eth0
    C 192.168.10.0 255.255.255.0 0 0 - Eth1
    S 192.168.30.0 255.255.255.0 1 0 192.168.10.1 Eth1
    R 192.168.40.0 255.255.255.0 120 1 192.168.0.1 Eth0
    R 192.168.40.0 255.255.255.0 120 4 192.168.10.1 Eth1
    ܾΊΔͱ͖ͷ༏ઌॱ
    2. AD஋Λൺֱ

    View Slide

  32. ৘ใݯ Ѽઌϧʔτ αϒωοτϚεΫ AD ϝτϦοΫ ωΫετϗοϓ ग़ྗIF
    C 192.168.0.0 255.255.255.0 0 0 - Eth0
    C 192.168.10.0 255.255.255.0 0 0 - Eth1
    S 192.168.30.0 255.255.255.0 1 0 192.168.10.1 Eth1
    R 192.168.40.0 255.255.255.0 120 1 192.168.0.1 Eth0
    R 192.168.40.0 255.255.255.0 120 4 192.168.10.1 Eth1
    ܾΊΔͱ͖ͷ༏ઌॱ
    3. ϝτϦοΫͷൺֱ

    View Slide

  33. ErlangͰͷ࣮૷

    View Slide

  34. ϧʔςΟϯάॲཧ
    2. 1Ͱऔಘͨ͠ϧʔτ৘ใ͔ΒҰ൪༏ઌ౓ͷߴ͍

    ϧʔτ৘ใΛऔಘ
    1. ૹ৴ઌIP͕ϧʔςΟϯάςʔϒϧͷѼઌϧʔτʹ
    Ϛον͢ΔϦετΛऔಘ
    3. 2Ͱऔಘͨ͠ϧʔτ৘ใͷωΫετϗοϓ

    ʹૹ৴͢Δ

    View Slide

  35. ϧʔςΟϯάॲཧ
    2. 1Ͱऔಘͨ͠ϧʔτ৘ใ͔ΒҰ൪༏ઌ౓ͷߴ͍

    ϧʔτ৘ใΛऔಘ
    1. ૹ৴ઌIP͕ϧʔςΟϯάςʔϒϧͷѼઌϧʔτʹ
    Ϛον͢ΔϦετΛऔಘ
    3. 2Ͱऔಘͨ͠ϧʔτ৘ใͷωΫετϗοϓ

    ʹૹ৴͢Δ

    View Slide

  36. ϧʔςΟϯάॲཧ
    • ྫɿύέοτͷૹ৴ઌ͕192.168.10.1ͷ৔߹ʹ

    ɹɹ౰ͯ͸·Δϧʔτ৘ใ
    Ѽઌϧʔτ αϒωοτϚεΫ ݁Ռ
    192.168.0.0 255.255.0.0 ౰ͯ͸·Δ
    192.168.10.0 255.255.255.0 ౰ͯ͸·Δ
    192.168.20.0 255.255.255.0 ౰ͯ͸·Βͳ͍

    View Slide

  37. ϧʔςΟϯάॲཧ
    ૹ৴ઌIP͕ϧʔςΟϯάςʔϒϧͷѼઌϧʔτʹ
    ౰ͯ͸·ͬͯΔ΋ͷͷϦετΛऔಘ
    % ୈҰҾ਺ : ϧʔςΟϯάςʔϒϧ಺ͷશϦετʢarrayʣ
    % ୈೋҾ਺ : ѼઌͷIPʢintegerʣ
    % ୈࡾҾ਺ : ૹ৴ઌީิʢѼઌͱ൑அ͞Εͨʣͷϧʔτ৘ใʢarrayʣ
    match_dest_ip([], _, List) ->
    List;
    match_dest_ip([{_, _, _, Ip, _, Subnetmask, Ad, Metric, Nexthop, _, If}| Tail], DestIp,
    List) when is_integer(DestIp) ->
    case DestIp band Subnetmask of
    Ip ->
    match_dest_ip(Tail, DestIp, [{If, Nexthop, Subnetmask, Ad, Metric}|List]);
    _ ->
    match_dest_ip(Tail, DestIp, List)
    end.

    View Slide

  38. ϧʔςΟϯάॲཧ
    % ୈҰҾ਺ : ϧʔςΟϯάςʔϒϧ಺ͷશϦετʢarrayʣ
    % ୈೋҾ਺ : ѼઌͷIPʢintegerʣ
    % ୈࡾҾ਺ : ૹ৴ઌީิʢѼઌͱ൑அ͞Εͨʣͷϧʔτ৘ใʢarrayʣ
    match_dest_ip([], _, List) ->
    List;
    match_dest_ip([{_, _, _, Ip, _, Subnetmask, Ad, Metric, Nexthop, _, If}| Tail], DestIp,
    List) when is_integer(DestIp) ->
    case DestIp band Subnetmask of
    Ip ->
    match_dest_ip(Tail, DestIp, [{If, Nexthop, Subnetmask, Ad, Metric}|List]);
    _ ->
    match_dest_ip(Tail, DestIp, List)
    end.
    1. ѼઌIPͱαϒωοτϚεΫͷandॲཧ
    ૹ৴ઌIP͕ϧʔςΟϯάςʔϒϧͷѼઌϧʔτʹ
    ౰ͯ͸·ͬͯΔ΋ͷͷϦετΛऔಘ

    View Slide

  39. ϧʔςΟϯάॲཧ
    % ୈҰҾ਺ : ϧʔςΟϯάςʔϒϧ಺ͷશϦετʢarrayʣ
    % ୈೋҾ਺ : ѼઌͷIPʢintegerʣ
    % ୈࡾҾ਺ : ૹ৴ઌީิʢѼઌͱ൑அ͞Εͨʣͷϧʔτ৘ใʢarrayʣ
    match_dest_ip([], _, List) ->
    List;
    match_dest_ip([{_, _, _, Ip, _, Subnetmask, Ad, Metric, Nexthop, _, If}| Tail], DestIp,
    List) when is_integer(DestIp) ->
    case DestIp band Subnetmask of
    Ip ->
    match_dest_ip(Tail, DestIp, [{If, Nexthop, Subnetmask, Ad, Metric}|List]);
    _ ->
    match_dest_ip(Tail, DestIp, List)
    end.
    2. 1ͷ݁ՌͱIp͕౳͍͔͠Ͳ͏͔
    ૹ৴ઌIP͕ϧʔςΟϯάςʔϒϧͷѼઌϧʔτʹ
    ౰ͯ͸·ͬͯΔ΋ͷͷϦετΛऔಘ

    View Slide

  40. ϧʔςΟϯάॲཧ
    2. 1Ͱऔಘͨ͠ϧʔτ৘ใ͔ΒҰ൪༏ઌ౓ͷߴ͍

    ϧʔτ৘ใΛऔಘ
    1. ૹ৴ઌIP͕ϧʔςΟϯάςʔϒϧͷѼઌϧʔτʹ
    Ϛον͢ΔϦετΛऔಘ
    3. 2Ͱऔಘͨ͠ϧʔτ৘ใͷωΫετϗοϓ

    ʹૹ৴͢Δ

    View Slide

  41. ϧʔςΟϯάॲཧ
    • ѼઌͱͳΔϧʔτ৘ใΛ࠶ؼॲཧʹͯऔಘɺͦͷ࣌ͷ༏ઌ౓
    1. ૹ৴ઌIP͕௚઀ܨ͕͍ͬͯΔωοτϫʔΫʹؚ·Ε͍ͯΔ΋ͷ
    2. αϒωοτϚεΫʢϓϨϑΟοΫε௕ʣ͕Ұ൪௕͍΋ͷ
    3. αϒωοτϚεΫ͕౳͘͠ AD஋͕খ͍͞΋ͷ
    4. αϒωοτϚεΫɺAD஋͕౳͘͠ɺϝτϦοΫ͕খ͍͞΋ͷ

    View Slide

  42. ϧʔςΟϯάॲཧ
    ѼઌIP͕௚઀ܨ͕͍ͬͯΔωοτϫʔΫʹؚ·Ε͍ͯΔ΋ͷ
    ϧʔτ৘ใͷѼઌ͕ʮNEXTHOP_DIRECTʯͷ৔߹͸௚઀ܨ͕͍ͬͯΔωοτϫʔΫ಺ʹ

    ଐ͍ͯ͠Δʢ৘ใݯ͕ʮCʯͷ΋ͷʣ
    AD͕0ͷ৔߹͸௚઀ܨ͕͍ͬͯΔωοτϫʔΫ಺ʹଐ͍ͯ͠Δʢ৘ใݯ͕ʮCʯͷ΋ͷʣ
    %% fetch to destination route
    % ୈҰҾ਺ : ϧʔτ৘ใʢarrayʣ
    % ୈೋҾ਺ : ݱࡏͷҰ൪༏ઌ౓͕ߴ͍ϧʔτ৘ใ
    fetch_dest_route([{_, ?NEXTHOP_DIRECT, _, _, _}=Route| _], _) ->
    Route;
    % ad 0
    fetch_dest_route([{_, _, _, 0, _}=Route| _], _) ->
    Route;
    ௚઀ܨ͕͍ͬͯΔωοτϫʔΫ

    View Slide

  43. ϧʔςΟϯάॲཧ
    ݱࡏͷϧʔτ৘ใΑΓαϒωοτϚεΫ͕௕͍ϧʔτ৘ใ͕

    ͋Δ৔߹ɺҰ൪༏ઌ౓͕ߴ͍΋ͷͱ͢Δ
    %% fetch to destination route
    % ୈҰҾ਺ : ϧʔτ৘ใʢarrayʣ
    % ୈೋҾ਺ : ݱࡏͷҰ൪༏ઌ౓͕ߴ͍ϧʔτ৘ใ
    fetch_dest_route([{_, _, Subnet, _, _}=Route| Tail],{_, _, NowSubnet, _, _})
    when Subnet > NowSubnet ->
    fetch_dest_route(Tail, Route);
    αϒωοτϚεΫͷൺֱ

    View Slide

  44. ϧʔςΟϯάॲཧ
    ݱࡏͷϧʔτ৘ใͱൺֱ͠αϒωοτϚεΫ͕౳͘͠

    AD஋͕খ͍͞৔߹Ұ൪༏ઌ౓͕ߴ͍΋ͷͱ͢Δ
    %% fetch to destination route
    % ୈҰҾ਺ : ϧʔτ৘ใʢarrayʣ
    % ୈೋҾ਺ : ݱࡏͷҰ൪༏ઌ౓͕ߴ͍ϧʔτ৘ใ
    fetch_dest_route([{_, _, Subnet, Ad, _}=Route| Tail], {_, _, Subnet, NowAd,
    _}) when Ad < NowAd ->
    fetch_dest_route(Tail, Route);
    AD஋Λൺֱ

    View Slide

  45. ϧʔςΟϯάॲཧ
    ݱࡏͷϧʔτ৘ใͱൺֱ͠αϒωοτϚεΫͱAD஋͕౳͘͠

    ϝτϦοΫ͕খ͍͞৔߹Ұ൪༏ઌ౓͕ߴ͍΋ͷͱ͢Δ
    %% fetch to destination route
    % ୈҰҾ਺ : ϧʔτ৘ใʢarrayʣ
    % ୈೋҾ਺ : ݱࡏͷҰ൪༏ઌ౓͕ߴ͍ϧʔτ৘ใ
    fetch_dest_route([{_, _, Subnet, Ad, Metric}=Route| Tail],{_, _, Subnet, Ad,
    NowMetric}) when Metric < NowMetric ->
    fetch_dest_route(Tail, Route);
    ϝτϦοΫΛൺֱ

    View Slide

  46. ϧʔςΟϯάॲཧ
    2. 1Ͱऔಘͨ͠ϧʔτ৘ใ͔ΒҰ൪༏ઌ౓ͷߴ͍

    ϧʔτ৘ใΛऔಘ
    1. ૹ৴ઌIP͕ϧʔςΟϯάςʔϒϧͷѼઌϧʔτʹ
    Ϛον͢ΔϦετΛऔಘ
    3. 2Ͱऔಘͨ͠ϧʔτ৘ใͷωΫετϗοϓ

    ʹૹ৴͢Δ

    View Slide

  47. ϧʔςΟϯάॲཧ
    ARPςʔϒϧ͔ΒωΫετϗοϓͷIPʹඥͮ͘ɺMACΞυϨεΛ

    औಘ͢Δ
    get_mac_addr({_, Nexthop}) ->
    % ARPςʔϒϧ͔ΒωΫετϗοϓʹඥͮ͘MACΞυϨεΛऔಘ
    case brook_arp_table:fetch_dest_mac_addr(Nexthop, false) of
    % ଘࡏͯ͠ͳ͍৔߹͸ɺʮundefinedʯΛฦ͢
    [] ->
    undefined;
    % ଘࡏͯ͠Δ৔߹͸ɺMACΞυϨεΛฦ͢
    [{arp_table, _, _, DestMac, _}| _] ->
    DestMac
    end.

    View Slide

  48. ϧʔςΟϯάॲཧ
    L2ϔομʔͷૹ৴ઌMACΞυϨεΛωΫετϗοϓɺ

    ૹ৴ݩMACΞυϨεΛࣗ෼ࣗ਎ʢΠϯλʔϑΣΠεʣ΁ͱ

    ॻ͖׵͑Δ
    ip_request(FD, #{source_mac := SourceMac, dest_mac := DestMac}=Opt, Data) ->
    Ethernet = ethernet_to_binary(#ethernet_header{
    source_mac_addr=tuple_to_list(SourceMac),
    dest_mac_addr=DestMac,
    type=?TYPE_IP}
    ),
    request(FD, <>, Opt)
    L2ͷύέοτϔομʔΛ࡞੒

    View Slide

  49. Ϟδϡʔϧ࣮૷
    ʢElixirʣ

    View Slide

  50. ϧʔλʹ֦ுੑΛ࣋ͨͤΔͨΊɺ
    ErlangͰPipelineॲཧͷ

    ࣮૷Λ͠·ͨ͠

    View Slide

  51. Pipelineॲཧͷ৔ॴ
    ύέοτͷड৴ -͕*1͔֬ೝ νΣοΫαϜͷ֬ೝ
    55-Λ 55-͕͔Ͳ͏͔֬ೝ νΣοΫαϜͷ࠶ܭࢉ
    ωΫετϗοϓͷ."$
    ΞυϨεͷऔಘ
    -ͷϔομʔΛ࡞੒ ύέοτΛૹ৴
    -ͷॲཧ
    ϧʔςΟϯάςʔϒϧ
    ͔Βϧʔτ৘ใΛऔಘ



    View Slide

  52. Pipelineॲཧͷ৔ॴ
    1. IPύέοτͷॲཧલ
    2. L4ϨΠϠʔͷॲཧલ
    3. L4ϨΠϠʔͷॲཧޙ
    4. IPύέοτͷॲཧޙ
    5. ύέοτͷૹ৴ޙ

    View Slide

  53. Ϟδϡʔϧͱ࣮ͯ͠૷ͨ͠΋ͷ
    • FirewallʢPipelineΛར༻ʣ
    • ύέοτϩεʢPipelineΛར༻ʣ
    • ϦϓϥΠʢPipelineΛར༻ʣ
    • ஗Ԇૹ৴ʢPipelineΛར༻ʣ
    • ελςΟοΫϧʔςΟϯάͷΠϯλʔϑΣΠε

    View Slide

  54. FirewallϞδϡʔϧͷ
    ࣮૷ྫ

    View Slide

  55. FirewallϞδϡʔϧ
    ύέοτͷड৴ -͕*1͔֬ೝ νΣοΫαϜͷ֬ೝ
    55-Λ 55-͕͔Ͳ͏͔֬ೝ νΣοΫαϜͷ࠶ܭࢉ
    ωΫετϗοϓͷ."$
    ΞυϨεͷऔಘ
    -ͷϔομʔΛ࡞੒ ύέοτΛૹ৴
    -ͷॲཧ
    ϧʔςΟϯάςʔϒϧ
    ͔Βϧʔτ৘ใΛऔಘ
    ͜͜ʹFirewallͷॲཧΛPipelineͱͯ͠௥Ճ͢Δ

    View Slide

  56. FirewallϞδϡʔϧ
    • ४උɿErlangଆͰPipelineॲཧΛ࣮ߦͰ͖ΔΑ͏ʹ͢Δ
    save_before_ip_pipeline(Func) when is_function(Func, 2) ->
    mnesia:transaction(fun() ->
    mnesia:write(pipeline, #pipeline{type=?BEFORE_IP, module=undefined, func=Func}, write)
    end)
    before_ip_pipeline(Data, Opt) ->
    Filter = mnesia:dirty_match_object(pipeline,
    {'_', ?BEFORE_IP, '$1', '$2'}
    ),
    pipeline(Filter, Data, Opt)
    pipeline([#pipeline{module=undefined, func=Func}| Tail], Data0, Opt0) ->
    case apply(Func, [Data0, Opt0]) of
    {error, Msg} ->
    {error, Msg};
    {ok, Data, Opt} ->
    pipeline(Tail, Data, Opt)
    end;

    View Slide

  57. FirewallϞδϡʔϧ
    • ४උɿErlangଆͰPipelineॲཧΛ࣮ߦͰ͖ΔΑ͏ʹ͢Δ
    save_before_ip_pipeline(Func) when is_function(Func, 2) ->
    mnesia:transaction(fun() ->
    mnesia:write(pipeline, #pipeline{type=?BEFORE_IP, module=undefined, func=Func}, write)
    end)
    before_ip_pipeline(Data, Opt) ->
    Filter = mnesia:dirty_match_object(pipeline,
    {'_', ?BEFORE_IP, '$1', '$2'}
    ),
    pipeline(Filter, Data, Opt)
    pipeline([#pipeline{module=undefined, func=Func}| Tail], Data0, Opt0) ->
    case apply(Func, [Data0, Opt0]) of
    {error, Msg} ->
    {error, Msg};
    {ok, Data, Opt} ->
    pipeline(Tail, Data, Opt)
    end;
    PipelineʹॲཧΛొ࿥

    View Slide

  58. FirewallϞδϡʔϧ
    • ४උɿErlangଆͰPipelineॲཧΛ࣮ߦͰ͖ΔΑ͏ʹ͢Δ
    save_before_ip_pipeline(Func) when is_function(Func, 2) ->
    mnesia:transaction(fun() ->
    mnesia:write(pipeline, #pipeline{type=?BEFORE_IP, module=undefined, func=Func}, write)
    end)
    before_ip_pipeline(Data, Opt) ->
    Filter = mnesia:dirty_match_object(pipeline,
    {'_', ?BEFORE_IP, '$1', '$2'}
    ),
    pipeline(Filter, Data, Opt)
    pipeline([#pipeline{module=undefined, func=Func}| Tail], Data0, Opt0) ->
    case apply(Func, [Data0, Opt0]) of
    {error, Msg} ->
    {error, Msg};
    {ok, Data, Opt} ->
    pipeline(Tail, Data, Opt)
    end;
    Pipelineͷ࣮ߦ

    View Slide

  59. FirewallϞδϡʔϧ
    • ४උɿErlangଆͰPipelineॲཧΛ࣮ߦͰ͖ΔΑ͏ʹ͢Δ
    save_before_ip_pipeline(Func) when is_function(Func, 2) ->
    mnesia:transaction(fun() ->
    mnesia:write(pipeline, #pipeline{type=?BEFORE_IP, module=undefined, func=Func}, write)
    end)
    before_ip_pipeline(Data, Opt) ->
    Filter = mnesia:dirty_match_object(pipeline,
    {'_', ?BEFORE_IP, '$1', '$2'}
    ),
    pipeline(Filter, Data, Opt)
    pipeline([#pipeline{module=undefined, func=Func}| Tail], Data0, Opt0) ->
    case apply(Func, [Data0, Opt0]) of
    {error, Msg} ->
    {error, Msg};
    {ok, Data, Opt} ->
    pipeline(Tail, Data, Opt)
    end;
    Pipelineʹొ࿥ͨ͠ॲཧΛ࣮ߦ͍ͯ͘͠

    View Slide

  60. FirewallϞδϡʔϧ
    • ४උɿErlangଆͰPipelineॲཧΛ࣮ߦͰ͖ΔΑ͏ʹ͢Δ
    save_before_ip_pipeline(Func) when is_function(Func, 2) ->
    mnesia:transaction(fun() ->
    mnesia:write(pipeline, #pipeline{type=?BEFORE_IP, module=undefined, func=Func}, write)
    end)
    before_ip_pipeline(Data, Opt) ->
    Filter = mnesia:dirty_match_object(pipeline,
    {'_', ?BEFORE_IP, '$1', '$2'}
    ),
    pipeline(Filter, Data, Opt)
    pipeline([#pipeline{module=undefined, func=Func}| Tail], Data0, Opt0) ->
    case apply(Func, [Data0, Opt0]) of
    {error, Msg} ->
    {error, Msg};
    {ok, Data, Opt} ->
    pipeline(Tail, Data, Opt)
    end;
    FuncʢϝιουʣΛ
    [Data0, Opt0] ͷҾ਺Ͱ࣮ߦ͢Δ

    View Slide

  61. FirewallϞδϡʔϧ
    • ४උɿErlangଆͰPipelineॲཧΛ࣮ߦͰ͖ΔΑ͏ʹ͢Δ
    save_before_ip_pipeline(Func) when is_function(Func, 2) ->
    mnesia:transaction(fun() ->
    mnesia:write(pipeline, #pipeline{type=?BEFORE_IP, module=undefined, func=Func}, write)
    end)
    before_ip_pipeline(Data, Opt) ->
    Filter = mnesia:dirty_match_object(pipeline,
    {'_', ?BEFORE_IP, '$1', '$2'}
    ),
    pipeline(Filter, Data, Opt)
    pipeline([#pipeline{module=undefined, func=Func}| Tail], Data0, Opt0) ->
    case apply(Func, [Data0, Opt0]) of
    {error, Msg} ->
    {error, Msg};
    {ok, Data, Opt} ->
    pipeline(Tail, Data, Opt)
    end;
    Τϥʔͷ৔߹͸ΤϥʔͱͳΓɺύέοτͷ
    ϧʔςΟϯάΛߦΘͳ͍
    ਖ਼ৗͷ৔߹͸ɺ࣍ͷPipelineॲཧΛ࣮ߦ

    View Slide

  62. Elixirଆͷ࣮૷

    View Slide

  63. FirewallϞδϡʔϧ
    • Firewallͷ৚݅ΛϝλϓϩάϥϜͰ࣮૷
    firewall :default do
    allow(
    source_ip: {192, 168, 20, 0},
    source_netmask: {255, 255, 255, 0},
    protocol: :ip
    )
    allow(
    source_ip: {192, 168, 40, 0},
    source_netmask: {255, 255, 255, 0},
    protocol: :tcp
    )
    deny()
    end

    View Slide

  64. FirewallϞδϡʔϧ
    • Firewallͷ৚݅ΛϝλϓϩάϥϜͰ࣮૷
    firewall :default do
    allow(
    source_ip: {192, 168, 20, 0},
    source_netmask: {255, 255, 255, 0},
    protocol: :ip
    )
    allow(
    source_ip: {192, 168, 40, 0},
    source_netmask: {255, 255, 255, 0},
    protocol: :tcp
    )
    deny()
    end
    ڐՄ͢Δύέοτ৘ใ
    ʢૹ৴ݩIPͱ͔ϓϩτίϧͱ͔ʣ

    View Slide

  65. FirewallϞδϡʔϧ
    • Firewallͷ৚݅ΛϝλϓϩάϥϜͰ࣮૷
    firewall :default do
    allow(
    source_ip: {192, 168, 20, 0},
    source_netmask: {255, 255, 255, 0},
    protocol: :ip
    )
    allow(
    source_ip: {192, 168, 40, 0},
    source_netmask: {255, 255, 255, 0},
    protocol: :tcp
    )
    deny()
    end
    શͯͷύέοτΛڋ൱͢Δ

    View Slide

  66. FirewallϞδϡʔϧ
    • Firewallॲཧͷొ࿥
    defmacro firewall_through(identifier) do
    quote do
    identifier = unquote(identifier)
    :brook_pipeline.save_before_ip_pipeline(Eshe.Firewall.firewall_filter(identifier))
    end
    end
    def firewall_filter(identifier) do
    filter = fetch_filter(Eshe.Supervisor.route_firewall(), identifier)
    fn data, option ->
    case is_allow_filter(filter, data) do
    :ok ->
    {:ok, data, option}
    error ->
    {:error, error}
    end
    end
    end

    View Slide

  67. FirewallϞδϡʔϧ
    • Firewallॲཧͷొ࿥
    defmacro firewall_through(identifier) do
    quote do
    identifier = unquote(identifier)
    :brook_pipeline.save_before_ip_pipeline(Eshe.Firewall.firewall_filter(identifier))
    end
    end
    def firewall_filter(identifier) do
    filter = fetch_filter(Eshe.Supervisor.route_firewall(), identifier)
    fn data, option ->
    case is_allow_filter(filter, data) do
    :ok ->
    {:ok, data, option}
    error ->
    {:error, error}
    end
    end
    end
    firewall_filterΛొ࿥͢Δ

    View Slide

  68. FirewallϞδϡʔϧ
    • Firewallॲཧͷొ࿥
    defmacro firewall_through(identifier) do
    quote do
    identifier = unquote(identifier)
    :brook_pipeline.save_before_ip_pipeline(Eshe.Firewall.firewall_filter(identifier))
    end
    end
    def firewall_filter(identifier) do
    filter = fetch_filter(Eshe.Supervisor.route_firewall(), identifier)
    fn data, option ->
    case is_allow_filter(filter, data) do
    :ok ->
    {:ok, data, option}
    error ->
    {:error, error}
    end
    end
    end
    Erlangଆ΁ॲཧΛฦ͠ɺΤϥʔͷ৔߹͸
    ύέοτͷॲཧΛऴྃͤ͞Δ

    View Slide

  69. FirewallϞδϡʔϧ
    • Firewallͷ൑ఆॲཧ
    def match(
    %{protocol: protocol} = record,
    <other::binary>>
    )
    when protocol in [:tcp, :udp] do
    {source_port, dest_port} = fetch_port(len, other)
    with res <- match_ip([], record[:dest_ip], record[:dest_netmask], dest_ip),
    res <- match_ip(res, record[:source_ip], record[:source_netmask], source_ip),
    res <- match_port(res, record[:source_port], source_port),
    res <- match_port(res, record[:dest_port], dest_port),
    res <- Enum.filter(res, &(&1 != nil)),
    {:ok, _value} <- Enum.fetch(res, 0) do
    Enum.all?(res, fn r -> r == true end)
    else
    _ ->
    false
    end
    end

    View Slide

  70. FirewallϞδϡʔϧ
    • Firewallͷ൑ఆॲཧ
    def match(
    %{protocol: protocol} = record,
    <other::binary>>
    )
    when protocol in [:tcp, :udp] do
    {source_port, dest_port} = fetch_port(len, other)
    with res <- match_ip([], record[:dest_ip], record[:dest_netmask], dest_ip),
    res <- match_ip(res, record[:source_ip], record[:source_netmask], source_ip),
    res <- match_port(res, record[:source_port], source_port),
    res <- match_port(res, record[:dest_port], dest_port),
    res <- Enum.filter(res, &(&1 != nil)),
    {:ok, _value} <- Enum.fetch(res, 0) do
    Enum.all?(res, fn r -> r == true end)
    else
    _ ->
    false
    end
    end
    ૹ৴ݩͱૹ৴ઌͷIP
    ૹ৴ݩͱૹ৴ઌͷϙʔτ

    View Slide

  71. FirewallϞδϡʔϧ
    • Firewallͷ൑ఆॲཧ
    def match(
    %{protocol: protocol} = record,
    <other::binary>>
    )
    when protocol in [:tcp, :udp] do
    {source_port, dest_port} = fetch_port(len, other)
    with res <- match_ip([], record[:dest_ip], record[:dest_netmask], dest_ip),
    res <- match_ip(res, record[:source_ip], record[:source_netmask], source_ip),
    res <- match_port(res, record[:source_port], source_port),
    res <- match_port(res, record[:dest_port], dest_port),
    res <- Enum.filter(res, &(&1 != nil)),
    {:ok, _value} <- Enum.fetch(res, 0) do
    Enum.all?(res, fn r -> r == true end)
    else
    _ ->
    false
    end
    end
    શͯͷൺֱ݁Ռ͕౳͍͠৔߹ͷΈtrueʹ

    View Slide

  72. ·ͱΊ

    View Slide

  73. ϧʔςΟϯάΛཧղ͢Ε͹
    ϧʔλͷ͜ͱ͕Θ͔Γ
    ωοτϫʔΫͷ͜ͱ΋
    ෼͔ͬͯ͘ΔͷͰ͸ɾɾɾ

    View Slide

  74. Θ͔Βͳ͍͜ͱ͕
    ·ͩ·ͩଟ͍ʂʂʂʂ

    View Slide

  75. ΍Εͯͳ͍͜ͱ

    View Slide

  76. ΍Εͯͳ͍͜ͱ
    • ϧʔςΟϯάϓϩτίϧͷ࣮૷ʢRIPͱ͔BGPͱ͔OSPFͱ͔ʣ

    View Slide

  77. ΍Εͯͳ͍͜ͱ
    • ϧʔςΟϯάϓϩτίϧͷ࣮૷ʢRIPͱ͔BGPͱ͔OSPFͱ͔ʣ
    • ϩϯήετϚονΞϧΰϦζϜͷ࣮૷

    View Slide

  78. ΍Εͯͳ͍͜ͱ
    • ϧʔςΟϯάϓϩτίϧͷ࣮૷ʢRIPͱ͔BGPͱ͔OSPFͱ͔ʣ
    • ϩϯήετϚονΞϧΰϦζϜͷ࣮૷
    • VRRPͷ࣮૷

    View Slide

  79. ΍Εͯͳ͍͜ͱ
    • ϧʔςΟϯάϓϩτίϧͷ࣮૷ʢRIPͱ͔BGPͱ͔OSPFͱ͔ʣ
    • ϩϯήετϚονΞϧΰϦζϜͷ࣮૷
    • VRRPͷ࣮૷
    • ARPΛ·ͩҰ෦͔࣮͠૷ͯ͠ͳ͍ɺɺɺ

    View Slide

  80. ΍Εͯͳ͍͜ͱ
    • ϧʔςΟϯάϓϩτίϧͷ࣮૷ʢRIPͱ͔BGPͱ͔OSPFͱ͔ʣ
    • ϩϯήετϚονΞϧΰϦζϜͷ࣮૷
    • VRRPͷ࣮૷
    • ARPΛ·ͩҰ෦͔࣮͠૷ͯ͠ͳ͍ɺɺɺ
    • IPSec΋࣮૷͓͖͍ͯͨ͠ʂʂ

    View Slide

  81. ·ͩ·ͩ΍Δ͜ͱ͕
    ͍ͬͺ͍ɾɾɾ

    View Slide

  82. ͨͩগ͠͸ϧʔλͷ͜ͱɺ

    ωοτϫʔΫͷ͜ͱ͕

    Θ͔ͬͨؾ͕͢Δɾɾɾʂ

    View Slide

  83. PHPer͔Βͷ
    ωοτϫʔΫʢϧʔλʣ
    ͷ࿩Ͱͨ͠

    View Slide

  84. ͝੩ௌ͋Γ͕ͱ͏

    ͍͟͝·ͨ͠

    View Slide