This commit is contained in:
insanity 2018-08-12 19:24:23 +09:00
parent 5755a0dabc
commit 85a6ffcd7b
7 changed files with 568 additions and 1 deletions

View File

@ -7,4 +7,7 @@
"editor.trimAutoWhitespace": true, "editor.trimAutoWhitespace": true,
"files.trimTrailingWhitespace": true, "files.trimTrailingWhitespace": true,
"files.trimFinalNewlines": true, "files.trimFinalNewlines": true,
} "go.testFlags": [
"-v"
]
}

82
matcher/matcher.go Normal file
View File

@ -0,0 +1,82 @@
package matcher
import (
csm "git.loafle.net/commons/service_matcher-go"
"git.loafle.net/commons/service_matcher-go/elasticsearch"
"git.loafle.net/commons/service_matcher-go/ftp"
"git.loafle.net/commons/service_matcher-go/http"
"git.loafle.net/commons/service_matcher-go/ldap"
"git.loafle.net/commons/service_matcher-go/lpd"
"git.loafle.net/commons/service_matcher-go/mongodb"
"git.loafle.net/commons/service_matcher-go/mysql"
"git.loafle.net/commons/service_matcher-go/nbss"
"git.loafle.net/commons/service_matcher-go/postgresql"
"git.loafle.net/commons/service_matcher-go/redis"
"git.loafle.net/commons/service_matcher-go/ssh"
"git.loafle.net/commons/service_matcher-go/telnet"
)
var (
AllMatchers []csm.Matcher
TCPMatchers []csm.Matcher
UDPMatchers []csm.UDPMatcher
TCPPrePacketMatchers []csm.Matcher
TCPNotPrePacketMatchers []csm.Matcher
)
func init() {
//TCP
addTCPMatcher(ssh.NewMatcher())
addTCPMatcher(mongodb.NewMatcher())
addTCPMatcher(mysql.NewMatcher())
addTCPMatcher(redis.NewMatcher())
addTCPMatcher(postgresql.NewMatcher())
addTCPMatcher(ftp.NewMatcher())
addTCPMatcher(http.NewMatcher())
addTCPMatcher(lpd.NewMatcher())
addTCPMatcher(elasticsearch.NewMatcher())
addTCPMatcher(telnet.NewMatcher())
addTCPMatcher(nbss.NewMatcher())
addTCPMatcher(ldap.NewMatcher())
addTCPMatcher(mysql.NewMatcher())
// UDP
}
func addTCPMatcher(m csm.Matcher) {
AllMatchers = append(AllMatchers, m)
TCPMatchers = append(TCPMatchers, m)
if m.IsPrePacket() {
TCPPrePacketMatchers = append(TCPPrePacketMatchers, m)
} else {
TCPNotPrePacketMatchers = append(TCPNotPrePacketMatchers, m)
}
}
func addUDPMatcher(m csm.UDPMatcher) {
AllMatchers = append(AllMatchers, m)
UDPMatchers = append(UDPMatchers, m)
}
func GetTCPMatchers(isPrePacket bool) []csm.Matcher {
if isPrePacket {
return TCPPrePacketMatchers
}
return TCPNotPrePacketMatchers
}
func GetUDPMatchers() []csm.UDPMatcher {
return UDPMatchers
}
func GetMatcherByKey(key string) csm.Matcher {
for _, m := range AllMatchers {
if m.Key() == key {
return m
}
}
return nil
}

60
pcap/pcap.go Normal file
View File

