tcp scan by connection added

This commit is contained in:
crusader 2018-08-31 23:00:08 +09:00
parent 92279d4944
commit 99166af860
13 changed files with 415 additions and 3 deletions

View File

@ -11,6 +11,9 @@ import (
"git.loafle.net/overflow_scanner/probe/discovery/protocol/snmp"
"git.loafle.net/overflow_scanner/probe/discovery/protocol/upnp"
"git.loafle.net/overflow_scanner/probe/discovery/session"
"git.loafle.net/overflow_scanner/probe/discovery/target/host"
"git.loafle.net/overflow_scanner/probe/discovery/target/port"
"git.loafle.net/overflow_scanner/probe/discovery/target/service"
"git.loafle.net/overflow_scanner/probe/discovery/types"
)
@ -218,5 +221,71 @@ func (d *ofDiscoverer) complexDiscover(s session.DiscoverySession) {
}
func (d *ofDiscoverer) hierarchyDiscover(s session.DiscoverySession) {
var wg sync.WaitGroup
discoveredChan := make(chan interface{})
s.SetDiscoveryDelegator(discoveredChan)
defer func() {
s.SetDiscoveryDelegator(nil)
close(discoveredChan)
}()
go func() {
for {
select {
case target, ok := <-discoveredChan:
if !ok {
return
}
switch target.(type) {
case *omd.Host:
d.SendMessage(s.DiscoveryRequest(), types.DiscoveryMessageTypeHost, target, nil)
if nil != s.DiscoverPort() {
wg.Add(1)
go func() {
defer wg.Done()
port.Scan(s, target.(*omd.Host))
}()
}
case *omd.Port:
d.SendMessage(s.DiscoveryRequest(), types.DiscoveryMessageTypePort, target, nil)
if nil != s.DiscoverService() {
wg.Add(1)
go func() {
defer wg.Done()
service.Scan(s, target.(*omd.Port))
}()
}
case *omd.Service:
d.SendMessage(s.DiscoveryRequest(), types.DiscoveryMessageTypeService, target, nil)
default:
}
}
}
}()
if nil != s.DiscoverHost() {
wg.Add(1)
go func() {
defer wg.Done()
host.Scan(s)
}()
} else if nil != s.DiscoverPort() {
if nil != s.Host() {
wg.Add(1)
go func() {
defer wg.Done()
port.Scan(s, s.Host())
}()
}
} else if nil != s.DiscoverService() {
if nil != s.Port() {
wg.Add(1)
go func() {
defer wg.Done()
service.Scan(s, s.Port())
}()
}
}
wg.Wait()
}

View File

@ -0,0 +1,116 @@
package connection
import (
"context"
"encoding/json"
"log"
"net"
"os/exec"
"strconv"
"strings"
"sync"
"time"
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/discovery/session"
"golang.org/x/sync/semaphore"
)
const (
defaultUlimit = 1024
)
func Scan(discoverySession session.DiscoverySession, targetHost *omd.Host) error {
if nil == targetHost || nil == discoverySession.DiscoverPort() {
return nil
}
dp := discoverySession.DiscoverPort()
lock := semaphore.NewWeighted(Ulimit())
var wg sync.WaitGroup
timeout := 500 * time.Millisecond
ports := make(map[int]*omd.Port)
Loop:
for portNumber := dp.FirstScanRange; portNumber < dp.LastScanRange; portNumber++ {
if nil != dp.ExcludePorts {
for _, exPortNumber := range dp.ExcludePorts {
if portNumber == exPortNumber {
continue Loop
}
}
}
lock.Acquire(context.TODO(), 1)
wg.Add(1)
go func(port int) {
defer func() {
lock.Release(1)
wg.Done()
}()
scanPort(discoverySession, ports, targetHost, port, timeout)
}(portNumber)
timer := time.NewTimer(time.Microsecond * 100)
select {
case <-timer.C:
}
}
wg.Wait()
return nil
}
func scanPort(discoverySession session.DiscoverySession, ports map[int]*omd.Port, targetHost *omd.Host, port int, timeout time.Duration) {
addr := net.JoinHostPort(targetHost.Address, strconv.Itoa(port))
conn, err := net.DialTimeout("tcp", addr, timeout)
dp := discoverySession.DiscoverPort()
if err != nil {
if strings.Contains(err.Error(), "too many open files") {
time.Sleep(timeout)
scanPort(discoverySession, ports, targetHost, port, timeout)
}
return
}
conn.Close()
if _, ok := ports[port]; ok || !dp.Contains(port) {
return
}
p := &omd.Port{
MetaPortType: omm.ToMetaPortType(omm.MetaPortTypeEnumTCP),
PortNumber: json.Number(strconv.Itoa(port)),
DiscoveredDate: omu.NowPtr(),
}
p.Host = targetHost
ports[port] = p
log.Printf("port: %v", p)
}
func Ulimit() int64 {
out, err := exec.Command("ulimit", "-n").Output()
if nil != err {
return defaultUlimit
}
s := strings.TrimSpace(string(out))
i, err := strconv.ParseInt(s, 10, 64)
if nil != err {
return defaultUlimit
}
return i
}

View File

