summaryrefslogtreecommitdiff
path: root/src/main/java/com/it_jaros/networkScanner
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/com/it_jaros/networkScanner')
-rw-r--r--src/main/java/com/it_jaros/networkScanner/App.java36
-rw-r--r--src/main/java/com/it_jaros/networkScanner/CliParser.java80
-rw-r--r--src/main/java/com/it_jaros/networkScanner/Counter.java25
-rw-r--r--src/main/java/com/it_jaros/networkScanner/PortRange.java91
-rw-r--r--src/main/java/com/it_jaros/networkScanner/Progress.java5
-rw-r--r--src/main/java/com/it_jaros/networkScanner/ProgressBar.java75
-rw-r--r--src/main/java/com/it_jaros/networkScanner/ScanOptions.java5
-rw-r--r--src/main/java/com/it_jaros/networkScanner/ScanResult.java5
-rw-r--r--src/main/java/com/it_jaros/networkScanner/Scanner.java148
9 files changed, 0 insertions, 470 deletions
diff --git a/src/main/java/com/it_jaros/networkScanner/App.java b/src/main/java/com/it_jaros/networkScanner/App.java
deleted file mode 100644
index d02fd8a..0000000
--- a/src/main/java/com/it_jaros/networkScanner/App.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.it_jaros.networkScanner;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
-public class App {
- public static void main(String[] args) {
- CliParser cliParser = new CliParser();
- try {
- ScanOptions options = cliParser.parseArgs(args);
- Scanner scanner = new Scanner(options.openSocketLimit(), options.timeoutInMillis(),
- options.delayInMillis(), options.maxWorkersPerHost());
- printResults(scanner.scan(options));
- } catch (IllegalArgumentException e) {
- System.out.printf("Error while parsing arguments: %s", e.getMessage());
- cliParser.usageAndExit();
- } catch (Exception e) {
- System.out.printf("ERROR: %s", e.getMessage());
- }
- }
-
- public static void printResults(List<ScanResult> results) {
- results.forEach(App::printResult);
- }
-
- private static void printResult(ScanResult result) {
- String ports = result.openPorts().stream().mapToObj(String::valueOf).collect(Collectors.joining(","));
- String output = "[" + result.target() + "]:";
- if (ports.isEmpty()) {
- output = output + "No open ports found";
- } else {
- output = output + ports;
- }
- System.out.print(output + "\n");
- }
-}
diff --git a/src/main/java/com/it_jaros/networkScanner/CliParser.java b/src/main/java/com/it_jaros/networkScanner/CliParser.java
deleted file mode 100644
index 201b18a..0000000
--- a/src/main/java/com/it_jaros/networkScanner/CliParser.java
+++ /dev/null
@@ -1,80 +0,0 @@
-package com.it_jaros.networkScanner;
-
-import java.util.HashSet;
-import java.util.Set;
-
-public class CliParser {
-
- public ScanOptions parseArgs(String[] args) {
- if (args.length < 1 || args[0].trim().equals("")) {
- throw new IllegalArgumentException("No argument given");
- }
-
- Set<String> targets = new HashSet<>();
- int socketLimit = 1000;
- int delayInMillis = 0;
- int timeoutInMillis = 1000;
- int maxWorkersPerHost = 1000;
- String ports = "1-1024";
- for (int i = 0; i < args.length; i++) {
- final String currentArg = args[i];
- if (!currentArg.startsWith("-")) {
- targets.add(currentArg);
- continue;
- }
-
- try {
- switch (currentArg) {
- case "--help", "-h":
- usageAndExit();
- break;
- case "--socketLimit", "-sl":
- socketLimit = Integer.parseInt(args[++i]);
- break;
- case "--delay", "-d":
- delayInMillis = Integer.parseInt(args[++i]);
- break;
- case "--timeout", "-t":
- timeoutInMillis = Integer.parseInt(args[++i]);
- break;
- case "--maxWorkersPerHost", "-wh":
- maxWorkersPerHost = Integer.parseInt(args[++i]);
- break;
- case "--ports", "-p":
- ports = args[++i];
- break;
- default:
- throw new IllegalArgumentException("No such param " + currentArg);
- }
- } catch (IndexOutOfBoundsException | NumberFormatException e) {
- System.out.printf("Missing or wrong argument for option %s", currentArg);
- System.exit(2);
- }
- }
-
- System.out.printf(
- "Parsed arguments: targets('%s'), ports(%s), socketLimit(%s), delayInMillis(%s), timeoutInMillis(%s), maxWorkersPerHost(%s)%n",
- targets, ports, socketLimit, delayInMillis, timeoutInMillis, maxWorkersPerHost);
-
- return new ScanOptions(targets.stream().toList(), socketLimit, delayInMillis, timeoutInMillis, maxWorkersPerHost, ports);
- }
-
- public void usageAndExit() {
- System.err.println("""
- Usage:
- java -jar scanner.jar [OPTIONS] <host>
-
- Options:
- --delay, -d: Waiting period in millis for connection attempts for a host; (Default: 0)
- --socketLimit, -sl: Socket Connection limit for a host; (Default: 1000)
- --timeout, -t: Timeout per connection attempt, 0 means infinite: (Default: 1000)
- --ports, -p: Ports to be scanned
- --maxWorkersPerHost, -wh: Virtual Worker Threads run per target. Higher doesn't mean necessarily faster. But the more you use the more RAM is required. (Default: 1000)
-
- Examples:
- java -jar scanner.jar localhost
- java -jar scanner.jar fd00::1
- """);
- System.exit(1);
- }
-}
diff --git a/src/main/java/com/it_jaros/networkScanner/Counter.java b/src/main/java/com/it_jaros/networkScanner/Counter.java
deleted file mode 100644
index a4baec0..0000000
--- a/src/main/java/com/it_jaros/networkScanner/Counter.java
+++ /dev/null
@@ -1,25 +0,0 @@
-package com.it_jaros.networkScanner;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-public final class Counter {
- private final AtomicInteger current = new AtomicInteger(0);
- private final AtomicInteger max = new AtomicInteger(0);
-
- public void inc() {
- int now = current.incrementAndGet();
- max.accumulateAndGet(now, Math::max);
- }
-
- public void dec() {
- current.decrementAndGet();
- }
-
- public int current() {
- return current.get();
- }
-
- public int max() {
- return max.get();
- }
-}
diff --git a/src/main/java/com/it_jaros/networkScanner/PortRange.java b/src/main/java/com/it_jaros/networkScanner/PortRange.java
deleted file mode 100644
index 9075ec2..0000000
--- a/src/main/java/com/it_jaros/networkScanner/PortRange.java
+++ /dev/null
@@ -1,91 +0,0 @@
-package com.it_jaros.networkScanner;
-
-import java.util.BitSet;
-import java.util.NoSuchElementException;
-
-public class PortRange {
-
- public static final int MIN_PORT = 1;
- public static final int MAX_PORT = 65535;
- private final BitSet specifiedPorts = new BitSet(MAX_PORT);
- private final BitSet availablePorts = new BitSet(MAX_PORT);
-
- private int cursor;
- private int done = 0;
-
- public PortRange(String ports) {
- if (ports == null || "".equals(ports)) {
- // keep defaults
- specifiedPorts.set(1, 1024 + 1);
- return;
- }
-
- String[] splitComma = ports.split(",");
- for (String commaValue : splitComma) {
- if (commaValue.contains("-")) {
- String[] rangeValue = commaValue.split("-");
- if (rangeValue.length > 2) {
- throw new IllegalArgumentException(String.format("Argument contains too many '-'' %s", commaValue));
- }
-
- int start = Integer.parseInt(rangeValue[0]);
- int end = Integer.parseInt(rangeValue[1]);
- checkValues(start, end);
- specifiedPorts.set(start, end + 1);
- } else {
- int port = Integer.parseInt(commaValue);
- checkValue(port);
- specifiedPorts.set(Integer.parseInt(commaValue));
- }
- }
-
- availablePorts.or(specifiedPorts);
- cursor = availablePorts.nextSetBit(MIN_PORT);
- }
-
- private void checkValues(int start, int end) {
- checkValue(start);
- checkValue(end);
-
- if (start >= end) {
- throw new IllegalArgumentException(
- String.format("Start value cannot be equal or bigger than end value '%s >= %s'", start, end));
- }
- }
-
- private void checkValue(int port) {
- if (port < MIN_PORT) {
- throw new IllegalArgumentException(
- String.format("Start value smaller than allowed range %s < %s", port, MIN_PORT));
- }
-
- if (port > MAX_PORT) {
- throw new IllegalArgumentException(
- String.format("End value bigger than allowed range %s > %s", port, MAX_PORT));
- }
- }
-
- public int next() {
- int p = availablePorts.nextSetBit(cursor);
- if (p > 0) {
- availablePorts.clear(p);
- cursor = p + 1;
- done++;
- return p;
- }
-
- throw new NoSuchElementException("Reached end of port range");
- }
-
- public boolean hasNext() {
- return availablePorts.nextSetBit(cursor) > 0;
- }
-
- public int getTotal() {
- return specifiedPorts.cardinality();
- }
-
- public int getDone() {
- return done;
- }
-}
diff --git a/src/main/java/com/it_jaros/networkScanner/Progress.java b/src/main/java/com/it_jaros/networkScanner/Progress.java
deleted file mode 100644
index 521046d..0000000
--- a/src/main/java/com/it_jaros/networkScanner/Progress.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.it_jaros.networkScanner;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-public record Progress(String host, int total, AtomicInteger done, AtomicInteger open) {} \ No newline at end of file
diff --git a/src/main/java/com/it_jaros/networkScanner/ProgressBar.java b/src/main/java/com/it_jaros/networkScanner/ProgressBar.java
deleted file mode 100644
index ca755a6..0000000
--- a/src/main/java/com/it_jaros/networkScanner/ProgressBar.java
+++ /dev/null
@@ -1,75 +0,0 @@
-package com.it_jaros.networkScanner;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.Executors;
-import java.util.concurrent.ScheduledExecutorService;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.ReentrantLock;
-
-public class ProgressBar {
-
- private final ScheduledExecutorService ui = Executors.newSingleThreadScheduledExecutor();
- private final ReentrantLock lock = new ReentrantLock();
-
- private List<Progress> hosts;
-
- public void start() {
- this.hosts = new ArrayList<>();
- System.out.print("Scanning targets...\n\n");
- ui.scheduleAtFixedRate(() -> {
- lock.lock();
- drawProgress(false);
- lock.unlock();
- }, 1, 200, TimeUnit.MILLISECONDS);
- }
-
- private void drawProgress(boolean last) {
- // paint a bar per host
- for (Progress progress : hosts) {
- drawBar(progress);
- }
-
- if (!last) {
- // move cursor up again
- System.out.print("\u001b[" + hosts.size() + "A");
- }
- }
-
- public void submit(Progress progress) {
- lock.lock();
- hosts.add(progress);
- lock.unlock();
- }
-
- private void drawBar(Progress progress) {
- System.out.print("\u001b[2K\r");
- System.out.println(createBar(
- progress.host(),
- progress.open().get(),
- progress.done().get(),
- progress.total()));
- }
-
- public String createBar(String label, int open, int done, int total) {
- int width = 30;
- double pct = total == 0 ? 1.0 : (done / (double) total);
- int filled = (int) (pct * width);
-
- String brackets = "[" + "#".repeat(filled) + "-".repeat(width - filled) + "]";
- int percent = (int) (pct * 100);
-
- return String.format("%-40s open=%s %s %3d%% (%d/%d)", label, open, brackets, percent, done, total);
- }
-
- public void stop() {
- ui.shutdown();
- try {
- ui.awaitTermination(10, TimeUnit.SECONDS);
- // we need to draw one last time for the 100% to appear
- drawProgress(true);
- } catch (InterruptedException ignored) {
- Thread.currentThread().interrupt();
- }
- }
-}
diff --git a/src/main/java/com/it_jaros/networkScanner/ScanOptions.java b/src/main/java/com/it_jaros/networkScanner/ScanOptions.java
deleted file mode 100644
index aee95a3..0000000
--- a/src/main/java/com/it_jaros/networkScanner/ScanOptions.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.it_jaros.networkScanner;
-
-import java.util.List;
-
-public record ScanOptions(List<String> targets, int openSocketLimit, int delayInMillis, int timeoutInMillis, int maxWorkersPerHost, String ports) {}
diff --git a/src/main/java/com/it_jaros/networkScanner/ScanResult.java b/src/main/java/com/it_jaros/networkScanner/ScanResult.java
deleted file mode 100644
index 48e4e58..0000000
--- a/src/main/java/com/it_jaros/networkScanner/ScanResult.java
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.it_jaros.networkScanner;
-
-import java.util.BitSet;
-
-public record ScanResult(String target, BitSet openPorts) {}
diff --git a/src/main/java/com/it_jaros/networkScanner/Scanner.java b/src/main/java/com/it_jaros/networkScanner/Scanner.java
deleted file mode 100644
index e3f90f1..0000000
--- a/src/main/java/com/it_jaros/networkScanner/Scanner.java
+++ /dev/null
@@ -1,148 +0,0 @@
-package com.it_jaros.networkScanner;
-
-import java.io.IOException;
-import java.net.InetSocketAddress;
-import java.net.Socket;
-import java.net.SocketException;
-import java.net.SocketTimeoutException;
-import java.util.ArrayList;
-import java.util.BitSet;
-import java.util.List;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.concurrent.locks.LockSupport;
-
-public class Scanner {
-
- private final Counter counter = new Counter();
- private final ProgressBar progressBar = new ProgressBar();
- private final Semaphore socketLimit;
- private final int timeoutInMillis;
- private final long delayInNanos;
- private final int maxWorkersPerHost;
-
- public Scanner(int socketLimit, int timeoutInMillis, int delayInMillis, int maxWorkersPerHost) {
- this.timeoutInMillis = timeoutInMillis;
- this.delayInNanos = TimeUnit.MILLISECONDS.toNanos(Math.max(0, delayInMillis));
- this.socketLimit = new Semaphore(socketLimit);
- this.maxWorkersPerHost = maxWorkersPerHost;
- }
-
- public List<ScanResult> scan(ScanOptions target) {
- return scanTargets(target.targets(), target.ports());
- }
-
- public List<ScanResult> scanTargets(List<String> targets, String ports) {
- List<ScanResult> results = new ArrayList<>();
- progressBar.start();
- try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
- List<Future<ScanResult>> futures = new ArrayList<>();
- for (String target : targets) {
- futures.add(executor.submit(() -> scanTarget(target, ports)));
- }
-
- futures.forEach((Future<ScanResult> f) -> {
- try {
- results.add(f.get());
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- } catch (ExecutionException e) {
- System.out.printf("%s -> %s%n", e.getClass().getSimpleName(), e.getMessage());
- }
- });
- }
-
- progressBar.stop();
- System.out.println("Peak concurrent connects: " + counter.max());
- return results;
- }
-
- private ScanResult scanTarget(String target, String ports) {
- PortRange portRange = new PortRange(ports);
- AtomicLong portSlotFactory = new AtomicLong(System.nanoTime());
- Semaphore maxWorkers = new Semaphore(maxWorkersPerHost);
- BitSet openPorts = new BitSet(PortRange.MAX_PORT);
-
- Progress progress = new Progress(target, portRange.getTotal(), new AtomicInteger(), new AtomicInteger());
- progressBar.submit(progress);
-
- try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) {
- List<Future<Integer>> futures = new ArrayList<>();
- while (portRange.hasNext()) {
- maxWorkers.acquireUninterruptibly();
- final int currentPort = portRange.next();
- futures.add(executor.submit(() -> {
- try {
- waitForSlot(portSlotFactory);
- int port = scanPort(target, currentPort);
- if (port != -1) {
- progress.open().incrementAndGet();
- }
- return port;
- } finally {
- maxWorkers.release();
- progress.done().incrementAndGet();
- }
- }));
- }
-
- List<Throwable> errors = new ArrayList<>();
- for (Future<Integer> f : futures) {
- try {
- int port = f.get();
- if (port != -1) {
- // openPorts is not threadsafe, so we do not update it outside the worker threads
- openPorts.set(port);
- }
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- } catch (ExecutionException e) {
- errors.add(e);
- }
- }
-
- if (!errors.isEmpty()) {
- System.out.printf("Errors happened during scan of target %s%nErrors:%s -> %s", target, errors.size(), errors);
- }
- }
-
- return new ScanResult(target, openPorts);
- }
-
- private int scanPort(String target, final int currentPort) {
- return isTargetPortOpen(target, currentPort) ? currentPort : -1;
- }
-
- private void waitForSlot(AtomicLong scanSlotFactory) {
- if (delayInNanos > 0) {
- long slot = scanSlotFactory.getAndAdd(delayInNanos);
- long wait = slot - System.nanoTime();
- if (wait > 0)
- LockSupport.parkNanos(wait);
- }
- }
-
- private boolean isTargetPortOpen(String target, int port) {
- socketLimit.acquireUninterruptibly();
- counter.inc();
- try (Socket socket = new Socket()) {
- socket.connect(new InetSocketAddress(target, port), timeoutInMillis);
- return true;
- } catch (SocketException | SocketTimeoutException ignored) {
- // Will happen a lot when scanning for open ports, so not needed
- } catch (IOException e) {
- System.out.printf("%s -> %s", e.getClass().getSimpleName(), e.getMessage());
- } finally {
- counter.dec();
- socketLimit.release();
- }
-
- return false;
- }
-}