@ -0,0 +1,60 @@
package pcap
import (
"sync"
"time"
ocmd "git.loafle.net/overflow/commons-go/model/discovery"
)
var mtx sync.Mutex
var instances map[string]PCapScanner
func init() {
instances = make(map[string]PCapScanner, 0)
}
func RetainScanner(zone *ocmd.Zone) (PCapScanner, error) {
mtx.Lock()
defer mtx.Unlock()
var ps PCapScanner
var ok bool
if ps, ok = instances[zone.Network]; !ok {
ps = newPCapScanner(zone)
if err := ps.start(); nil != err {
return nil, err
}
instances[zone.Network] = ps
}
ps.retain()
return ps, nil
}
func ReleaseScanner(zone *ocmd.Zone) {
go func() {
time.Sleep(2 * time.Second)
mtx.Lock()
defer mtx.Unlock()
if ps, ok := instances[zone.Network]; ok {
if ps.release() {
ps.stop()
delete(instances, zone.Network)
}
}
}()
}
func ReleaseScannerAll() {
mtx.Lock()
defer mtx.Unlock()
for k, ps := range instances {
ps.stop()
delete(instances, k)
}
}

248
pcap/pcap_scan.go Normal file
View File

@ -0,0 +1,248 @@
package pcap
import (
"fmt"
"sort"
"sync"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
)
func newPCapScanner(iface string) PCapScanner {
ps := &pCapScan{
iface: iface
}
return ps
}
type PCapScanner interface {
OpenARP() chan *layers.ARP
CloseARP(ch chan *layers.ARP)
OpenTCP(ip string) chan *layers.TCP
CloseTCP(ip string, ch chan *layers.TCP)
OpenUDP(ip string) chan gopacket.Packet
CloseUDP(ip string, ch chan gopacket.Packet)
WritePacketData(data []byte) (err error)
start() error
stop()
retain()
release() bool
}
type pCapScan struct {
pCapHandle *pcap.Handle
iface string
arpListenerChanMtx sync.RWMutex
arpListenerChans []chan *layers.ARP
tcpListenerChanMtx sync.RWMutex
tcpListenerChans map[string][]chan *layers.TCP
udpListenerChanMtx sync.RWMutex
udpListenerChans map[string][]chan gopacket.Packet
refCount int
stopChan chan struct{}
stopWg sync.WaitGroup
}
func (ps *pCapScan) start() error {
if ps.stopChan != nil {
return fmt.Errorf("PCapScanner: already running. Stop it before starting it again")
}
// new pcap handle
var h *pcap.Handle
var err error
if h, err = pcap.OpenLive(ps.zone.Iface, 65536, true, pcap.BlockForever); nil != err {
return err
}
// set filter
// todo add tcp, udp filter
if err = h.SetBPFFilter("arp and src net " + ps.zone.Network + " or (((tcp[tcpflags] & (tcp-syn|tcp-ack) != 0) or (tcp[tcpflags] & (tcp-rst) != 0)) and port 60000) or udp "); nil != err {
h.Close()
return err
}
ps.pCapHandle = h
ps.arpListenerChans = make([]chan *layers.ARP, 0)
ps.tcpListenerChans = make(map[string][]chan *layers.TCP, 0)
ps.udpListenerChans = make(map[string][]chan gopacket.Packet, 0)
ps.stopChan = make(chan struct{})
ps.stopWg.Add(1)
go handleReceive(ps)
return nil
}
func (ps *pCapScan) stop() {
if ps.stopChan == nil {
panic("PCapScanner: must be started before stopping it")
}
close(ps.stopChan)
ps.stopWg.Wait()
ps.stopChan = nil
}
func (ps *pCapScan) OpenARP() chan *layers.ARP {
ps.arpListenerChanMtx.Lock()
defer ps.arpListenerChanMtx.Unlock()
c := make(chan *layers.ARP, 0)
ps.arpListenerChans = append(ps.arpListenerChans, c)
return c
}
func (ps *pCapScan) CloseARP(ch chan *layers.ARP) {
ps.arpListenerChanMtx.Lock()
defer ps.arpListenerChanMtx.Unlock()
i := sort.Search(len(ps.arpListenerChans), func(i int) bool {
return ch == ps.arpListenerChans[i]
})
if -1 != i {
close(ch)
ps.arpListenerChans = append(ps.arpListenerChans[:i], ps.arpListenerChans[i+1:]...)
}
}
func (ps *pCapScan) OpenTCP(ip string) chan *layers.TCP {
ps.tcpListenerChanMtx.Lock()
defer ps.tcpListenerChanMtx.Unlock()
if _, ok := ps.tcpListenerChans[ip]; !ok {
ps.tcpListenerChans[ip] = make([]chan *layers.TCP, 0)
}
ch := make(chan *layers.TCP, 0)
ps.tcpListenerChans[ip] = append(ps.tcpListenerChans[ip], ch)
return ch
}
func (ps *pCapScan) CloseTCP(ip string, ch chan *layers.TCP) {
ps.tcpListenerChanMtx.Lock()
defer ps.tcpListenerChanMtx.Unlock()
if _, ok := ps.tcpListenerChans[ip]; !ok {
return
}
chs := ps.tcpListenerChans[ip]
i := sort.Search(len(chs), func(i int) bool {
return ch == chs[i]
})
if -1 != i {
close(ch)
ps.tcpListenerChans[ip] = append(ps.tcpListenerChans[ip][:i], ps.tcpListenerChans[ip][i+1:]...)
}
}
func (ps *pCapScan) OpenUDP(ip string) chan gopacket.Packet {
ps.udpListenerChanMtx.Lock()
defer ps.udpListenerChanMtx.Unlock()
if _, ok := ps.udpListenerChans[ip]; !ok {
ps.udpListenerChans[ip] = make([]chan gopacket.Packet, 0)
}
ch := make(chan gopacket.Packet, 0)
ps.udpListenerChans[ip] = append(ps.udpListenerChans[ip], ch)
return ch
}
func (ps *pCapScan) CloseUDP(ip string, ch chan gopacket.Packet) {
ps.udpListenerChanMtx.Lock()
defer ps.udpListenerChanMtx.Unlock()
if _, ok := ps.udpListenerChans[ip]; !ok {
return
}
chs := ps.udpListenerChans[ip]
i := sort.Search(len(chs), func(i int) bool {
return ch == chs[i]
})
if -1 != i {
close(ch)
ps.udpListenerChans[ip] = append(ps.udpListenerChans[ip][:i], ps.udpListenerChans[ip][i+1:]...)
}
}
func (ps *pCapScan) WritePacketData(data []byte) (err error) {
return ps.pCapHandle.WritePacketData(data)
}
func (ps *pCapScan) retain() {
ps.refCount++
}
func (ps *pCapScan) release() bool {
ps.refCount--
if 0 > ps.refCount {
ps.refCount = 0
}
return 0 == ps.refCount
}
func (ps *pCapScan) destroy() {
ps.tcpListenerChanMtx.Lock()
for k, v := range ps.tcpListenerChans {
for _, ch := range v {
close(ch)
}
v = v[:0]
delete(ps.tcpListenerChans, k)
}
ps.tcpListenerChanMtx.Unlock()
ps.udpListenerChanMtx.Lock()
for k, v := range ps.udpListenerChans {
for _, ch := range v {
close(ch)
}
v = v[:0]
delete(ps.udpListenerChans, k)
}
ps.udpListenerChanMtx.Unlock()
ps.arpListenerChanMtx.Lock()
for _, v := range ps.arpListenerChans {
close(v)
}
ps.arpListenerChans = ps.arpListenerChans[:0]
ps.arpListenerChanMtx.Unlock()
ps.pCapHandle.Close()
}
func handleReceive(ps *pCapScan) {
defer ps.stopWg.Done()
pSrc := gopacket.NewPacketSource(ps.pCapHandle, layers.LayerTypeEthernet)
inPacket := pSrc.Packets()
for {
select {
case packet := <-inPacket:
handlePacket(ps, packet)
case <-ps.stopChan:
ps.destroy()
return
}
}
}

