1 Library Usage
nsportsman edited this page 2026-01-29 20:12:34 -06:00

Library Usage

Using Nerva as a Go library in your applications.

Installation

go get github.com/praetorian-inc/nerva

Basic Example

package main

import (
    "fmt"
    "log"
    "net/netip"
    "time"

    "github.com/praetorian-inc/nerva/pkg/plugins"
    "github.com/praetorian-inc/nerva/pkg/scan"
)

func main() {
    // Configure scan
    config := scan.Config{
        DefaultTimeout: 2 * time.Second,
        FastMode:       false,
        UDP:            false,
        SCTP:           false,
    }

    // Create target
    ip, _ := netip.ParseAddr("93.184.216.34")
    target := plugins.Target{
        Address: netip.AddrPortFrom(ip, 22),
        Host:    "example.com",
    }

    // Run scan
    results, err := scan.ScanTargets([]plugins.Target{target}, config)
    if err != nil {
        log.Fatal(err)
    }

    // Process results
    for _, result := range results {
        fmt.Printf("%s:%d - %s (%s)\n",
            result.Host, result.Port,
            result.Protocol, result.Transport)
    }
}

Configuration Options

type Config struct {
    DefaultTimeout time.Duration  // Connection timeout (default: 2s)
    FastMode       bool           // Only check default ports
    Verbose        bool           // Enable debug logging
    UDP            bool           // Enable UDP plugins
    SCTP           bool           // Enable SCTP plugins (Linux only)
}

Service Result Structure

type Service struct {
    Host      string          `json:"host,omitempty"`
    IP        string          `json:"ip"`
    Port      int             `json:"port"`
    Protocol  string          `json:"protocol"`   // "ssh", "http", etc.
    TLS       bool            `json:"tls"`
    Transport string          `json:"transport"`  // "TCP", "UDP", "SCTP"
    Version   string          `json:"version,omitempty"`
    Raw       json.RawMessage `json:"metadata"`   // Protocol-specific
}

Protocol-Specific Metadata

Each protocol returns typed metadata:

SSH Metadata

type ServiceSSH struct {
    Banner          string   `json:"banner"`
    PasswordAuthOk  bool     `json:"passwordAuthOk"`
    Algorithms      []string `json:"algorithms"`
    HostKey         string   `json:"hostKey"`
}

HTTP Metadata

type ServiceHTTP struct {
    Status      string              `json:"status"`
    StatusCode  int                 `json:"statusCode"`
    Headers     map[string][]string `json:"responseHeaders"`
    Version     string              `json:"version"`
    Technologies []string           `json:"technologies"`
}

Scanning Multiple Targets

targets := []plugins.Target{
    {Address: netip.MustParseAddrPort("10.0.0.1:22"), Host: "server1"},
    {Address: netip.MustParseAddrPort("10.0.0.2:80"), Host: "server2"},
    {Address: netip.MustParseAddrPort("10.0.0.3:443"), Host: "server3"},
}

results, err := scan.ScanTargets(targets, config)

Error Handling

results, err := scan.ScanTargets(targets, config)
if err != nil {
    // Handle scan-level error
    log.Fatal(err)
}

for _, result := range results {
    if result.Protocol == "" {
        // No service detected on this target
        continue
    }
    // Process successful detection
}

See Also