From 40f2ebad2326259cf9a2d01ae91e8e21804a39a8 Mon Sep 17 00:00:00 2001 From: crusader Date: Wed, 22 Nov 2017 19:04:04 +0900 Subject: [PATCH] ing --- api/module/discovery/model/discovery.go | 4 +- api/module/discovery/model/port.go | 4 + discovery/ipv4/port_tcp.go | 1 + discovery/ipv4/port_udp.go | 3 +- discovery/ipv4/service.go | 38 +++++ discovery/ipv4/service_conn.go | 68 ++++++++ discovery/ipv4/service_tcp.go | 208 ++++++++++++++++++++++++ discovery/ipv4/service_udp.go | 29 ++++ discovery/ipv6/service.go | 7 + discovery/service.go | 25 ++- service/matcher/pop/pop.go | 2 +- service/service.go | 4 +- 12 files changed, 386 insertions(+), 7 deletions(-) create mode 100644 discovery/ipv4/service.go create mode 100644 discovery/ipv4/service_conn.go create mode 100644 discovery/ipv4/service_tcp.go create mode 100644 discovery/ipv4/service_udp.go create mode 100644 discovery/ipv6/service.go diff --git a/api/module/discovery/model/discovery.go b/api/module/discovery/model/discovery.go index 406a373..bf61754 100644 --- a/api/module/discovery/model/discovery.go +++ b/api/module/discovery/model/discovery.go @@ -27,10 +27,10 @@ type DiscoveryPort struct { } func (dp *DiscoveryPort) Contains(port int) bool { - if dp.FirstScanRange < port { + if dp.FirstScanRange > port { return false } - if dp.LastScanRange > port { + if dp.LastScanRange < port { return false } for _, p := range dp.ExcludePorts { diff --git a/api/module/discovery/model/port.go b/api/module/discovery/model/port.go index 6d9af59..d128058 100644 --- a/api/module/discovery/model/port.go +++ b/api/module/discovery/model/port.go @@ -1,5 +1,7 @@ package model +import "github.com/google/gopacket" + const ( PortTypeTCP = "TCP" PortTypeUDP = "UDP" @@ -13,4 +15,6 @@ type Port struct { ID int `json:"id,omitempty"` PortType string `json:"portType,omitempty"` PortNumber int `json:"portNumber,omitempty"` + + UDPLayer gopacket.Layer } diff --git a/discovery/ipv4/port_tcp.go b/discovery/ipv4/port_tcp.go index 29d8e8c..21c6dbf 100644 --- a/discovery/ipv4/port_tcp.go +++ b/discovery/ipv4/port_tcp.go @@ -118,6 +118,7 @@ func handlePacketTCP(host *model.Host, dp *model.DiscoveryPort, ports map[int]*m } port := int(packet.SrcPort) + logging.Logger().Debug(fmt.Sprintf("Discovery: IP of TCP(%d) src %s", port, host.IP)) if _, ok := ports[port]; ok || !dp.Contains(port) { return nil diff --git a/discovery/ipv4/port_udp.go b/discovery/ipv4/port_udp.go index 1dec5d2..5ac34a0 100644 --- a/discovery/ipv4/port_udp.go +++ b/discovery/ipv4/port_udp.go @@ -134,7 +134,7 @@ func handlePacketUDP(host *model.Host, dp *model.DiscoveryPort, ports map[int]*m srcIP := ipLayer.(*layers.IPv4).SrcIP port := int(udp.SrcPort) - logging.Logger().Debug(fmt.Sprintf("Discovery: IP of UPD(%d) src %v", port, srcIP)) + logging.Logger().Debug(fmt.Sprintf("Discovery: IP of UDP(%d) src %v", port, srcIP)) if _, ok := ports[port]; ok || !dp.Contains(port) { return nil } @@ -142,6 +142,7 @@ func handlePacketUDP(host *model.Host, dp *model.DiscoveryPort, ports map[int]*m p := &model.Port{ PortType: model.PortTypeUDP, PortNumber: port, + UDPLayer: udpLayer, } p.Host = host ports[port] = p diff --git a/discovery/ipv4/service.go b/discovery/ipv4/service.go new file mode 100644 index 0000000..2abc514 --- /dev/null +++ b/discovery/ipv4/service.go @@ -0,0 +1,38 @@ +package ipv4 + +import ( + "fmt" + + "git.loafle.net/overflow/overflow_discovery/api/module/discovery/model" + "github.com/google/gopacket/layers" +) + +func ScanService(port *model.Port, ds *model.DiscoveryService, resultChan chan interface{}, errChan chan error, stopChan chan struct{}) { + + switch port.PortType { + case model.PortTypeTCP: + if !scanServiceTCP(port, ds, resultChan, errChan, stopChan) { + if dName, ok := layers.TCPPortNames[layers.TCPPort(port.PortNumber)]; ok { + sName := fmt.Sprintf("Not Supported Service. Perhaps %s[%d]", dName, port.PortNumber) + s := &model.Service{ + ServiceName: sName, + } + s.Port = port + resultChan <- s + } + } + + case model.PortTypeUDP: + if !scanServiceUDP(port, ds, resultChan, errChan, stopChan) { + if dName, ok := layers.UDPPortNames[layers.UDPPort(port.PortNumber)]; ok { + sName := fmt.Sprintf("Not Supported Service. Perhaps %s[%d]", dName, port.PortNumber) + s := &model.Service{ + ServiceName: sName, + } + s.Port = port + resultChan <- s + } + } + } + +} diff --git a/discovery/ipv4/service_conn.go b/discovery/ipv4/service_conn.go new file mode 100644 index 0000000..45d58a1 --- /dev/null +++ b/discovery/ipv4/service_conn.go @@ -0,0 +1,68 @@ +package ipv4 + +import ( + "crypto/tls" + "fmt" + "net" + "time" +) + +type serviceConnector interface { + Type() string + Dial(ip string, port int) (net.Conn, error) +} + +type normalServiceConn struct { + t string +} + +func (nsc *normalServiceConn) Type() string { + return nsc.t +} + +func (nsc *normalServiceConn) Dial(ip string, port int) (net.Conn, error) { + addr := fmt.Sprintf("%s:%d", ip, port) + conn, err := net.DialTimeout("tcp", addr, time.Duration(3)*time.Second) + if err != nil { + return nil, err + } + + err = conn.SetDeadline(time.Now().Add(3 * time.Second)) + if err != nil { + return nil, err + } + return conn, err +} + +type tlsServiceConn struct { + t string +} + +func (tsc *tlsServiceConn) Type() string { + return tsc.t +} + +func (tsc *tlsServiceConn) Dial(ip string, port int) (net.Conn, error) { + addr := fmt.Sprintf("%s:%d", ip, port) + dialer := &net.Dialer{ + Timeout: 3 * time.Second, + } + conn, err := tls.DialWithDialer( + dialer, + "tcp", + addr, + &tls.Config{ + InsecureSkipVerify: true, + ServerName: ip, + }, + ) + if err != nil { + return nil, err + } + + err = conn.SetDeadline(time.Now().Add(3 * time.Second)) + if err != nil { + return nil, err + } + return conn, err +} diff --git a/discovery/ipv4/service_tcp.go b/discovery/ipv4/service_tcp.go new file mode 100644 index 0000000..a6f84aa --- /dev/null +++ b/discovery/ipv4/service_tcp.go @@ -0,0 +1,208 @@ +package ipv4 + +import ( + "fmt" + "net" + + "git.loafle.net/commons_go/logging" + + "git.loafle.net/overflow/overflow_discovery/api/module/discovery/model" + "git.loafle.net/overflow/overflow_discovery/service" + "git.loafle.net/overflow/overflow_discovery/service/matcher" +) + +func scanServiceTCP(port *model.Port, ds *model.DiscoveryService, resultChan chan interface{}, errChan chan error, stopChan chan struct{}) bool { + + hostIP := port.Host.IP + portNumber := port.PortNumber + info := matcher.NewMatchInfo(hostIP, portNumber) + var s *model.Service + + scs := []serviceConnector{ + &normalServiceConn{ + t: model.PortTypeTCP, + }, + &tlsServiceConn{ + t: model.CryptoTypeTLS, + }, + } + + for i := 0; i < len(scs); i++ { + sc := scs[i] + + conn, err := sc.Dial(hostIP, portNumber) + if err != nil { + errChan <- fmt.Errorf("Discovery: Service scan[%s] on %s:%d error has occurred %v ", sc.Type(), hostIP, portNumber, err) + break + } + buf := make([]byte, 1024) + rn, err := conn.Read(buf) + if err != nil { + rn = 0 + } + if rn != 0 { + s = hadlePrePacket(info, sc, conn, matcher.NewPacket(buf, rn)) + } else { + conn.Close() + s = hadlePostPacket(info, sc) + } + + if nil != s { + break + } + } + + if nil != s { + s.Port = port + resultChan <- s + return true + } + + return false +} + +func hadlePrePacket(info matcher.MatchInfo, sc serviceConnector, conn net.Conn, packet *matcher.Packet) *model.Service { + defer func() { + conn.Close() + }() + + // logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan pre packet length[%d], buf[%v]", packet.Len, packet.Buffer)) + logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan pre packet length[%d]", packet.Len)) + + ms := service.GetTCPMatchers(true) + buf := make([]byte, 1024) + var s *model.Service + +Loop: + for i := 0; i < len(ms); i++ { + m := ms[i] + + if m.Match(info, 0, packet) { + packetCount := m.PacketCount() + + if 0 == packetCount { + s = &model.Service{ + ServiceName: m.ServiceName(), + CryptoType: sc.Type(), + } + break Loop + } + + found := false + + for j := 0; j < packetCount; j++ { + tPacket := m.Packet(j) + // logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan send packet length[%d], buf[%v]", tPacket.Len, tPacket.Buffer)) + logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan send packet length[%d]", tPacket.Len)) + wn, err := conn.Write(tPacket.Buffer) + if nil != err { + logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan send packet error %v", err)) + break + } + if wn != tPacket.Len { + logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan send packet length[%d] not same with %d", wn, tPacket.Len)) + break + } + + rn, err := conn.Read(buf) + if nil != err { + logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan receive packet error %v", err)) + break + } + + if m.Match(info, j+1, matcher.NewPacket(buf, rn)) { + // logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan receive match length[%d], buf[%v]", rn, buf)) + logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan receive match length[%d]", rn)) + found = true + } else { + // logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan receive not match length[%d], buf[%v]", rn, buf)) + logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan receive not match length[%d]", rn)) + found = false + break + } + } + + if found { + s = &model.Service{ + ServiceName: m.ServiceName(), + CryptoType: sc.Type(), + } + break Loop + } + } + } + + return s +} + +func hadlePostPacket(info matcher.MatchInfo, sc serviceConnector) *model.Service { + ms := service.GetTCPMatchers(false) + buf := make([]byte, 1024) + var s *model.Service + +Loop: + for i := 0; i < len(ms); i++ { + m := ms[i] + + conn, err := sc.Dial(info.IP(), info.Port()) + if err != nil { + logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan socket[%s:%d] dial error %v", info.IP(), info.Port(), err)) + break Loop + } + + packetCount := m.PacketCount() + for j := 0; j < packetCount; j++ { + tPacket := m.Packet(j) + // logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan send packet length[%d], buf[%v]", tPacket.Len, tPacket.Buffer)) + logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan send packet length[%d]", tPacket.Len)) + wn, err := conn.Write(tPacket.Buffer) + if nil != err { + logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan send packet error %v", err)) + break + } + if wn != tPacket.Len { + logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan send packet length[%d] not same with %d", wn, tPacket.Len)) + break + } + + rn, err := conn.Read(buf) + if nil != err { + if !m.HasResponse(j) { + s = &model.Service{ + ServiceName: m.ServiceName(), + CryptoType: sc.Type(), + } + break + } + + logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan receive packet error %v", err)) + break + } + + if m.Match(info, j, matcher.NewPacket(buf, rn)) { + if packetCount-1 == j { + s = &model.Service{ + ServiceName: m.ServiceName(), + CryptoType: sc.Type(), + } + break + } + + // logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan receive match length[%d], buf[%v]", rn, buf)) + logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan receive match length[%d]", rn)) + continue + } else { + // logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan receive not match length[%d], buf[%v]", rn, buf)) + logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan receive not match length[%d]", rn)) + break + } + } + conn.Close() + + if nil != s { + break Loop + } + } + + return s +} diff --git a/discovery/ipv4/service_udp.go b/discovery/ipv4/service_udp.go new file mode 100644 index 0000000..be36c60 --- /dev/null +++ b/discovery/ipv4/service_udp.go @@ -0,0 +1,29 @@ +package ipv4 + +import ( + "git.loafle.net/overflow/overflow_discovery/api/module/discovery/model" + "git.loafle.net/overflow/overflow_discovery/service" + "git.loafle.net/overflow/overflow_discovery/service/matcher" +) + +func scanServiceUDP(port *model.Port, ds *model.DiscoveryService, resultChan chan interface{}, errChan chan error, stopChan chan struct{}) bool { + + ms := service.GetUDPMatchers() + mi := matcher.NewMatchInfo(port.Host.IP, port.PortNumber) + + for i := 0; i < len(ms); i++ { + m := ms[i] + p := matcher.NewPacket(port.UDPLayer.LayerPayload(), len(port.UDPLayer.LayerPayload())) + + if m.Match(mi, 0, p) { + s := &model.Service{ + ServiceName: m.ServiceName(), + } + s.Port = port + resultChan <- s + return true + } + } + + return false +} diff --git a/discovery/ipv6/service.go b/discovery/ipv6/service.go new file mode 100644 index 0000000..8f9e279 --- /dev/null +++ b/discovery/ipv6/service.go @@ -0,0 +1,7 @@ +package ipv6 + +import "git.loafle.net/overflow/overflow_discovery/api/module/discovery/model" + +func ScanService(port *model.Port, ds *model.DiscoveryService, resultChan chan interface{}, errChan chan error, stopChan chan struct{}) { + +} diff --git a/discovery/service.go b/discovery/service.go index 6df7389..6c6e8b3 100644 --- a/discovery/service.go +++ b/discovery/service.go @@ -1,10 +1,33 @@ package discovery -import "git.loafle.net/overflow/overflow_discovery/api/module/discovery/model" +import ( + "fmt" + "net" + + "git.loafle.net/overflow/overflow_discovery/api/module/discovery/model" + "git.loafle.net/overflow/overflow_discovery/discovery/ipv4" + "git.loafle.net/overflow/overflow_discovery/discovery/ipv6" +) func scanService(port *model.Port, ds *model.DiscoveryService, resultChan chan interface{}, errChan chan error, doneChan chan<- struct{}, stopChan chan struct{}) { defer func() { doneChan <- struct{}{} }() + _, ipNet, err := net.ParseCIDR(port.Host.Zone.Network) + if nil != err { + errChan <- err + return + } + + switch len(ipNet.IP) { + case net.IPv4len: + ipv4.ScanService(port, ds, resultChan, errChan, stopChan) + case net.IPv6len: + ipv6.ScanService(port, ds, resultChan, errChan, stopChan) + + default: + errChan <- fmt.Errorf("Discovery: Not supported ip length") + return + } } diff --git a/service/matcher/pop/pop.go b/service/matcher/pop/pop.go index 58c34e1..1b4ca1b 100644 --- a/service/matcher/pop/pop.go +++ b/service/matcher/pop/pop.go @@ -13,7 +13,7 @@ type POPMatcher struct { } func (p *POPMatcher) ServiceName() string { - return "POPMatcher" + return "POP3" } func (p *POPMatcher) IsPrePacket() bool { diff --git a/service/service.go b/service/service.go index 4d1bc33..a31348c 100644 --- a/service/service.go +++ b/service/service.go @@ -82,8 +82,8 @@ func registerUDPMatcher(m matcher.UDPMatcher) { UDPMatchers = append(UDPMatchers, m) } -func GetTCPMatchers(ispre bool) []matcher.Matcher { - if ispre { +func GetTCPMatchers(isPrePacket bool) []matcher.Matcher { + if isPrePacket { return TCPPrePacketMatchers }