@ -0,0 +1,107 @@
package connection
import (
"testing"
"time"
omd "git.loafle.net/overflow/model/discovery"
omm "git.loafle.net/overflow/model/meta"
"git.loafle.net/overflow_scanner/probe/discovery/session"
"git.loafle.net/overflow_scanner/probe/discovery/types"
)
func TestScan(t *testing.T) {
s := session.NewMockDiscoverySession(
"testRequester",
types.DiscoveryRequestTypeHost,
&omd.Zone{
Network: "192.168.1.0/24",
Iface: "enp3s0",
MetaIPType: omm.ToMetaIPType(omm.MetaIPTypeEnumV4),
Address: "192.168.1.101",
Mac: "44:8a:5b:f1:f1:f3",
},
&omd.DiscoverHost{
MetaIPType: omm.ToMetaIPType(omm.MetaIPTypeEnumV4),
FirstScanRange: "192.168.1.1",
LastScanRange: "192.168.1.254",
DiscoveryConfig: &omd.DiscoveryConfig{},
DiscoverPort: &omd.DiscoverPort{
FirstScanRange: 1,
LastScanRange: 65535,
IncludeTCP: true,
},
},
)
targetHost := &omd.Host{
MetaIPType: omm.ToMetaIPType(omm.MetaIPTypeEnumV4),
Name: "atGame",
Address: "192.168.1.1",
Mac: "00:11:32:7f:20:61",
Zone: s.Zone(),
}
type args struct {
discoverySession session.DiscoverySession
targetHost *omd.Host
}
tests := []struct {
name string
args args
wantErr bool
}{
{
name: "1",
args: args{
discoverySession: s,
targetHost: targetHost,
},
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := Scan(tt.args.discoverySession, tt.args.targetHost); (err != nil) != tt.wantErr {
t.Errorf("Scan() error = %v, wantErr %v", err, tt.wantErr)
}
})
}
}
func Test_scanPort(t *testing.T) {
type args struct {
discoverySession session.DiscoverySession
ports map[int]*omd.Port
targetHost *omd.Host
port int
timeout time.Duration
}
tests := []struct {
name string
args args
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
scanPort(tt.args.discoverySession, tt.args.ports, tt.args.targetHost, tt.args.port, tt.args.timeout)
})
}
}
func TestUlimit(t *testing.T) {
tests := []struct {
name string
want int64
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := Ulimit(); got != tt.want {
t.Errorf("Ulimit() = %v, want %v", got, tt.want)
}
})
}
}

View File

@ -1,4 +1,4 @@
package tcp
package syn
import (
omd "git.loafle.net/overflow/model/discovery"

View File

@ -1,4 +1,4 @@
package tcp
package syn
import (
"encoding/json"

View File

@ -1,4 +1,4 @@
package tcp
package syn
import (
"reflect"

View File

@ -0,0 +1,59 @@
package host
import (
"sync"
"git.loafle.net/overflow_scanner/probe/discovery/protocol/arp"
"git.loafle.net/overflow_scanner/probe/discovery/protocol/icmp"
"git.loafle.net/overflow_scanner/probe/discovery/session"
"git.loafle.net/overflow_scanner/probe/internal/pcap"
)
func Scan(discoverySession session.DiscoverySession) error {
targetHosts := discoverySession.TargetHosts()
if nil == targetHosts || 0 == len(targetHosts) || nil == discoverySession.DiscoverHost() {
return nil
}
zone := discoverySession.Zone()
var privileged bool
_, err := pcap.RetainScanner(zone)
if nil == err {
pcap.ReleaseScanner(zone)
privileged = true
}
if privileged {
return privilegedScan(discoverySession)
}
return unprivilegedScan(discoverySession)
}
func privilegedScan(discoverySession session.DiscoverySession) error {
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
arp.Scan(discoverySession)
}()
wg.Add(1)
go func() {
defer wg.Done()
icmp.Scan(discoverySession)
}()
wg.Wait()
return nil
}
func unprivilegedScan(discoverySession session.DiscoverySession) error {
return nil
}

View File

@ -0,0 +1,61 @@
package port
import (
"sync"
omd "git.loafle.net/overflow/model/discovery"
"git.loafle.net/overflow_scanner/probe/discovery/protocol/tcp/connection"
"git.loafle.net/overflow_scanner/probe/discovery/protocol/tcp/syn"
"git.loafle.net/overflow_scanner/probe/discovery/session"
"git.loafle.net/overflow_scanner/probe/internal/pcap"
)
func Scan(discoverySession session.DiscoverySession, targetHost *omd.Host) error {
if nil == targetHost || nil == discoverySession.DiscoverPort() {
return nil
}
zone := discoverySession.Zone()
var privileged bool
_, err := pcap.RetainScanner(zone)
if nil == err {
pcap.ReleaseScanner(zone)
privileged = true
}
if privileged {
return privilegedScan(discoverySession, targetHost)
}
return unprivilegedScan(discoverySession, targetHost)
}
func privilegedScan(discoverySession session.DiscoverySession, targetHost *omd.Host) error {
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
syn.Scan(discoverySession, targetHost)
}()
wg.Wait()
return nil
}
func unprivilegedScan(discoverySession session.DiscoverySession, targetHost *omd.Host) error {
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
connection.Scan(discoverySession, targetHost)
}()
wg.Wait()
return nil
}