This commit is contained in:
crusader 2017-11-22 19:04:04 +09:00
parent 18fe18ccef
commit 40f2ebad23
12 changed files with 386 additions and 7 deletions

View File

@ -27,10 +27,10 @@ type DiscoveryPort struct {
} }
func (dp *DiscoveryPort) Contains(port int) bool { func (dp *DiscoveryPort) Contains(port int) bool {
if dp.FirstScanRange < port { if dp.FirstScanRange > port {
return false return false
} }
if dp.LastScanRange > port { if dp.LastScanRange < port {
return false return false
} }
for _, p := range dp.ExcludePorts { for _, p := range dp.ExcludePorts {

View File

@ -1,5 +1,7 @@
package model package model
import "github.com/google/gopacket"
const ( const (
PortTypeTCP = "TCP" PortTypeTCP = "TCP"
PortTypeUDP = "UDP" PortTypeUDP = "UDP"
@ -13,4 +15,6 @@ type Port struct {
ID int `json:"id,omitempty"` ID int `json:"id,omitempty"`
PortType string `json:"portType,omitempty"` PortType string `json:"portType,omitempty"`
PortNumber int `json:"portNumber,omitempty"` PortNumber int `json:"portNumber,omitempty"`
UDPLayer gopacket.Layer
} }

View File

@ -118,6 +118,7 @@ func handlePacketTCP(host *model.Host, dp *model.DiscoveryPort, ports map[int]*m
} }
port := int(packet.SrcPort) 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) { if _, ok := ports[port]; ok || !dp.Contains(port) {
return nil return nil

View File

@ -134,7 +134,7 @@ func handlePacketUDP(host *model.Host, dp *model.DiscoveryPort, ports map[int]*m
srcIP := ipLayer.(*layers.IPv4).SrcIP srcIP := ipLayer.(*layers.IPv4).SrcIP
port := int(udp.SrcPort) 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) { if _, ok := ports[port]; ok || !dp.Contains(port) {
return nil return nil
} }
@ -142,6 +142,7 @@ func handlePacketUDP(host *model.Host, dp *model.DiscoveryPort, ports map[int]*m
p := &model.Port{ p := &model.Port{
PortType: model.PortTypeUDP, PortType: model.PortTypeUDP,
PortNumber: port, PortNumber: port,
UDPLayer: udpLayer,
} }
p.Host = host p.Host = host
ports[port] = p ports[port] = p

38
discovery/ipv4/service.go Normal file
View File

@ -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
}
}
}
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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{}) {
}

View File

@ -1,10 +1,33 @@
package discovery 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{}) { func scanService(port *model.Port, ds *model.DiscoveryService, resultChan chan interface{}, errChan chan error, doneChan chan<- struct{}, stopChan chan struct{}) {
defer func() { defer func() {
doneChan <- struct{}{} 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
}
} }

View File

@ -13,7 +13,7 @@ type POPMatcher struct {
} }
func (p *POPMatcher) ServiceName() string { func (p *POPMatcher) ServiceName() string {
return "POPMatcher" return "POP3"
} }
func (p *POPMatcher) IsPrePacket() bool { func (p *POPMatcher) IsPrePacket() bool {

View File

@ -82,8 +82,8 @@ func registerUDPMatcher(m matcher.UDPMatcher) {
UDPMatchers = append(UDPMatchers, m) UDPMatchers = append(UDPMatchers, m)
} }
func GetTCPMatchers(ispre bool) []matcher.Matcher { func GetTCPMatchers(isPrePacket bool) []matcher.Matcher {
if ispre { if isPrePacket {
return TCPPrePacketMatchers return TCPPrePacketMatchers
} }