9
pcap/pcap_test.go Normal file
View File

@ -0,0 +1,9 @@
package pcap
import (
"testing"
)
func TestPcap(t *testing.T) {
}

99
ping/ping.go Normal file
View File

@ -0,0 +1,99 @@
package ping
import (
"crypto/tls"
"fmt"
"net"
"strings"
"time"
csm "git.loafle.net/commons/service_matcher-go"
opm "git.loafle.net/overflow_scanner/probe/matcher"
)
type Res struct {
Matcher csm.Matcher
Error error
}
func Ping(ch chan Res, ip string, port int, tls bool, portType, key string) {
go func() {
conn, err := getConnection(ip, port, portType, tls)
if err != nil {
ch <- Res{nil, err}
close(ch)
}
defer conn.Close()
m := opm.GetMatcherByKey(key)
if m.IsPrePacket() {
processPrepacket(ch, conn, m)
}
processPostpacket(ch, conn, m)
}()
}
func processPrepacket(ch chan Res, conn net.Conn, m csm.Matcher) {
for i := 0; i < m.PacketCount(); i++ {
bytes := make([]byte, 1024)
n, _ := conn.Read(bytes)
p := csm.NewPacket(bytes, n)
_, err := conn.Write(m.Packet(i).Buffer)
if err != nil {
ch <- Res{nil, err}
close(ch)
}
if err := m.Match(nil, i, p); err != nil {
ch <- Res{nil, err}
close(ch)
}
}
ch <- Res{m, nil}
close(ch)
}
func processPostpacket(ch chan Res, conn net.Conn, m csm.Matcher) {
for i := 0; i < m.PacketCount(); i++ {
_, err := conn.Write(m.Packet(i).Buffer)
if err != nil {
ch <- Res{nil, err}
close(ch)
}
bytes := make([]byte, 1024)
n, _ := conn.Read(bytes)
p := csm.NewPacket(bytes, n)
if err := m.Match(nil, i, p); err != nil {
ch <- Res{nil, err}
close(ch)
}
}
ch <- Res{m, nil}
close(ch)
}
func getConnection(ip string, port int, portType string, isTLS bool) (net.Conn, error) {
addr := fmt.Sprintf("%s:%d", ip, port)
portType = strings.ToLower(portType)
if isTLS {
dialer := &net.Dialer{
Timeout: 5 * time.Second,
}
return tls.DialWithDialer(
dialer,
portType,
addr,
&tls.Config{
InsecureSkipVerify: true,
ServerName: ip,
},
)
}
return net.Dial(portType, addr)
}

