github.com/slackhq/nebula@v1.9.0/dist/wireshark/nebula.lua (about)

     1  local nebula = Proto("nebula", "nebula")
     2  
     3  local default_settings = {
     4      port      = 4242,
     5      all_ports = false,
     6  }
     7  
     8  nebula.prefs.port  = Pref.uint("Port number", default_settings.port, "The UDP port number for Nebula")
     9  nebula.prefs.all_ports  = Pref.bool("All ports", default_settings.all_ports, "Assume nebula packets on any port, useful when dealing with hole punching")
    10  
    11  local pf_version  = ProtoField.new("version", "nebula.version", ftypes.UINT8, nil, base.DEC, 0xF0)
    12  local pf_type     = ProtoField.new("type", "nebula.type", ftypes.UINT8, {
    13      [0] = "handshake",
    14      [1] = "message",
    15      [2] = "recvError",
    16      [3] = "lightHouse",
    17      [4] = "test",
    18      [5] = "closeTunnel",
    19  }, base.DEC, 0x0F)
    20  
    21  local pf_subtype = ProtoField.new("subtype", "nebula.subtype", ftypes.UINT8, nil, base.DEC)
    22  local pf_subtype_test = ProtoField.new("subtype", "nebula.subtype", ftypes.UINT8, {
    23      [0] = "request",
    24      [1] = "reply",
    25  }, base.DEC)
    26  
    27  local pf_subtype_handshake = ProtoField.new("subtype", "nebula.subtype", ftypes.UINT8, {
    28      [0] = "ix_psk0",
    29  }, base.DEC)
    30  
    31  local pf_reserved        = ProtoField.new("reserved",     "nebula.reserved",     ftypes.UINT16, nil, base.HEX)
    32  local pf_remote_index    = ProtoField.new("remote index", "nebula.remote_index", ftypes.UINT32, nil, base.DEC)
    33  local pf_message_counter = ProtoField.new("counter",      "nebula.counter",      ftypes.UINT64, nil, base.DEC)
    34  local pf_payload         = ProtoField.new("payload",      "nebula.payload",      ftypes.BYTES,  nil, base.NONE)
    35  
    36  nebula.fields = { pf_version, pf_type, pf_subtype, pf_subtype_handshake, pf_subtype_test, pf_reserved, pf_remote_index, pf_message_counter, pf_payload }
    37  
    38  local ef_holepunch = ProtoExpert.new("nebula.holepunch.expert", "Nebula hole punch packet", expert.group.PROTOCOL, expert.severity.NOTE)
    39  local ef_punchy = ProtoExpert.new("nebula.punchy.expert", "Nebula punchy keepalive packet", expert.group.PROTOCOL, expert.severity.NOTE)
    40  
    41  nebula.experts = { ef_holepunch, ef_punchy }
    42  local type_field = Field.new("nebula.type")
    43  local subtype_field = Field.new("nebula.subtype")
    44  
    45  function nebula.dissector(tvbuf, pktinfo, root)
    46      -- set the protocol column to show our protocol name
    47      pktinfo.cols.protocol:set("NEBULA")
    48  
    49      local pktlen = tvbuf:reported_length_remaining()
    50      local tree = root:add(nebula, tvbuf:range(0,pktlen))
    51  
    52      if pktlen == 0 then
    53          tree:add_proto_expert_info(ef_holepunch)
    54          pktinfo.cols.info:append(" (holepunch)")
    55          return
    56      elseif pktlen == 1 then
    57          tree:add_proto_expert_info(ef_punchy)
    58          pktinfo.cols.info:append(" (punchy)")
    59          return
    60      end
    61  
    62      tree:add(pf_version, tvbuf:range(0,1))
    63      local type = tree:add(pf_type,    tvbuf:range(0,1))
    64  
    65      local nebula_type = bit32.band(tvbuf:range(0,1):uint(), 0x0F)
    66      if nebula_type == 0 then
    67          local stage = tvbuf(8,8):uint64()
    68          tree:add(pf_subtype_handshake, tvbuf:range(1,1))
    69          type:append_text(" stage " .. stage)
    70          pktinfo.cols.info:append(" (" .. type_field().display .. ", stage " .. stage .. ", " .. subtype_field().display .. ")")
    71      elseif nebula_type == 4 then
    72          tree:add(pf_subtype_test, tvbuf:range(1,1))
    73          pktinfo.cols.info:append(" (" .. type_field().display .. ", " .. subtype_field().display .. ")")
    74      else
    75          tree:add(pf_subtype, tvbuf:range(1,1))
    76          pktinfo.cols.info:append(" (" .. type_field().display .. ")")
    77      end
    78  
    79      tree:add(pf_reserved,        tvbuf:range(2,2))
    80      tree:add(pf_remote_index,    tvbuf:range(4,4))
    81      tree:add(pf_message_counter, tvbuf:range(8,8))
    82      tree:add(pf_payload,         tvbuf:range(16,tvbuf:len() - 16))
    83  end
    84  
    85  function nebula.prefs_changed()
    86      if default_settings.all_ports == nebula.prefs.all_ports and default_settings.port == nebula.prefs.port then
    87          -- Nothing changed, bail
    88          return
    89      end
    90  
    91      -- Remove our old dissector
    92      DissectorTable.get("udp.port"):remove_all(nebula)
    93  
    94      if nebula.prefs.all_ports and default_settings.all_ports ~= nebula.prefs.all_ports then
    95          default_settings.all_port = nebula.prefs.all_ports
    96  
    97          for i=0, 65535 do
    98              DissectorTable.get("udp.port"):add(i, nebula)
    99          end
   100  
   101          -- no need to establish again on specific ports
   102          return
   103      end
   104  
   105  
   106      if default_settings.all_ports ~= nebula.prefs.all_ports then
   107          -- Add our new port dissector
   108          default_settings.port = nebula.prefs.port
   109          DissectorTable.get("udp.port"):add(default_settings.port, nebula)
   110      end
   111  end
   112  
   113  DissectorTable.get("udp.port"):add(default_settings.port, nebula)