Using nmap4j in Java to Scan Ports and Identify Services

This guide explains how to integrate the nmap4j library into Java projects to perform Nmap‑based port scanning, service detection, and OS identification, covering prerequisite setup, key command‑line flags, Windows and Linux implementations, and parsing XML results with Dom4j.

Java Architect Handbook
Java Architect Handbook
Java Architect Handbook
Using nmap4j in Java to Scan Ports and Identify Services

Background

When a requirement arises to discover the service name and version of a host (e.g., a database) based on its IP and port, Nmap is the typical tool. Java does not provide native bindings, so the nmap4j wrapper library is used to invoke Nmap from Java code.

Prerequisites

Install Nmap (recommended version 7.95). Download from https://nmap.org/download.html.

Obtain the nmap4j JAR (not available in Maven Central) from https://github.com/narkisr/nmap4j or the release zip https://master.dl.sourceforge.net/project/nmap4j/1.1.0/org.nmap4j-1.1.0-RELEASE.zip and add it to the project classpath.

Key Nmap Flags Used

-iL

: read targets from a file. -iR <num>: randomly select a number of hosts. --exclude <hosts>: exclude specific hosts or networks. -sS: TCP SYN (stealth) scan. -sT: TCP connect scan. -sU: UDP scan. -sV: enable service version detection. -O: enable OS detection. -p <ports>: specify ports or ranges. --top-ports <num>: scan the most common ports. -oX: output results as XML (required for parsing). -v, -vv, -vvv: increase verbosity.

Windows Implementation

/**
 * Scan a host using nmap4j.
 * @param ip   Target IP address
 * @param ports List of target ports
 * @return List of NmapPortInfo containing service name and version
 */
@RequestMapping("/querydb")
public List<NmapPortInfo> querydb(@RequestParam("ip") String ip,
                                 @RequestParam("ports") List<String> ports) {
    ArrayList<NmapPortInfo> portInfos = new ArrayList<>();
    String portStr = StrUtil.join(",", ports);
    String path = "D:/StudyApps/nmap"; // Nmap installation directory
    String fileName = "temp_result.xml";

    Nmap4j nmap4j = new Nmap4j(path);
    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        nmap4j.addFlags("-sV -p " + portStr + " -T5 -O -oX " + fileName);
        nmap4j.includeHosts(ip);
        try { nmap4j.execute(); } catch (Exception e) { throw new RuntimeException(e); }
    }, threadPoolExecutor);
    future.join();
    return getPortInfo(portInfos, fileName);
}

private List<NmapPortInfo> getPortInfo(List<NmapPortInfo> portInfos, String fileName) {
    String projectPath = System.getProperty("user.dir");
    String filePath = projectPath + FileUtil.FILE_SEPARATOR + fileName;
    SAXReader reader = new SAXReader();
    org.dom4j.Document doc = reader.read(FileUtil.file(filePath));
    org.dom4j.Element host = doc.getRootElement().element("host");
    List<org.dom4j.Element> ports = host.element("ports").elements("port");
    for (org.dom4j.Element p : ports) {
        org.dom4j.Element service = p.element("service");
        String product = service.attributeValue("product");
        String version = service.attributeValue("version");
        portInfos.add(new NmapPortInfo(product, version));
    }
    FileUtil.del(filePath);
    return portInfos;
}

Linux Implementation

/**
 * Scan a host on Linux using the native nmap command.
 */
@GetMapping("/linux/querydb")
@SneakyThrows
public List<NmapPortInfo> linuxQuerydb(@RequestParam("ip") String ip,
                                      @RequestParam("ports") List<String> ports) {
    ArrayList<NmapPortInfo> portInfos = new ArrayList<>();
    String portStr = StrUtil.join(",", ports);
    String fileName = "temp_result.xml";
    String nmapCommand = "nmap -sV -p " + portStr + " -T5 -O -oX " + fileName + " " + ip;

    CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
        try {
            Process proc = Runtime.getRuntime().exec(nmapCommand);
            proc.waitFor();
        } catch (Exception e) { throw new RuntimeException(e); }
    }, threadPoolExecutor);
    future.join();
    return getPortInfo(portInfos, fileName);
}

Parsing the XML Result

Both implementations rely on Dom4j to read the XML file generated by the -oX flag. The parser extracts the product and version attributes from each service element and wraps them in a simple POJO NmapPortInfo.

Important Notes

The nmap4j JAR must be added manually because it is not hosted on Maven Central.

Use Nmap version 7.95; other versions may produce XML that Dom4j cannot parse.

When running on Linux, ensure the nmap executable is available in the system PATH.

References

Project source: https://github.com/maoshengyzx/SpringBoot

nmap4j repository: https://github.com/narkisr/nmap4j

Javanetwork securityPort scanningnmap4jservice detection
Java Architect Handbook
Written by

Java Architect Handbook

Focused on Java interview questions and practical article sharing, covering algorithms, databases, Spring Boot, microservices, high concurrency, JVM, Docker containers, and ELK-related knowledge. Looking forward to progressing together with you.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.