diff --git a/api/module/discovery/model/port.go b/api/module/discovery/model/port.go index 7737f84..6d9af59 100644 --- a/api/module/discovery/model/port.go +++ b/api/module/discovery/model/port.go @@ -1,5 +1,12 @@ package model +const ( + PortTypeTCP = "TCP" + PortTypeUDP = "UDP" + + CryptoTypeTLS = "TLS" +) + type Port struct { Host *Host `json:"host,omitempty"` diff --git a/discovery/ipv4/host.go b/discovery/ipv4/host.go index 9f5911e..cf11739 100644 --- a/discovery/ipv4/host.go +++ b/discovery/ipv4/host.go @@ -52,7 +52,7 @@ func ScanHost(zone *model.Zone, dh *model.DiscoveryHost, resultChan chan interfa return } if h := handlePacketARP(zone, cr, hosts, packet); nil != h { - logging.Logger().Debug(fmt.Sprintf("Discovery: Host[%v] is founded", h)) + resultChan <- h } case <-stopChan: return @@ -68,27 +68,6 @@ func ScanHost(zone *model.Zone, dh *model.DiscoveryHost, resultChan chan interfa time.Sleep(10 * time.Second) } -func handlePacketARP(zone *model.Zone, cr cidr.CIDRRanger, hosts map[string]*model.Host, packet *layers.ARP) *model.Host { - if packet.Operation != layers.ARPReply { - return nil - } - - // logging.Logger().Debug(fmt.Sprintf("Discovery: arp packet %v", packet)) - - ip := net.IP(packet.SourceProtAddress) - if _, ok := hosts[ip.String()]; ok || !cr.Contains(ip) { - return nil - } - h := &model.Host{} - h.IP = ip.String() - h.Mac = net.HardwareAddr(packet.SourceHwAddress).String() - h.Zone = zone - - hosts[ip.String()] = h - - return h -} - func sendARP(ps pcap.PCapScanner, zone *model.Zone, hostRanges []net.IP, stopChan chan struct{}) error { hwAddr, err := net.ParseMAC(zone.Mac) if nil != err { @@ -123,6 +102,25 @@ func sendARP(ps pcap.PCapScanner, zone *model.Zone, hostRanges []net.IP, stopCha return nil } +func handlePacketARP(zone *model.Zone, cr cidr.CIDRRanger, hosts map[string]*model.Host, packet *layers.ARP) *model.Host { + if packet.Operation != layers.ARPReply { + return nil + } + + ip := net.IP(packet.SourceProtAddress) + if _, ok := hosts[ip.String()]; ok || !cr.Contains(ip) { + return nil + } + h := &model.Host{} + h.IP = ip.String() + h.Mac = net.HardwareAddr(packet.SourceHwAddress).String() + h.Zone = zone + + hosts[ip.String()] = h + + return h +} + func getTargetHostRange(dh *model.DiscoveryHost, cr cidr.CIDRRanger) ([]net.IP, error) { excludeIPs := make([]net.IP, 0) for _, eHost := range dh.ExcludeHosts { diff --git a/discovery/ipv4/port_tcp.go b/discovery/ipv4/port_tcp.go new file mode 100644 index 0000000..439e76b --- /dev/null +++ b/discovery/ipv4/port_tcp.go @@ -0,0 +1,107 @@ +package ipv4 + +import ( + "fmt" + "net" + "time" + + "git.loafle.net/commons_go/logging" + "git.loafle.net/overflow/overflow_discovery/api/module/discovery/model" + "git.loafle.net/overflow/overflow_discovery/commons/pcap" + "github.com/google/gopacket" + "github.com/google/gopacket/layers" +) + +func scanPortTCP(host *model.Host, dp *model.DiscoveryPort, resultChan chan interface{}, errChan chan error, stopChan chan struct{}) { + ps, err := pcap.RetainScanner(host.Zone) + if nil != err { + errChan <- fmt.Errorf("Discovery: Cannot retain pcap instance %v", err) + return + } + + defer func() { + pcap.ReleaseScanner(host.Zone) + }() + + tcpChan := ps.OpenTCP(host.IP) + defer func() { + ps.CloseTCP(host.IP, tcpChan) + }() + + go func() { + for { + select { + case packet, ok := <-tcpChan: + if !ok { + logging.Logger().Debug(fmt.Sprintf("Discovery: tcp channel is closed")) + return + } + if h := handlePacketTCP(zone, cr, hosts, packet); nil != h { + resultChan <- h + } + case <-stopChan: + return + } + } + }() + + if err := sendTCP(ps, zone, hostRanges, stopChan); nil != err { + errChan <- err + return + } + + time.Sleep(20 * time.Second) +} + +func sendTCP(ps pcap.PCapScanner, zone *model.Zone, hostRanges []net.IP, stopChan chan struct{}) error { + hwAddr, err := net.ParseMAC(zone.Mac) + if nil != err { + return err + } + ip := net.ParseIP(zone.IP) + if nil == ip { + return fmt.Errorf("Discovery: IP(%s) of zone is not valid", zone.IP) + } + + ethPacket := makePacketEthernet(hwAddr) + arpPacket := makePacketARP(hwAddr, ip.To4()) + opts := gopacket.SerializeOptions{FixLengths: true, ComputeChecksums: true} + buf := gopacket.NewSerializeBuffer() + + for _, targetHost := range hostRanges { + arpPacket.DstProtAddress = []byte(targetHost) + // log.Printf("ARP:%v", arpPacket) + gopacket.SerializeLayers(buf, opts, ðPacket, &arpPacket) + if err := ps.WritePacketData(buf.Bytes()); err != nil { + return err + } + + select { + case <-stopChan: + return nil + default: + } + + time.Sleep(time.Microsecond * 100) + } + return nil +} + +func handlePacketTCP(host *model.Host, packet *layers.TCP) *model.Port { + if nil == packet || packet.DstPort != 60000 { + return nil + } + + if packet.RST { + return nil + } + + port := int(packet.SrcPort) + p := &model.Port{ + PortType: model.PortTypeTCP, + PortNumber: port, + } + p.Host = host + + return p +} diff --git a/discovery/ipv4/port_udp.go b/discovery/ipv4/port_udp.go new file mode 100644 index 0000000..890e799 --- /dev/null +++ b/discovery/ipv4/port_udp.go @@ -0,0 +1,7 @@ +package ipv4 + +import "git.loafle.net/overflow/overflow_discovery/api/module/discovery/model" + +func scanPortUDP(host *model.Host, dp *model.DiscoveryPort, resultChan chan interface{}, errChan chan error, stopChan chan struct{}) { + +}