Files
tchivert fba71272b0
build / build (push) Successful in 2m8s
fix logging
2024-08-10 12:49:42 +02:00

240 lines
4.5 KiB
Go

package main
import (
"bufio"
"flag"
"fmt"
"net"
"os"
"strings"
"sync"
"time"
)
var (
iplist = flag.String("i", "ips.txt", "File containing list of IPs")
ports = flag.String("p", "1-1024", "Ports to scan")
timeout = flag.Int("t", 200, "Timeout in milliseconds")
wait = flag.Int("w", 2000, "Wait time between scans in milliseconds")
debug = flag.Bool("D", false, "Debug mode")
logdir = flag.String("l", "", "Directory to store logs")
daemon = flag.Bool("d", false, "Start in daemon mode to scan all IPs continuously")
portus = []Portus{}
)
type Portus struct {
ip string
ports []int
}
func main() {
flag.Parse()
var wg sync.WaitGroup
if *logdir != "" {
_, err := os.Stat(*logdir)
if err != nil {
err = os.Mkdir(*logdir, 0755)
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("Created logs directory: %s\n", *logdir)
}
}
ips, err := readLines(*iplist)
if err != nil {
fmt.Println(err)
return
}
start, end := checkports(*ports)
if start == 0 || end == 0 {
fmt.Println("Invalid port range:", *ports)
return
}
err = checkips(ips)
if err != nil {
fmt.Println(err)
return
}
for _, ip := range ips {
portus = append(portus, Portus{ip, []int{}})
}
fmt.Printf("Scanning for %d ports on %d IPs\n", end-start+1, len(ips))
if *debug {
fmt.Printf("Timeout: %d seconds\n", *timeout)
fmt.Printf("Wait time: %d seconds\n", *wait)
}
if *daemon {
for {
for _, ip := range ips {
fmt.Printf("Scanning %s\n", ip)
scan(ip, start, end)
}
}
} else {
fmt.Println("Starting scans")
for _, ip := range ips {
wg.Add(1)
go func(ip string) {
defer wg.Done()
scan(ip, start, end)
}(ip)
}
wg.Wait()
fmt.Println("Done")
}
}
func readLines(path string) ([]string, error) {
file, err := os.Open(path)
if err != nil {
return nil, err
}
defer file.Close()
var lines []string
scanner := bufio.NewScanner(file)
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
return lines, scanner.Err()
}
func atoi(s string) int {
i := 0
for _, r := range s {
i = i*10 + int(r-'0')
}
return i
}
func checkports(ports string) (int, int) {
p := strings.Split(ports, "-")
start := atoi(p[0])
end := start
if len(p) > 1 {
end = atoi(p[1])
}
if start < 1 || start > 65535 || end < 1 || end > 65535 {
return 0, 0
}
if start > end {
return 0, 0
}
return start, end
}
func checkips(ips []string) error {
for _, ip := range ips {
if net.ParseIP(ip) == nil {
return fmt.Errorf("Invalid IP address: %s", ip)
}
}
return nil
}
func scan(ip string, start int, end int) {
open := []int{}
for port := start; port <= end; port++ {
if *debug {
fmt.Printf("Scanning %s:%d\n", ip, port)
}
conn, err := net.DialTimeout("tcp", fmt.Sprintf("%s:%d", ip, port), time.Duration(*timeout)*time.Millisecond)
time.Sleep(time.Duration(*wait)*time.Millisecond)
if err != nil {
continue
}
conn.Close()
fmt.Printf("Port %d is open on %s\n", port, ip)
open = append(open, port)
}
if len(open) > 0 {
checkportus(ip, open)
}
}
func checkportus(ip string, open []int) {
hits := []int{}
for i, p := range portus {
if p.ip == ip {
for _, port := range open {
if !contains(p.ports, port) {
portus[i].ports = append(portus[i].ports, port)
hits = append(hits, port)
}
}
if len(hits) > 0 {
notify(ip, hits)
}
return
}
}
}
func contains(ports []int, port int) bool {
for _, p := range ports {
if p == port {
return true
}
}
return false
}
func notify(ip string, ports []int) {
if *debug {
fmt.Printf("New open ports on %s:\n", ip)
for _, port := range ports {
fmt.Printf("| %d\n", port)
}
}
fmt.Printf("Open ports on %s:\n", ip)
for _, p := range portus {
if p.ip == ip {
for _, port := range p.ports {
fmt.Printf("| %d\n", port)
}
}
}
if *logdir != "" {
dir := *logdir
if dir[len(dir)-1:] == "/" {
dir = (dir)[:len(dir)-1]
}
logfile := fmt.Sprintf("%s/%s.log", dir, ip)
if *debug {
fmt.Printf("Logging to: %s\n", logfile)
}
_, err := os.Stat(logfile)
if err == nil {
if *debug {
fmt.Printf("Removing existing log file: %s\n", logfile)
}
os.Remove(logfile)
}
if *debug {
fmt.Printf("Creating log file: %s\n", logfile)
}
f, err := os.OpenFile(logfile, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
if err != nil {
fmt.Println(err)
return
}
defer f.Close()
if *debug {
fmt.Printf("Writing to log file: %s\n", logfile)
}
for _, port := range ports {
f.WriteString(fmt.Sprintf("%d\n", port))
}
}
}