port scan modified

This commit is contained in:
insanity 2018-08-15 15:18:40 +09:00
parent 02dee66629
commit 20eea426b3
10 changed files with 345 additions and 60 deletions

View File

@ -8,6 +8,7 @@
"files.trimTrailingWhitespace": true,
"files.trimFinalNewlines": true,
"go.testFlags": [
"-v"
]
"-v",
],
"go.testTimeout": "300s"
}

View File

@ -3,14 +3,19 @@ package discoverer_test
import (
"encoding/json"
"log"
"net"
"strconv"
"testing"
"time"
logging "git.loafle.net/commons/logging-go"
omd "git.loafle.net/overflow/model/discovery"
omm "git.loafle.net/overflow/model/meta"
omu "git.loafle.net/overflow/model/util"
"git.loafle.net/overflow_scanner/probe/discoverer"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"github.com/google/gopacket/pcap"
)
var (
@ -21,7 +26,7 @@ var (
Network: "192.168.1.0/24",
MetaIPType: omm.ToMetaIPType(omm.MetaIPTypeEnumV4),
Address: "192.168.1.201",
Iface: " \\Device\\NPF_{1924FA2B-6927-4BA5-AF43-876C3F8853CE}",
Iface: "\\Device\\NPF_{1924FA2B-6927-4BA5-AF43-876C3F8853CE}",
Mac: "30:9C:23:15:A3:09",
}
dh = &omd.DiscoverHost{
@ -37,7 +42,7 @@ var (
}
dp = &omd.DiscoverPort{
FirstScanRange: 1,
LastScanRange: 50000,
LastScanRange: 65535,
ExcludePorts: []int{
631,
},
@ -88,7 +93,7 @@ var (
LastScanRange: "192.168.1.255",
DiscoverPort: &omd.DiscoverPort{
FirstScanRange: 1,
LastScanRange: 50000,
LastScanRange: 20000,
ExcludePorts: []int{
631,
},
@ -191,3 +196,148 @@ func handleDiscovery(_discoverer discoverer.Discoverer, discoveryFunc func(dataC
}
}
}
type scanner struct {
// iface is the interface to send packets on.
iface *net.Interface
// destination, gateway (if applicable), and source IP addresses to use.
dst, gw, src net.IP
handle *pcap.Handle
// opts and buf allow us to easily serialize packets in the send()
// method.
opts gopacket.SerializeOptions
buf gopacket.SerializeBuffer
}
func TestTCP(t *testing.T) {
s, err := newScanner()
if err != nil {
log.Printf("unable to create scanner for : %v", err)
return
}
if err := s.scan(); err != nil {
log.Printf("unable to scan %v: %v", err)
}
s.close()
}
// newScanner creates a new scanner for a given destination IP address, using
// router to determine how to route packets to that IP.
func newScanner() (*scanner, error) {
s := &scanner{
dst: net.ParseIP("192.168.1.229"),
src: net.ParseIP("192.168.1.201"),
opts: gopacket.SerializeOptions{
FixLengths: true,
ComputeChecksums: true,
},
buf: gopacket.NewSerializeBuffer(),
}
// Open the handle for reading/writing.
// Note we could very easily add some BPF filtering here to greatly
// decrease the number of packets we have to look at when getting back
// scan results.
handle, err := pcap.OpenLive("\\Device\\NPF_{1924FA2B-6927-4BA5-AF43-876C3F8853CE}", 65536, true, pcap.BlockForever)
if err != nil {
return nil, err
}
s.handle = handle
return s, nil
}
// close cleans up the handle.
func (s *scanner) close() {
s.handle.Close()
}
func (s *scanner) scan() error {
// First off, get the MAC address we should be sending packets to.
srcMac, err := net.ParseMAC("30:9C:23:15:A3:09")
if nil != err {
return err
}
dstMac, err := net.ParseMAC("50:E5:49:46:93:28")
if nil != err {
return err
}
eth := layers.Ethernet{
SrcMAC: srcMac,
DstMAC: dstMac,
EthernetType: layers.EthernetTypeIPv4,
}
ip4 := layers.IPv4{
SrcIP: s.src,
DstIP: s.dst,
Version: 4,
TTL: 64,
Protocol: layers.IPProtocolTCP,
}
tcp := layers.TCP{
SrcPort: 60000,
DstPort: 0, // will be incremented during the scan
SYN: true,
Seq: 0,
}
if err := tcp.SetNetworkLayerForChecksum(&ip4); err != nil {
log.Println(err)
return err
}
// Create the flow we expect returning packets to have, so we can check
// against it and discard useless packets.
//ipFlow := gopacket.NewFlow(layers.EndpointIPv4, s.dst, s.src)
start := time.Now()
for {
// Send one packet per loop iteration until we've sent packets
// to all of ports [1, 65535].
if tcp.DstPort < 65535 {
start = time.Now()
tcp.DstPort++
if err := s.send(&eth, &ip4, &tcp); err != nil {
log.Printf("error sending to port %v: %v", tcp.DstPort, err)
}
}
// Time out 5 seconds after the last packet we sent.
if time.Since(start) > time.Second*60 {
log.Printf("timed out for %v, assuming we've seen all we can", s.dst)
return nil
}
// Read in the next packet.
data, _, err := s.handle.ReadPacketData()
if err == pcap.NextErrorTimeoutExpired {
continue
} else if err != nil {
log.Printf("error reading packet: %v", err)
continue
}
// Parse the packet. We'd use DecodingLayerParser here if we
// wanted to be really fast.
packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy)
if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer == nil {
continue
} else if tcp, ok := tcpLayer.(*layers.TCP); !ok {
continue
} else if tcp.DstPort != 60000 {
continue
} else if tcp.SYN && tcp.ACK {
log.Println("OPENED: ", tcp.SrcPort)
}
}
}
// send sends the given layers as a single packet on the network.
func (s *scanner) send(l ...gopacket.SerializableLayer) error {
if err := gopacket.SerializeLayers(s.buf, s.opts, l...); err != nil {
return err
}
return s.handle.WritePacketData(s.buf.Bytes())
}

View File

@ -12,7 +12,7 @@ func TestHostScan(t *testing.T) {
z := &omd.Zone{
Network: "192.168.1.0/24",
Iface: " \\Device\\NPF_{1924FA2B-6927-4BA5-AF43-876C3F8853CE}",
Iface: "\\Device\\NPF_{1924FA2B-6927-4BA5-AF43-876C3F8853CE}",
Mac: "30:9C:23:15:A3:09",
Address: "192.168.1.201",
DiscoveredDate: omu.NowPtr(),

View File

@ -69,7 +69,7 @@ func scanPortTCP(host *omd.Host, dp *omd.DiscoverPort, resultChan chan interface
}
}()
if err := sendTCP(host, dp, stopChan); nil != err {
if err := sendTCP(ps, host, dp, stopChan); nil != err {
errChan <- err
return
}
@ -82,14 +82,11 @@ func scanPortTCP(host *omd.Host, dp *omd.DiscoverPort, resultChan chan interface
}
}
func sendTCP(host *omd.Host, dp *omd.DiscoverPort, stopChan chan struct{}) error {
func sendTCP(ps pcap.PCapScanner, host *omd.Host, dp *omd.DiscoverPort, stopChan chan struct{}) error {
tcpPacket, err := makePacketPortTCP(host)
if nil != err {
return err
}
defer func() {
tcpPacket.PacketConn.Close()
}()
buf := gopacket.NewSerializeBuffer()
@ -103,12 +100,14 @@ Loop:
}
}
tcpPacket.TCP.DstPort = layers.TCPPort(portNumber)
tcpPacket.TCP.SetNetworkLayerForChecksum(tcpPacket.IP)
if err := gopacket.SerializeLayers(buf, tcpPacket.Opts, tcpPacket.TCP); err != nil {
if err := tcpPacket.TCP.SetNetworkLayerForChecksum(tcpPacket.IP); err != nil {
return err
}
if _, err := tcpPacket.PacketConn.WriteTo(buf.Bytes(), &net.IPAddr{IP: tcpPacket.IP.DstIP}); err != nil {
if err := gopacket.SerializeLayers(buf, tcpPacket.Opts, tcpPacket.Eth, tcpPacket.IP, tcpPacket.TCP); err != nil {
return err
}
if err := ps.WritePacketData(buf.Bytes()); err != nil {
return err
}
@ -129,16 +128,13 @@ func handlePacketTCP(host *omd.Host, dp *omd.DiscoverPort, ports map[int]*omd.Po
return nil
}
if packet.RST {
return nil
}
if packet.SYN && packet.ACK {
port := int(packet.SrcPort)
logging.Logger().Debugf("Discovery: IP of TCP(%d) src %s", port, host.Address)
if _, ok := ports[port]; ok || !dp.Contains(port) {
return nil
}
logging.Logger().Debugf("Discovery: IP of TCP(%d) src %s", port, host.Address)
p := &omd.Port{
MetaPortType: omm.ToMetaPortType(omm.MetaPortTypeEnumTCP),
@ -150,13 +146,18 @@ func handlePacketTCP(host *omd.Host, dp *omd.DiscoverPort, ports map[int]*omd.Po
ports[port] = p
return p
}
return nil
}
type PortPacketTCP struct {
Eth *layers.Ethernet
IP *layers.IPv4
TCP *layers.TCP
Opts gopacket.SerializeOptions
PacketConn net.PacketConn
//PacketConn net.PacketConn
}
func makePacketPortTCP(host *omd.Host) (*PortPacketTCP, error) {
@ -171,9 +172,25 @@ func makePacketPortTCP(host *omd.Host) (*PortPacketTCP, error) {
return nil, fmt.Errorf("Discovery: IP(%s) of host is not valid", host.Address)
}
srcMac, err := net.ParseMAC("30:9C:23:15:A3:09")
if nil != err {
return nil, err
}
dstMac, err := net.ParseMAC("50:E5:49:46:93:28")
if nil != err {
return nil, err
}
packetTCP.Eth = &layers.Ethernet{
SrcMAC: srcMac,
DstMAC: dstMac,
EthernetType: layers.EthernetTypeIPv4,
}
packetTCP.IP = &layers.IPv4{
SrcIP: srcIP.To4(),
DstIP: dstIP.To4(),
SrcIP: srcIP,
DstIP: dstIP,
Version: 4,
TTL: 64,
Protocol: layers.IPProtocolTCP,
@ -189,12 +206,5 @@ func makePacketPortTCP(host *omd.Host) (*PortPacketTCP, error) {
FixLengths: true,
}
conn, err := net.ListenPacket("ip4:tcp", "0.0.0.0")
if err != nil {
return nil, fmt.Errorf("Discovery: SYN create socket error %v", err)
}
packetTCP.PacketConn = conn
return packetTCP, nil
}

View File

@ -69,9 +69,8 @@ func (ps *pCapScan) start() error {
}
// 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 {
if err = h.SetBPFFilter("arp"); nil != err {
//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 {
if err = h.SetBPFFilter("arp or tcp or udp"); nil != err {
h.Close()
return err
}
@ -248,4 +247,5 @@ func handleReceive(ps *pCapScan) {
return
}
}
}

View File

@ -16,11 +16,11 @@ type Res struct {
Error error
}
func Ping(ch chan Res, ip string, port int, tls bool, portType, key string) {
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}
ch <- &Res{nil, err}
close(ch)
}
defer conn.Close()
@ -33,7 +33,7 @@ func Ping(ch chan Res, ip string, port int, tls bool, portType, key string) {
}()
}
func processPrepacket(ch chan Res, conn net.Conn, m csm.Matcher) {
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)
@ -41,25 +41,25 @@ func processPrepacket(ch chan Res, conn net.Conn, m csm.Matcher) {
_, err := conn.Write(m.Packet(i).Buffer)
if err != nil {
ch <- Res{nil, err}
ch <- &Res{nil, err}
close(ch)
}
if err := m.Match(nil, i, p); err != nil {
ch <- Res{nil, err}
ch <- &Res{nil, err}
close(ch)
}
}
ch <- Res{m, nil}
ch <- &Res{m, nil}
close(ch)
}
func processPostpacket(ch chan Res, conn net.Conn, m csm.Matcher) {
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}
ch <- &Res{nil, err}
close(ch)
}
@ -68,11 +68,11 @@ func processPostpacket(ch chan Res, conn net.Conn, m csm.Matcher) {
p := csm.NewPacket(bytes, n)
if err := m.Match(nil, i, p); err != nil {
ch <- Res{nil, err}
ch <- &Res{nil, err}
close(ch)
}
}
ch <- Res{m, nil}
ch <- &Res{m, nil}
close(ch)
}

View File

@ -12,7 +12,7 @@ func TestPing(t *testing.T) {
key := "REDIS"
tls := false
ch := make(chan Res)
ch := make(chan *Res)
Ping(ch, ip, port, tls, portType, key)
for res := range ch {

View File

@ -0,0 +1,11 @@
package service
/*
Start()
Stop()
Interfaces()
Discover()
PingHost()
PingService()
DiscoverSNMP()
*/

54
snmp/snmp.go Normal file
View File

@ -0,0 +1,54 @@
package snmp
import (
"fmt"
"github.com/k-sone/snmpgo"
)
// in progress
func getV2(ip string, port int, community string, oidMap map[string]string) (map[string]string, error) {
address := fmt.Sprintf("%s:%d", ip, port)
snmp, err := snmpgo.NewSNMP(snmpgo.SNMPArguments{
Version: snmpgo.V2c,
Address: address,
Retries: 1,
Community: community,
})
if err != nil {
return nil, err
}
defer snmp.Close()
_oids := make([]string, 0, len(oidMap))
for k := range oidMap {
_oids = append(_oids, k)
}
oids, err := snmpgo.NewOids(_oids)
if err != nil {
return nil, err
}
pdu, err := snmp.GetRequest(oids)
if err != nil {
return nil, err
}
if pdu.ErrorStatus() != snmpgo.NoError {
return nil, fmt.Errorf("%s", pdu.ErrorStatus().String())
}
if pdu == nil {
return nil, fmt.Errorf("%s", "Empty PDU")
}
res := make(map[string]string)
for _, val := range pdu.VarBinds() {
// fmt.Printf("[%s] %s = %s: %s\n", ip, oidMap[val.Oid.String()], val.Variable.Type(), val.Variable.String())
res[oidMap[val.Oid.String()]] = val.Variable.String()
}
return res, nil
}

59
snmp/snmp_test.go Normal file
View File

@ -0,0 +1,59 @@
package snmp
import (
"sync"
"testing"
)
type Agent struct {
ip string
port int
community string
}
func TestV2c(t *testing.T) {
oids := map[string]string{
"1.3.6.1.2.1.1.5.0": "sysName",
}
agents := []Agent{
Agent{
ip: "192.168.1.229",
port: 161,
community: "test1252serc",
},
Agent{
ip: "192.168.1.254",
port: 161,
community: "loafle",
},
Agent{
ip: "192.168.1.99",
port: 161,
community: "public",
},
Agent{
ip: "192.168.1.1",
port: 161,
community: "public",
},
Agent{
ip: "192.168.1.2",
port: 161,
community: "public",
},
}
var wg sync.WaitGroup
wg.Add(len(agents))
for _, agent := range agents {
go func(a Agent) {
res, _ := getV2(a.ip, a.port, a.community, oids)
t.Log(res)
defer wg.Done()
}(agent)
}
wg.Wait()
}