func ScanCIDR(config ScanConfig, cidrAddresses ...string) <-chan PortACK {
	defer func() {
		if r := recover(); r != nil {
			fmt.Printf("Error: %+v\n", r)
			os.Exit(1)
		}
	}()
	rate := 1000
	if config.PacketsPerSecond > 0 {
		rate = config.PacketsPerSecond
	} else {
		panic(fmt.Errorf("Invalid packets per second: %d. Stopping", config.PacketsPerSecond))
	}
	rl := ratelimit.New(rate)  
	route := getRoute(config)
	cidrPortMap := make(map[string][]int)
	for _, cidrX := range cidrAddresses {
		ports := []int{}
		if strings.Contains(cidrX, ":") {
			cidrPorts := strings.Split(cidrX, ":")
			cRange := ""
			if strings.Contains(cidrX, "/") {
				cRange = "/" + strings.Split(cidrX, "/")[1]
			}
			cidrX = cidrPorts[0] + cRange
			ports = parsePorts(strings.Split(cidrPorts[1], "/")[0])
		}
		cidrX = getNet(cidrX)
		if len(ports) == 0 {
			ports = knownPorts[:]
		}
		if currentPorts, present := cidrPortMap[cidrX]; !present {
			cidrPortMap[cidrX] = ports
		} else {
			cidrPortMap[cidrX] = append(currentPorts, ports...)
		}
	}
	cidrXs := []string{}
	for cidrX := range cidrPortMap {
		cidrXs = append(cidrXs, "net "+cidrX)
	}
	filter := fmt.Sprintf(`(%s) and not src host %s`, strings.Join(cidrXs, " or "), route.SrcIP.String())
	handle := getHandle(filter, config)
	stop := make(chan bool, 1)
	out := listenForACKPackets(handle, route, config, stop)
	go func() {
		sampleIP := ""
		for cidrX, cidrPorts := range cidrPortMap {
			ipAdds := cidr.Expand(cidrX)
			if len(ipAdds) == 0 {
				continue
			}
			mathrand.Shuffle(len(ipAdds), func(i, j int) {
				ipAdds[i], ipAdds[j] = ipAdds[j], ipAdds[i]
			})
			sampleIP = ipAdds[0]
			count := 1  
			go func(ips []string, ports []int) {  
				writeHandle := getNonFilteredHandle(config)
				defer writeHandle.Close()
				stopPort := 65535
				sourcePort := 50000
				for _, dstPort := range ports {
					for _, dstIP := range ips {
						dst := net.ParseIP(dstIP)
						for i := 0; i < count; i++ {
							rl.Take()
							err := sendSYNPacket(route.SrcIP, dst, sourcePort, dstPort, route, writeHandle)
							bailout(err)
							sourcePort++
							if sourcePort > stopPort {
								sourcePort = 50000
							}
						}
					}
				}
			}(ipAdds, cidrPorts)
		}
		timeout := time.Duration(config.Timeout) * time.Second
		select {
		case <-time.After(timeout):
			closeHandle(handle, sampleIP, config, stop)
		}
		return
	}()
	return out
}
ScanCIDR scans for open TCP ports in IP addresses within a CIDR range
package portscan
import (
	"crypto/rand"
	"encoding/binary"
	"errors"
	"fmt"
	"io"
	mathrand "math/rand"
	"net"
	"os"
	"strconv"
	"strings"
	"sync"
	"time"
	"github.com/jackpal/gateway"
	"github.com/adedayo/cidr"
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
	"go.uber.org/ratelimit"
)
var (
	options = gopacket.SerializeOptions{
		FixLengths:       true,
		ComputeChecksums: true,
	}
	tcpOptions = []layers.TCPOption{
		layers.TCPOption{
			OptionType:   layers.TCPOptionKindMSS,
			OptionLength: 4,
			OptionData:   []byte{0x5, 0xb4},  
		},
		layers.TCPOption{
			OptionType: layers.TCPOptionKindNop,
		},
		layers.TCPOption{
			OptionType:   layers.TCPOptionKindWindowScale,
			OptionLength: 3,
			OptionData:   []byte{0x5},
		},
		layers.TCPOption{
			OptionType: layers.TCPOptionKindNop,
		},
		layers.TCPOption{
			OptionType: layers.TCPOptionKindNop,
		},
		layers.TCPOption{
			OptionType:   layers.TCPOptionKindTimestamps,
			OptionLength: 10,
			OptionData:   []byte{0xac, 0x49, 0x31, 0xcb, 0x0, 0x0, 0x0, 0x0},
		},
		layers.TCPOption{
			OptionType:   layers.TCPOptionKindSACKPermitted,
			OptionLength: 2,
		},
		layers.TCPOption{
			OptionType: layers.TCPOptionKindEndList,
		},
	}
	lastConfig ScanConfig
	lastRoute  routeFinder
)
type routeFinder struct {
	IsPPP           bool
	IsTun           bool
	SrcHardwareAddr net.HardwareAddr
	DstHardwareAddr net.HardwareAddr
	SrcIP           net.IP
	Device          pcap.Interface
	Interface       net.Interface
}