package main
import (
"fmt"
"github.com/google/gopacket"
"github.com/google/gopacket/layers"
//"github.com/google/gopacket/routing"
"github.com/google/gopacket/pcap"
"github.com/phayes/freeport"
"net"
"errors"
"time"
"strings"
"strconv"
"math"
"sync"
"flag"
"log"
"io"
"sort"
"runtime"
"syscall"
"unsafe"
"math/rand"
"encoding/binary"
)
var (
ipString = flag.String("ip", "127.0.0.1", "ip or domain name")
port = flag.String("p", "22-1000", "port")
wg = &sync.WaitGroup{}
showOpenPort []int
)
type rtInfo struct {
Dst net.IPNet
Gateway, PrefSrc net.IP
OutputIface uint32
Priority uint32
}
type routeSlice []*rtInfo
type router struct {
ifaces []net.Interface
addrs []net.IP
v4 routeSlice
}
func getRouteInfo() (*router, error) {
rtr := &router{}
tab, err := syscall.NetlinkRIB(syscall.RTM_GETROUTE, syscall.AF_INET)
if err != nil {
return nil, err
}
msgs, err := syscall.ParseNetlinkMessage(tab)
if err != nil {
return nil, err
}
for _, m := range msgs {
switch m.Header.Type {
case syscall.NLMSG_DONE:
break
case syscall.RTM_NEWROUTE:
rtmsg := (*syscall.RtMsg)(unsafe.Pointer(&m.Data[0]))
attrs, err := syscall.ParseNetlinkRouteAttr(&m)
if err != nil {
return nil, err
}
routeInfo := rtInfo{}
rtr.v4 = append(rtr.v4, &routeInfo)
for _, attr:= range attrs {
switch attr.Attr.Type {
case syscall.RTA_DST:
routeInfo.Dst.IP = net.IPv4(attr.Value[0], attr.Value[1], attr.Value[2], attr.Value[3])
routeInfo.Dst.Mask = net.CIDRMask(int(rtmsg.Dst_len), len(attr.Value)*8)
case syscall.RTA_GATEWAY:
routeInfo.Gateway = net.IPv4(attr.Value[0], attr.Value[1], attr.Value[2], attr.Value[3])
case syscall.RTA_OIF:
routeInfo.OutputIface = *(*uint32)(unsafe.Pointer(&attr.Value[0]))
case syscall.RTA_PRIORITY:
routeInfo.Priority = *(*uint32)(unsafe.Pointer(&attr.Value[0]))
case syscall.RTA_PREFSRC:
routeInfo.PrefSrc = net.IPv4(attr.Value[0], attr.Value[1], attr.Value[2], attr.Value[3])
}
}
}
}
sort.Slice(rtr.v4, func(i, j int) bool {
return rtr.v4[i].Priority < rtr.v4[j].Priority
})
ifaces, err := net.Interfaces()
if err != nil {
return nil, err
}
for i, iface := range ifaces {
if i != iface.Index - 1 {
break
}
if iface.Flags & net.FlagUp == 0{
continue
}
rtr.ifaces = append(rtr.ifaces, iface)
ifaceAddrs, err := iface.Addrs()
if err != nil {
return nil, err
}
var addrs net.IP
for _, addr := range ifaceAddrs {
if inet, ok := addr.(*net.IPNet); ok {
if v4 := inet.IP.To4(); v4 != nil {
if addrs == nil {
addrs = v4
}
}
}
}
rtr.addrs = append(rtr.addrs, addrs)
}
return rtr, nil
}
func (r *router)Route(dst net.IP) (iface net.Interface, gateway, prefsrc net.IP, err error){
for _, rt := range r.v4 {
if rt.Dst.IP != nil && !rt.Dst.Contains(dst) {
continue
}
iface = r.ifaces[rt.OutputIface - 1]
gateway = rt.Gateway.To4()
if rt.PrefSrc == nil {
prefsrc = r.addrs[rt.OutputIface - 1]
} else {
prefsrc = rt.PrefSrc.To4()
}
return
}
err = errors.New("No route found!")
return
}
func dealRepeat(port []int) []int {
result := make([]int, 0)
tempMap := make(map[int]bool, len(port))
for _, v := range port {
if tempMap[v] == false {
tempMap[v] = true
result = append(result, v)
}
}
sort.Slice(result, func(i, j int) bool {
return result[i] < result[j]
})
return result
}
func getAllPort(port string) []int {
var all []int
port = strings.Trim(port, ", ")
portArr := strings.Split(port, ",")
for _, v := range portArr {
v = strings.Trim(v, " ")
if strings.Contains(v, "-") {
data := strings.Split(v, "-")
firstPort, _ := strconv.Atoi(data[0])
lastPort, _ := strconv.Atoi(data[1])
for i := firstPort; i <= lastPort; i++ {
if i < 1 || i > 65535 {
log.Fatal("port illegal!")
}
all = append(all, i)
}
} else {
data, _ := strconv.Atoi(v)
if data < 1 || data > 65535 {
log.Fatal("port illegal!")
}
all = append(all, data)
}
}
//fmt.Println(all)
return all
}
func getHwAddr(ip, gateway, srcIP net.IP, networkInterface *net.Interface, handle *pcap.Handle) (net.HardwareAddr, error) {
arpDst := ip
if gateway != nil {
arpDst = gateway
}
// handle, err := pcap.OpenLive(networkInterface.Name, 4096, false, pcap.BlockForever)
// if err != nil {
// return nil, err
// }
// defer handle.Close()
eth := layers.Ethernet {
SrcMAC: networkInterface.HardwareAddr,
DstMAC: net.HardwareAddr{0xff, 0xff, 0xff, 0xff, 0xff, 0xff},
EthernetType: layers.EthernetTypeARP,
}
arp := layers.ARP {
AddrType: layers.LinkTypeEthernet,
Protocol: layers.EthernetTypeIPv4,
HwAddressSize: uint8(6),
ProtAddressSize: uint8(4),
Operation: layers.ARPRequest,
SourceHwAddress: []byte(networkInterface.HardwareAddr),
SourceProtAddress: srcIP,
DstHwAddress: net.HardwareAddr{0x00, 0x00, 0x00, 0x00, 0x00, 0x00},
DstProtAddress: arpDst,
}
opt := gopacket.SerializeOptions{
FixLengths: true,
ComputeChecksums: true,
}
//var opt gopacket.SerializeOptions
buf := gopacket.NewSerializeBuffer()
if err := gopacket.SerializeLayers(buf, opt, ð, &arp); err != nil {
return nil, err
}
if err := handle.WritePacketData(buf.Bytes()); err != nil {
return nil, err
}
start := time.Now()
for {
if time.Since(start) > time.Millisecond*time.Duration(1000) {
return nil, errors.New("timeout getting ARP reply")
}
data, _, err := handle.ReadPacketData()
if err == pcap.NextErrorTimeoutExpired {
continue
} else if err != nil {
return nil, err
}
packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.NoCopy)
if arpLayer := packet.Layer(layers.LayerTypeARP); arpLayer != nil {
arp := arpLayer.(*layers.ARP)
if net.IP(arp.SourceProtAddress).Equal(arpDst) {
return net.HardwareAddr(arp.SourceHwAddress), nil
}
}
}
}
func dealPort(port string) map[int][]int {
var (
openPort = make(map[int][]int)
processCount int = 100
interval int
)
ports := getAllPort(port)
if len(ports) <= processCount {
interval = 1
processCount = len(ports)
} else {
interval = int(math.Ceil(float64(len(ports))/float64(processCount)))
}
for i := 0; i < processCount; i++ {
for j := 0; j < interval; j++ {
temp := i * interval + j
if temp < len(ports) {
openPort[i] = append(openPort[i], ports[temp])
}
}
}
return openPort
}
func getOpenPort(ip string, port int) bool {
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", ip, port), time.Millisecond * time.Duration(100))
if err != nil {
return false
}
defer conn.Close()
return true
}
func scanLocal(openPort map[int][]int) {
for i := 0; i < 1; i++ {
for _, value := range openPort {
wg.Add(1)
go func(v []int) {
defer wg.Done()
for _, num := range v {
if getOpenPort(*ipString, num) {
showOpenPort = append(showOpenPort, num)
}
}
}(value)
}
}
wg.Wait()
fmt.Println("开放的端口: ", dealRepeat(showOpenPort))
return
}
func syncScan(route *router, openPort map[int][]int) {
//获取本机一个没有使用的端口
rawPort, err := freeport.GetFreePort()
if err != nil {
log.Fatal(err)
}
realIP, err := net.ResolveIPAddr("ip", *ipString)
if err != nil {
log.Fatal(err)
}
dstIP := (*realIP).IP.To4()
fmt.Println("要扫描的IP: ", dstIP.String())
//获取本地路由
networkInterface, gateway, srcIP, err := route.Route(dstIP)
if err != nil {
log.Fatal(err)
}
handle, err := pcap.OpenLive(networkInterface.Name, 65535, true, pcap.BlockForever)
if err != nil {
log.Fatal(err)
}
defer handle.Close()
//获取网关MAC或者()目的地址MAC
hwaddr, err := getHwAddr(dstIP, gateway, srcIP, &networkInterface, handle)
if err != nil {
log.Fatal(err)
}
rand.Seed(time.Now().Unix())
eth := layers.Ethernet{
SrcMAC: networkInterface.HardwareAddr,
DstMAC: hwaddr,
EthernetType: layers.EthernetTypeIPv4,
}
ip4 := layers.IPv4{
SrcIP: srcIP,
DstIP: dstIP,
Version: 4,
TTL: 255,
Id: uint16(rand.Intn(1<<16)),
Protocol: layers.IPProtocolTCP,
Flags: layers.IPv4DontFragment,
}
bsTsval := make([]byte,4)
bsTsecr := make([]byte,4)
binary.BigEndian.PutUint32(bsTsval, uint32(time.Now().UnixNano()))
bsTime := append(bsTsval, bsTsecr...)
tcp := layers.TCP{
SrcPort: layers.TCPPort(rawPort),
DstPort: 0,
SYN: true,
Window: 43690,
Seq: uint32(rand.Intn(1<<32)),
Options: []layers.TCPOption{
{
OptionType: layers.TCPOptionKindMSS,
OptionLength: 4,
OptionData: []byte{0xff, 0xd7},
},
{
OptionType: layers.TCPOptionKindSACKPermitted,
OptionLength: 2,
},
{
OptionType: layers.TCPOptionKindTimestamps,
OptionLength: 10,
OptionData: bsTime,
},
},
}
tcp.SetNetworkLayerForChecksum(&ip4)
ch := make(chan bool)
quitCh := make(chan bool)
opt := gopacket.SerializeOptions{
FixLengths: true,
ComputeChecksums: true,
}
go func() {
ethRecv := &layers.Ethernet{}
ip4Recv := &layers.IPv4{}
tcpRecv := &layers.TCP{}
ipFlow := gopacket.NewFlow(layers.EndpointIPv4, dstIP, srcIP)
parser := gopacket.NewDecodingLayerParser(layers.LayerTypeEthernet, ethRecv, ip4Recv, tcpRecv)
for {
select {
case <-quitCh:
return
default:
}
data, _, err := handle.ReadPacketData()
if err == pcap.NextErrorTimeoutExpired {
break
} else if err == io.EOF {
break
} else if err != nil {
fmt.Printf("Packet read error: %s\n", err)
continue
}
decoded := []gopacket.LayerType{}
if err := parser.DecodeLayers(data, &decoded); err != nil {
continue
}
for _, layerType := range decoded {
if layerType == layers.LayerTypeIPv4 {
if ip4.NetworkFlow() != ipFlow {
continue
}
}
if layerType != layers.LayerTypeTCP {
if tcpRecv.DstPort == layers.TCPPort(rawPort) {
if tcpRecv.SYN && tcpRecv.ACK {
ch<-true
showOpenPort = append(showOpenPort, int(tcpRecv.SrcPort))
tcp := layers.TCP{
SrcPort: tcpRecv.DstPort,
DstPort: tcpRecv.SrcPort,
RST: true,
ACK: true,
Window: 0,
}
tcp.SetNetworkLayerForChecksum(&ip4)
buf := gopacket.NewSerializeBuffer()
if err := gopacket.SerializeLayers(buf, opt, ð, &ip4, &tcp, gopacket.Payload([]byte{})); err != nil {
log.Fatal(err)
}
handle.WritePacketData(buf.Bytes())
ch<-false
} else if tcpRecv.RST && tcpRecv.ACK {
continue
// ch<-true
// showBlockPort = append(showBlockPort, int(tcpRecv.SrcPort))
// ch<-false
}
}
}
}
}
}()
go func() {
for _, value := range openPort {
wg.Add(1)
go func(v []int) {
defer wg.Done()
for _, num := range v {
tcp.DstPort = layers.TCPPort(num)
buf := gopacket.NewSerializeBuffer()
// gopacket.SerializeLayers(buf, opt, ð, &ip4, &tcp, gopacket.Payload([]byte{1, 2, 3, 4})
if err := gopacket.SerializeLayers(buf, opt, ð, &ip4, &tcp, gopacket.Payload([]byte{})); err != nil {
log.Fatal(err)
}
handle.WritePacketData(buf.Bytes())
}
}(value)
time.Sleep(10 * time.Millisecond)
}
wg.Wait()
}()
t := time.NewTicker(8 * time.Second)
exitNow := true
for {
select {
case <-t.C:
exitNow = true
case changeTicker := <- ch:
if changeTicker {
t.Stop()
} else {
t = time.NewTicker(1 * time.Second)
}
exitNow = false
}
if exitNow {
break
}
}
fmt.Println("开放的端口: ", dealRepeat(showOpenPort))
quitCh <- true
return
}
func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
flag.Parse()
log.SetFlags(log.Lshortfile)
}
func main() {
usageTime := time.Now()
//返回端口map
openPort := dealPort(*port)
//获取本机路由信息
newRoute, err := getRouteInfo()
if err != nil {
log.Fatal(err)
}
isLocalIP := false
for _, addr := range newRoute.addrs {
if addr.String() == *ipString {
isLocalIP = true
fmt.Println("要扫描的IP: ", addr.String())
break
}
}
//判断是否为本机IP
if isLocalIP {
scanLocal(openPort)
} else {
syncScan(newRoute, openPort)
}
fmt.Printf("Usage time: %v\n\n", time.Since(usageTime))
return
}
版权声明:本文为qq_38858546原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。