66
ping/ping_test.go Normal file
View File

@ -0,0 +1,66 @@
package ping
import (
"fmt"
"log"
"testing"
"github.com/google/gopacket"
"github.com/google/gopacket/pcap"
)
func TestPing(t *testing.T) {
ip := "192.168.1.229"
port := 6379
portType := "TCP"
key := "REDIS"
tls := false
ch := make(chan Res)
Ping(ch, ip, port, tls, portType, key)
for res := range ch {
if res.Error != nil {
t.Error(res.Error)
} else {
t.Log(res.Matcher.Name())
t.Log(res.Matcher.Meta())
}
}
}
func TestPcap(t *testing.T) {
devices, err := pcap.FindAllDevs()
if err != nil {
log.Fatal(err)
}
// Print device information
fmt.Println("Devices found:")
for _, d := range devices {
fmt.Println("\nName: ", d.Name)
fmt.Println("Description: ", d.Description)
fmt.Println("Devices addresses: ", d.Description)
for _, address := range d.Addresses {
fmt.Println("- IP address: ", address.IP)
fmt.Println("- Subnet mask: ", address.Netmask)
}
}
h, err := pcap.OpenLive("{1924FA2B-6927-4BA5-AF43-876C3F8853CE}", 1600, true, pcap.BlockForever)
if err != nil {
t.Error(err)
}
if err = h.SetBPFFilter("tcp"); nil != err {
h.Close()
t.Error(err)
}
packetSource := gopacket.NewPacketSource(h, h.LinkType())
for packet := range packetSource.Packets() {
fmt.Printf("%s", packet.Dump())
}
}