This commit is contained in:
crusader 2018-09-05 14:59:34 +09:00
parent 6161d7fade
commit 4728182733
2 changed files with 110 additions and 38 deletions

View File

@ -15,8 +15,16 @@ import (
"git.loafle.net/overflow_scanner/probe/internal/pcap"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
"golang.org/x/net/icmp"
"golang.org/x/net/ipv4"
)
const (
// IP flag
DF = 0x02
// // IP header len
// IPHLEN = 40
//
// SIOCGIFMTU = 0x8921
UINT16 = 65535
)
func scanV4(discoverySession session.DiscoverySession) error {
@ -38,12 +46,15 @@ func scanV4(discoverySession session.DiscoverySession) error {
}()
timerStopped := make(chan struct{})
stopChan := make(chan struct{})
defer close(stopChan)
go func() {
hosts := make(map[string]*omd.Host)
var delay atomic.Value
delay.Store(false)
ticker := time.NewTicker(time.Millisecond * 500)
ticker := time.NewTicker(time.Millisecond * 1000)
for {
select {
@ -67,7 +78,7 @@ func scanV4(discoverySession session.DiscoverySession) error {
}
}()
if err := sendICMP4(ps, zone, targetHosts); nil != err {
if err := sendICMP4(ps, discoverySession, stopChan); nil != err {
log.Printf("sendICMP %v", err)
return nil
}
@ -80,31 +91,53 @@ func scanV4(discoverySession session.DiscoverySession) error {
}
}
func sendICMP4(ps pcap.PCapScanner, zone *omd.Zone, targetHosts []net.IP) error {
conn, err := icmp.ListenPacket("ip4:icmp", "")
if nil != err {
return err
}
defer conn.Close()
func sendICMP4(ps pcap.PCapScanner, discoverySession session.DiscoverySession, stopChan chan struct{}) error {
targetHosts := discoverySession.TargetHosts()
msg, err := makeMessageICMP4()
icmp4Packet, err := makePacketICMPv4(discoverySession.Zone())
if nil != err {
return err
}
var dst net.IPAddr
buf := gopacket.NewSerializeBuffer()
LOOP:
for _, targetHost := range targetHosts {
dst.IP = targetHost
if _, err := conn.WriteTo(msg, &dst); nil != err {
h := discoverySession.DiscoveredHost(targetHost.String())
if nil != h && "" != h.Mac {
mac, err := net.ParseMAC(h.Mac)
if nil != err {
icmp4Packet.Eth.DstMAC = nil
} else {
icmp4Packet.Eth.DstMAC = mac
}
}
if nil == icmp4Packet.Eth.DstMAC {
icmp4Packet.Eth.DstMAC = net.HardwareAddr{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}
}
icmp4Packet.IP.DstIP = targetHost
icmp4Packet.IP.Id = uint16(rand.Intn(UINT16))
icmp4Packet.ICMPv4.Id = uint16(rand.Intn(0xffff))
icmp4Packet.ICMPv4.Seq = uint16(rand.Intn(0xffff))
if err := gopacket.SerializeLayers(buf, icmp4Packet.Opts, icmp4Packet.Eth, icmp4Packet.IP, icmp4Packet.ICMPv4); err != nil {
log.Print(err)
continue LOOP
}
if err := ps.WritePacketData(buf.Bytes()); err != nil {
log.Print(err)
continue LOOP
}
select {
case <-time.After(time.Microsecond * 100):
case <-stopChan:
return nil
}
}
return nil
}
@ -152,17 +185,47 @@ func handlePacketICMP4(zone *omd.Zone, targetHosts []net.IP, hosts map[string]*o
return h
}
func makeMessageICMP4() ([]byte, error) {
id := rand.Intn(0xffff)
seq := rand.Intn(0xffff)
return (&icmp.Message{
Type: ipv4.ICMPTypeEcho,
Code: 0,
Body: &icmp.Echo{
ID: id,
Seq: seq,
Data: []byte("PING by overFlow"),
},
}).Marshal(nil)
type PacketICMPv4 struct {
Eth *layers.Ethernet
IP *layers.IPv4
ICMPv4 *layers.ICMPv4
Opts gopacket.SerializeOptions
}
func makePacketICMPv4(zone *omd.Zone) (*PacketICMPv4, error) {
packetICMPv4 := &PacketICMPv4{}
srcIP := net.ParseIP(zone.Address)
if nil == srcIP {
return nil, fmt.Errorf("IP(%s) of zone is not valid", zone.Address)
}
srcMac, err := net.ParseMAC(zone.Mac)
if nil != err {
return nil, err
}
packetICMPv4.Eth = &layers.Ethernet{
SrcMAC: srcMac,
EthernetType: layers.EthernetTypeIPv4,
}
packetICMPv4.IP = &layers.IPv4{
SrcIP: srcIP,
Flags: DF,
Version: 4,
TTL: 64,
Protocol: layers.IPProtocolICMPv4,
}
packetICMPv4.ICMPv4 = &layers.ICMPv4{
TypeCode: layers.CreateICMPv4TypeCode(layers.ICMPv4TypeEchoRequest, 0),
}
packetICMPv4.Opts = gopacket.SerializeOptions{
ComputeChecksums: true,
FixLengths: true,
}
return packetICMPv4, nil
}

View File

@ -18,7 +18,12 @@ func Test_scanV4(t *testing.T) {
"testRequester",
types.DiscoveryRequestTypeHost,
__test.Zone(),
__test.DiscoverHost(__test.DiscoveryConfig(), 1, 254, nil),
__test.DiscoverHost(
__test.DiscoveryConfig(),
1,
254,
nil,
),
)
type args struct {
@ -48,9 +53,9 @@ func Test_scanV4(t *testing.T) {
func Test_sendICMP4(t *testing.T) {
type args struct {
ps pcap.PCapScanner
zone *omd.Zone
targetHosts []net.IP
ps pcap.PCapScanner
discoverySession session.DiscoverySession
stopChan chan struct{}
}
tests := []struct {
name string
@ -61,7 +66,7 @@ func Test_sendICMP4(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if err := sendICMP4(tt.args.ps, tt.args.zone, tt.args.targetHosts); (err != nil) != tt.wantErr {
if err := sendICMP4(tt.args.ps, tt.args.discoverySession, tt.args.stopChan); (err != nil) != tt.wantErr {
t.Errorf("sendICMP4() error = %v, wantErr %v", err, tt.wantErr)
}
})
@ -91,23 +96,27 @@ func Test_handlePacketICMP4(t *testing.T) {
}
}
func Test_makeMessageICMP4(t *testing.T) {
func Test_makePacketICMPv4(t *testing.T) {
type args struct {
zone *omd.Zone
}
tests := []struct {
name string
want []byte
args args
want *PacketICMPv4
wantErr bool
}{
// TODO: Add test cases.
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := makeMessageICMP4()
got, err := makePacketICMPv4(tt.args.zone)
if (err != nil) != tt.wantErr {
t.Errorf("makeMessageICMP4() error = %v, wantErr %v", err, tt.wantErr)
t.Errorf("makePacketICMPv4() error = %v, wantErr %v", err, tt.wantErr)
return
}
if !reflect.DeepEqual(got, tt.want) {
t.Errorf("makeMessageICMP4() = %v, want %v", got, tt.want)
t.Errorf("makePacketICMPv4() = %v, want %v", got, tt.want)
}
})
}