diff options
Diffstat (limited to 'src/main/java/com')
4 files changed, 153 insertions, 0 deletions
diff --git a/src/main/java/com/it_jaros/networkScanner/App.java b/src/main/java/com/it_jaros/networkScanner/App.java new file mode 100644 index 0000000..5d52065 --- /dev/null +++ b/src/main/java/com/it_jaros/networkScanner/App.java @@ -0,0 +1,41 @@ +package com.it_jaros.networkScanner; + +import java.util.List; + +public class App { + public static void main(String[] args) { + Scanner scanner = new Scanner(); + if (args.length < 1 || args[0] == "") { + usageAndExit(); + } + String target = args[0]; + System.out.printf( + "Scanning host=%s \n", + target); + + try (FdCounter fd = new FdCounter()) { + fd.start(20); // sample every 20ms + List<Integer> openPorts = scanner.scanPorts(target, 10000); + printPorts(target, openPorts); + System.out.println("FD limit: " + fd.maxFds()); + System.out.println("Peak open FDs during scan: " + fd.peakOpenFds()); + } + } + + public static void printPorts(String address, List<Integer> openPorts) { + System.out.println("Address:" + address); + openPorts.forEach((p) -> System.out.println("Open port: " + p)); + } + + private static void usageAndExit() { + System.err.println(""" + Usage: + java -jar scanner.jar <host> + + 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 new file mode 100644 index 0000000..a4baec0 --- /dev/null +++ b/src/main/java/com/it_jaros/networkScanner/Counter.java @@ -0,0 +1,25 @@ +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/FdCounter.java b/src/main/java/com/it_jaros/networkScanner/FdCounter.java new file mode 100644 index 0000000..05eb9a4 --- /dev/null +++ b/src/main/java/com/it_jaros/networkScanner/FdCounter.java @@ -0,0 +1,37 @@ +package com.it_jaros.networkScanner; + +import java.lang.management.ManagementFactory; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicLong; + +import com.sun.management.UnixOperatingSystemMXBean; + +public final class FdCounter implements AutoCloseable { + private final UnixOperatingSystemMXBean os = + (UnixOperatingSystemMXBean) ManagementFactory.getOperatingSystemMXBean(); + private final ScheduledExecutorService ses = + Executors.newSingleThreadScheduledExecutor(Thread.ofPlatform().daemon().factory()); + private final AtomicLong peak = new AtomicLong(0); + + public void start(long everyMillis) { + ses.scheduleAtFixedRate(() -> { + long now = os.getOpenFileDescriptorCount(); + peak.accumulateAndGet(now, Math::max); + }, 0, everyMillis, TimeUnit.MILLISECONDS); + } + + public long peakOpenFds() { + return peak.get(); + } + + public long maxFds() { + return os.getMaxFileDescriptorCount(); + } + + @Override public void close() { + ses.shutdownNow(); + } +} + diff --git a/src/main/java/com/it_jaros/networkScanner/Scanner.java b/src/main/java/com/it_jaros/networkScanner/Scanner.java new file mode 100644 index 0000000..1f71f56 --- /dev/null +++ b/src/main/java/com/it_jaros/networkScanner/Scanner.java @@ -0,0 +1,50 @@ +package com.it_jaros.networkScanner; + +import java.io.IOException; +import java.net.ConnectException; +import java.net.InetSocketAddress; +import java.net.Socket; +import java.util.List; +import java.util.Queue; +import java.util.concurrent.ConcurrentLinkedQueue; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Semaphore; + +public class Scanner { + + private Counter counter = new Counter(); + private final int socketLimitDefault = 1024; + + public Scanner() {} + + public List<Integer> scanPorts(String address) { + return scanPorts(address, socketLimitDefault); + } + + public List<Integer> scanPorts(String address, int socketLimit) { + Queue<Integer> openPorts = new ConcurrentLinkedQueue<>(); + Semaphore socketCap = new Semaphore(socketLimit); + try (ExecutorService executor = Executors.newVirtualThreadPerTaskExecutor()) { + for (int port = 1; port < 65536; port++) { + final int currentPort = port; + executor.submit(() -> { + socketCap.acquireUninterruptibly(); + counter.inc(); + try (Socket socket = new Socket()) { + socket.connect(new InetSocketAddress(address, currentPort)); + openPorts.add(currentPort); + } catch (ConnectException ignored) { + } catch (IOException e) { + System.out.println(e.getClass().getSimpleName() + ": " + e.getMessage()); + } finally { + counter.dec(); + socketCap.release(); + } + }); + } + } + System.out.println("Peak concurrent connects: " + counter.max()); + return openPorts.stream().toList(); + } +} |
