package ipv4 import ( "fmt" "net" "time" logging "git.loafle.net/commons/logging-go" cuej "git.loafle.net/commons/util-go/encoding/json" omd "git.loafle.net/overflow/model/discovery" omm "git.loafle.net/overflow/model/meta" omu "git.loafle.net/overflow/model/util" osm "git.loafle.net/overflow/service_matcher-go" "git.loafle.net/overflow_scanner/probe/matcher" ) func scanServiceTCP(port *omd.Port, ds *omd.DiscoverService, resultChan chan interface{}, errChan chan error, stopChan chan struct{}) bool { hostIP := port.Host.Address portNumber, err := cuej.NumberToInt(port.PortNumber) if err != nil { errChan <- fmt.Errorf("Discovery: Service scan on %s:%s error has occurred %v ", hostIP, port.PortNumber, err) return false } info := osm.NewMatchInfo(hostIP, portNumber) var s *omd.Service scs := []serviceConnector{ &normalServiceConn{ metaCryptoType: omm.ToMetaCryptoType(omm.MetaCryptoTypeEnumNONE), }, &tlsServiceConn{ metaCryptoType: omm.ToMetaCryptoType(omm.MetaCryptoTypeEnumTLS), }, } LOOP: 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.MetaCryptoType().Key, hostIP, portNumber, err) return false } logging.Logger().Debugf("Discovery: Service scan connected[%s:%d] %s", hostIP, portNumber, sc.MetaCryptoType().Key) buf := make([]byte, 1024) if err := conn.SetReadDeadline(time.Now().Add(1 * time.Second)); nil != err { logging.Logger().Debugf("Discovery: cannot set readdeadline connected[%s:%d] %s", hostIP, portNumber, sc.MetaCryptoType().Key) return false } rn, err := conn.Read(buf) if err != nil { rn = 0 } if rn != 0 { s = hadlePrePacket(info, sc, conn, osm.NewPacket(buf, rn)) } else { conn.Close() s = hadlePostPacket(info, sc, nil) } if nil != s { if s.Key == "HTTP" { hsm := matcher.GetHTTPSubMatchers() if ss := hadlePostPacket(info, sc, hsm); ss != nil { s = ss } } break LOOP } select { case <-stopChan: return false default: } } if nil != s { s.Port = port resultChan <- s return true } return false } func hadlePrePacket(info osm.MatchInfo, sc serviceConnector, conn net.Conn, packet *osm.Packet) *omd.Service { defer func() { conn.Close() }() // logging.Logger().Debugf("Discovery: Service scan pre packet length[%d], buf[%v]", packet.Len, packet.Buffer) logging.Logger().Debugf("Discovery: Service scan[%s] on %s:%d pre packet length[%d]", sc.MetaCryptoType().Key, info.IP(), info.Port(), packet.Len) ms := matcher.GetTCPMatchers(true) buf := make([]byte, 1024) var s *omd.Service LOOP: for i := 0; i < len(ms); i++ { m := ms[i] if err := m.Match(info, 0, packet); err == nil { packetCount := m.PacketCount() if 0 == packetCount { s = discoveredService(m, sc) break LOOP } found := false for j := 0; j < packetCount; j++ { tPacket := m.Packet(j) // logging.Logger().Debugf("Discovery: Service scan send packet length[%d], buf[%v]", tPacket.Len, tPacket.Buffer) logging.Logger().Debugf("Discovery: Service scan[%s] on %s:%d send packet length[%d]", sc.MetaCryptoType().Key, info.IP(), info.Port(), tPacket.Len) if err := conn.SetWriteDeadline(time.Now().Add(1 * time.Second)); nil != err { logging.Logger().Debugf("Discovery: cannot set writeDeadLine Service scan[%s] on %s:%d send packet length[%d]", sc.MetaCryptoType().Key, info.IP(), info.Port(), tPacket.Len) break LOOP } wn, err := conn.Write(tPacket.Buffer) if nil != err { logging.Logger().Debugf("Discovery: Service scan[%s] on %s:%d send packet error %v", sc.MetaCryptoType().Key, info.IP(), info.Port(), err) continue LOOP } if wn != tPacket.Len { logging.Logger().Debugf("Discovery: Service scan[%s] on %s:%d send packet length[%d] not same with %d", sc.MetaCryptoType().Key, info.IP(), info.Port(), wn, tPacket.Len) continue LOOP } if err := conn.SetReadDeadline(time.Now().Add(1 * time.Second)); nil != err { logging.Logger().Debugf("Discovery: cannot set readDeadLine Service scan[%s] on %s:%d send packet length[%d]", sc.MetaCryptoType().Key, info.IP(), info.Port(), tPacket.Len) break LOOP } rn, err := conn.Read(buf) if nil != err { logging.Logger().Debugf("Discovery: Service scan[%s] on %s:%d receive packet error %v", sc.MetaCryptoType().Key, info.IP(), info.Port(), err) break LOOP } if err := m.Match(info, j+1, osm.NewPacket(buf, rn)); err == nil { // logging.Logger().Debugf("Discovery: Service scan receive match length[%d], buf[%v]", rn, buf) logging.Logger().Debugf("Discovery: Service scan[%s] on %s:%d receive match length[%d]", sc.MetaCryptoType().Key, info.IP(), info.Port(), rn) found = true } else { // logging.Logger().Debugf("Discovery: Service scan receive not match length[%d], buf[%v]", rn, buf) logging.Logger().Debugf("Discovery: Service scan[%s] on %s:%d receive not match length[%d]", sc.MetaCryptoType().Key, info.IP(), info.Port(), rn) found = false continue LOOP } } if found { s = discoveredService(m, sc) break LOOP } } } return s } func hadlePostPacket(info osm.MatchInfo, sc serviceConnector, limitedMatchers []osm.Matcher) *omd.Service { defer func() { }() ms := matcher.GetTCPMatchers(false) if limitedMatchers != nil { ms = limitedMatchers } buf := make([]byte, 1024) var s *omd.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().Debugf("Discovery: Service scan[%s] on %s:%d socket dial error %v", sc.MetaCryptoType().Key, info.IP(), info.Port(), err) break LOOP } packetCount := m.PacketCount() for j := 0; j < packetCount; j++ { tPacket := m.Packet(j) // logging.Logger().Debugf("Discovery: Service scan send packet length[%d], buf[%v]", tPacket.Len, tPacket.Buffer) logging.Logger().Debugf("Discovery: Service scan[%s] on %s:%d send packet length[%d]", sc.MetaCryptoType().Key, info.IP(), info.Port(), tPacket.Len) if err := conn.SetWriteDeadline(time.Now().Add(1 * time.Second)); nil != err { logging.Logger().Debugf("Discovery: cannot set writeDeadLine Service scan[%s] on %s:%d send packet length[%d]", sc.MetaCryptoType().Key, info.IP(), info.Port(), tPacket.Len) break } wn, err := conn.Write(tPacket.Buffer) if nil != err { logging.Logger().Debugf("Discovery: Service scan[%s] on %s:%d send packet error %v", sc.MetaCryptoType().Key, info.IP(), info.Port(), err) break } if wn != tPacket.Len { logging.Logger().Debugf("Discovery: Service scan[%s] on %s:%d send packet length[%d] not same with %d", sc.MetaCryptoType().Key, info.IP(), info.Port(), wn, tPacket.Len) break } if err := conn.SetReadDeadline(time.Now().Add(1 * time.Second)); nil != err { logging.Logger().Debugf("Discovery: cannot set readDeadLine Service scan[%s] on %s:%d send packet length[%d]", sc.MetaCryptoType().Key, info.IP(), info.Port(), tPacket.Len) break } rn, err := conn.Read(buf) if nil != err { if !m.HasResponse(j) { s = discoveredService(m, sc) break } logging.Logger().Debugf("Discovery: Service scan[%s] on %s:%d receive packet error %v", sc.MetaCryptoType().Key, info.IP(), info.Port(), err) break } if err := m.Match(info, j, osm.NewPacket(buf, rn)); err == nil { if packetCount-1 == j { s = discoveredService(m, sc) break } // logging.Logger().Debugf("Discovery: Service scan receive match length[%d], buf[%v]", rn, buf) logging.Logger().Debugf("Discovery: Service scan[%s] on %s:%d receive match length[%d]", sc.MetaCryptoType().Key, info.IP(), info.Port(), rn) continue } else { // logging.Logger().Debugf("Discovery: Service scan receive not match length[%d], buf[%v]", rn, buf) logging.Logger().Debugf("Discovery: Service scan[%s] on %s:%d receive not match length[%d]", sc.MetaCryptoType().Key, info.IP(), info.Port(), rn) break } } conn.Close() if nil != s { break LOOP } } return s } func discoveredService(m osm.Matcher, sc serviceConnector) *omd.Service { return &omd.Service{ Key: m.Key(), MetaCryptoType: sc.MetaCryptoType(), DiscoveredDate: omu.NowPtr(), Metadata: m.Meta(), Name: m.Name(), } }