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 } logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan connected[%s:%d] %s", hostIP, portNumber, sc.Type())) 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[%s] on %s:%d pre packet length[%d]", sc.Type(), info.IP(), info.Port(), 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[%s] on %s:%d send packet length[%d]", sc.Type(), info.IP(), info.Port(), tPacket.Len)) wn, err := conn.Write(tPacket.Buffer) if nil != err { logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan[%s] on %s:%d send packet error %v", sc.Type(), info.IP(), info.Port(), err)) break } if wn != tPacket.Len { logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan[%s] on %s:%d send packet length[%d] not same with %d", sc.Type(), info.IP(), info.Port(), wn, tPacket.Len)) break } rn, err := conn.Read(buf) if nil != err { logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan[%s] on %s:%d receive packet error %v", sc.Type(), info.IP(), info.Port(), 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[%s] on %s:%d receive match length[%d]", sc.Type(), info.IP(), info.Port(), 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[%s] on %s:%d receive not match length[%d]", sc.Type(), info.IP(), info.Port(), 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[%s] on %s:%d socket dial error %v", sc.Type(), 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[%s] on %s:%d send packet length[%d]", sc.Type(), info.IP(), info.Port(), tPacket.Len)) wn, err := conn.Write(tPacket.Buffer) if nil != err { logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan[%s] on %s:%d send packet error %v", sc.Type(), info.IP(), info.Port(), err)) break } if wn != tPacket.Len { logging.Logger().Debug(fmt.Sprintf("Discovery: Service scan[%s] on %s:%d send packet length[%d] not same with %d", sc.Type(), info.IP(), info.Port(), 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[%s] on %s:%d receive packet error %v", sc.Type(), info.IP(), info.Port(), 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[%s] on %s:%d receive match length[%d]", sc.Type(), info.IP(), info.Port(), 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[%s] on %s:%d receive not match length[%d]", sc.Type(), info.IP(), info.Port(), rn)) break } } conn.Close() if nil != s { break Loop } } return s }