commit cedba0f485d95cca854ab1b3b83d020a4aa10181
parent a17a156f18e86a79572fee147f2237f6ef8202b2
Author: Matthias Jaros <jaros@mailbox.org>
Date: Thu, 2 Jul 2026 11:49:42 +0200
Added banner recognition parameter to enable it depending on use case
Diffstat:
4 files changed, 42 insertions(+), 34 deletions(-)
diff --git a/src/main/java/com/it_jaros/jscanner/CliDefaults.java b/src/main/java/com/it_jaros/jscanner/CliDefaults.java
@@ -2,6 +2,7 @@ package com.it_jaros.jscanner;
public class CliDefaults {
public static final String PORTS = "1-1024";
+ public static final boolean BANNER_RECOGNITION = false;
public static final boolean DISABLE_HOST_CHECK = false;
public static final boolean QUIET = false;
public static final boolean SHOW_FILTERED_PORTS = false;
diff --git a/src/main/java/com/it_jaros/jscanner/CliParser.java b/src/main/java/com/it_jaros/jscanner/CliParser.java
@@ -6,21 +6,22 @@ import java.util.Set;
public class CliParser {
public ScanOptions parseArgs(String[] args) {
- if (args.length < 1 || args[0].trim().equals("")) {
+ if (args.length < 1 || args[0].trim().isEmpty()) {
throw new IllegalArgumentException("No argument given");
}
Set<String> hostsArgv = new HashSet<>();
- int socketLimit = CliDefaults.SOCKET_LIMIT;
- int delayInMillis = CliDefaults.DELAY_IN_MILLIS;
- int timeoutInMillis = CliDefaults.TIMEOUT_IN_MILLIS;
- int maxWorkersPerHost = CliDefaults.MAX_WORKERS_PER_HOST;
- int maxHostsLimit = CliDefaults.MAX_HOSTS_LIMIT;
+ String hostsFile = null;
String ports = CliDefaults.PORTS;
- boolean showFilteredPorts = CliDefaults.SHOW_FILTERED_PORTS;
+ boolean bannerRecognition = CliDefaults.BANNER_RECOGNITION;
boolean disableOnlineCheck = CliDefaults.DISABLE_HOST_CHECK;
boolean quiet = CliDefaults.QUIET;
- String hostsFile = null;
+ boolean showFilteredPorts = CliDefaults.SHOW_FILTERED_PORTS;
+ int delayInMillis = CliDefaults.DELAY_IN_MILLIS;
+ int maxHostsLimit = CliDefaults.MAX_HOSTS_LIMIT;
+ int maxWorkersPerHost = CliDefaults.MAX_WORKERS_PER_HOST;
+ int socketLimit = CliDefaults.SOCKET_LIMIT;
+ int timeoutInMillis = CliDefaults.TIMEOUT_IN_MILLIS;
for (int i = 0; i < args.length; i++) {
final String currentArg = args[i];
@@ -30,49 +31,48 @@ public class CliParser {
}
switch (currentArg) {
- case "--help", "-h":
- usageAndExit();
- break;
- case "--socketLimit", "-sl":
- socketLimit = parseIntOption(args, ++i, currentArg);
+ case "--bannerRecognition", "-b":
+ bannerRecognition = true;
break;
case "--delay", "-d":
delayInMillis = parseIntOption(args, ++i, currentArg);
break;
- case "--timeout", "-t":
- timeoutInMillis = parseIntOption(args, ++i, currentArg);
+ case "--disableOnlineCheck", "-do":
+ disableOnlineCheck = true;
break;
- case "--maxWorkersPerHost", "-mh":
- maxWorkersPerHost = parseIntOption(args, ++i, currentArg);
+ case "--help", "-h":
+ usageAndExit();
+ break;
+ case "--input", "-i":
+ hostsFile = requireValue(args, ++i, currentArg);
break;
case "--maxHostsLimit", "-m":
maxHostsLimit = parseIntOption(args, ++i, currentArg);
break;
+ case "--maxWorkersPerHost", "-mh":
+ maxWorkersPerHost = parseIntOption(args, ++i, currentArg);
+ break;
case "--ports", "-p":
ports = requireValue(args, ++i, currentArg);
break;
+ case "--quiet", "-q":
+ quiet = true;
+ break;
case "--showFilteredPorts", "-sf":
showFilteredPorts = true;
break;
- case "--disableOnlineCheck", "-do":
- disableOnlineCheck = true;
- break;
- case "--input", "-i":
- hostsFile = requireValue(args, ++i, currentArg);
+ case "--socketLimit", "-sl":
+ socketLimit = parseIntOption(args, ++i, currentArg);
break;
- case "--quiet", "-q":
- quiet = true;
+ case "--timeout", "-t":
+ timeoutInMillis = parseIntOption(args, ++i, currentArg);
break;
default:
throw new IllegalArgumentException("No such param " + currentArg);
}
}
- System.out.printf(
- "Parsed arguments: hostsArgv('%s'), ports(%s), socketLimit(%s), delayInMillis(%s), timeoutInMillis(%s), maxWorkersPerHost(%s), maxHostsLimit(%s), showFilteredPorts(%s), disableOnlineCheck(%s), file(%s), quiet(%b) %n",
- hostsArgv, ports, socketLimit, delayInMillis, timeoutInMillis, maxWorkersPerHost, maxHostsLimit, showFilteredPorts, disableOnlineCheck, hostsFile, quiet);
-
- return new ScanOptions(hostsArgv.stream().toList(), socketLimit, delayInMillis, timeoutInMillis, maxWorkersPerHost, maxHostsLimit, ports, showFilteredPorts, disableOnlineCheck, hostsFile, quiet);
+ return new ScanOptions(hostsArgv.stream().toList(), socketLimit, delayInMillis, timeoutInMillis, maxWorkersPerHost, maxHostsLimit, ports, showFilteredPorts, disableOnlineCheck, hostsFile, quiet, bannerRecognition);
}
private String requireValue(String[] args, int index, String option) {
@@ -100,6 +100,7 @@ public class CliParser {
Options:
""");
usage.append("""
+ --bannerRecognition, -b:\tEnable banner recognition to find out which service is running behind port (Default :%b)
--delay, -d:\t\tWaiting period in millis for connection attempts for a host (Default: %d)
--disableOnlineCheck, -do:\tDon't check if Host is reachable (Default: %b)
--input, -i:\t\tRead file to get host targets to scan (Default: null)
@@ -110,7 +111,7 @@ public class CliParser {
--showFilteredPorts, -sf:\tShow also filtered ports (Default: %b)
--socketLimit, -sl:\t\tSocket limit in total. You can not scan more ports than allowed here (Default: %d)
--timeout, -t:\t\tTimeout in millis per connection attempt, 0 means infinite (Default: %d)
- """.formatted(CliDefaults.DELAY_IN_MILLIS, CliDefaults.DISABLE_HOST_CHECK, CliDefaults.MAX_HOSTS_LIMIT, CliDefaults.MAX_WORKERS_PER_HOST, CliDefaults.PORTS, CliDefaults.QUIET, CliDefaults.SHOW_FILTERED_PORTS, CliDefaults.SOCKET_LIMIT, CliDefaults.TIMEOUT_IN_MILLIS)
+ """.formatted(CliDefaults.BANNER_RECOGNITION, CliDefaults.DELAY_IN_MILLIS, CliDefaults.DISABLE_HOST_CHECK, CliDefaults.MAX_HOSTS_LIMIT, CliDefaults.MAX_WORKERS_PER_HOST, CliDefaults.PORTS, CliDefaults.QUIET, CliDefaults.SHOW_FILTERED_PORTS, CliDefaults.SOCKET_LIMIT, CliDefaults.TIMEOUT_IN_MILLIS)
);
usage.append("""
diff --git a/src/main/java/com/it_jaros/jscanner/ScanOptions.java b/src/main/java/com/it_jaros/jscanner/ScanOptions.java
@@ -2,4 +2,4 @@ package com.it_jaros.jscanner;
import java.util.List;
-public record ScanOptions(List<String> hostsArgv, int openSocketLimit, int delayInMillis, int timeoutInMillis, int maxWorkersPerHost, int maxHostsLimit, String ports, boolean showFilteredPorts, boolean disableHostCheck, String hostsFile, boolean quiet) {}
+public record ScanOptions(List<String> hostsArgv, int openSocketLimit, int delayInMillis, int timeoutInMillis, int maxWorkersPerHost, int maxHostsLimit, String ports, boolean showFilteredPorts, boolean disableHostCheck, String hostsFile, boolean quiet, boolean bannerRecognition) {}
diff --git a/src/main/java/com/it_jaros/jscanner/Scanner.java b/src/main/java/com/it_jaros/jscanner/Scanner.java
@@ -24,6 +24,7 @@ public class Scanner implements AutoCloseable {
private volatile boolean cancelled = false;
private final Semaphore socketLimit;
+ private final boolean bannerRecognition;
private final boolean disableOnlineCheck;
private final boolean quiet;
private final int maxHostsLimit;
@@ -38,9 +39,11 @@ public class Scanner implements AutoCloseable {
int maxWorkersPerHost,
int maxHostsLimit,
boolean disableOnlineCheck,
- boolean quiet
+ boolean quiet,
+ boolean bannerRecognition
) {
this.delayInNanos = TimeUnit.MILLISECONDS.toNanos(Math.max(0, delayInMillis));
+ this.bannerRecognition = bannerRecognition;
this.disableOnlineCheck = disableOnlineCheck;
this.maxHostsLimit = maxHostsLimit;
this.maxWorkersPerHost = maxWorkersPerHost;
@@ -50,7 +53,7 @@ public class Scanner implements AutoCloseable {
}
public Scanner(ScanOptions options) {
- this(options.openSocketLimit(), options.timeoutInMillis(), options.delayInMillis(), options.maxWorkersPerHost(), options.maxHostsLimit(), options.disableHostCheck(), options.quiet());
+ this(options.openSocketLimit(), options.timeoutInMillis(), options.delayInMillis(), options.maxWorkersPerHost(), options.maxHostsLimit(), options.disableHostCheck(), options.quiet(), options.bannerRecognition());
}
public List<ScanResult> scan(ScanOptions options) {
@@ -228,7 +231,10 @@ public class Scanner implements AutoCloseable {
scanState.counter().inc();
try (Socket socket = new Socket()) {
socket.connect(new InetSocketAddress(host, port), timeoutInMillis);
- result.setBanner(getBanner(socket));
+
+ if (bannerRecognition) {
+ result.setBanner(getBanner(socket));
+ }
result.setState(PortState.OPEN);
} catch (SocketTimeoutException ignored) {
result.setState(PortState.FILTERED);