Skip to content

Network Assets

This document describes the four network infrastructure asset types in the open-asset-model: FQDN, IPAddress, Netblock, and AutonomousSystem. These asset types represent the fundamental building blocks of network topology and addressing used in network reconnaissance and attack surface mapping. This page focuses on their structure, implementation, and network-specific relationships.

For information about registration records associated with network assets (DomainRecord, AutnumRecord, IPNetRecord), see 3.6. For details on the Asset interface these types implement, see 2.1. For the complete relationship validation system, see 4.

Network Asset Type Overview

The network domain defines four asset types that model Internet infrastructure:

Asset Type Purpose Key Format Primary Use Case
FQDN Fully Qualified Domain Name Domain name string DNS hierarchy, hostnames
IPAddress IP address (v4 or v6) IP address string Network endpoints, routing
Netblock IP address range in CIDR notation CIDR string (e.g., "192.168.1.0/24") IP allocation, ownership
AutonomousSystem AS number representing routing domain AS number as string BGP routing, ISP identification

Sources: , , ,

Asset Type: FQDN

The FQDN asset type represents fully qualified domain names in the DNS hierarchy. It is the most relationship-rich asset type in the network domain, supporting DNS record relationships, port-based service connections, hierarchical node relationships, and domain registration links.

FQDN Relationships

graph TB
    FQDN["FQDN"]

    subgraph "DNS Record Relationships"
        BasicDNS["BasicDNSRelation<br/>A, AAAA, CNAME, NS"]
        PrefDNS["PrefDNSRelation<br/>MX records"]
        SRV["SRVDNSRelation<br/>Service records"]
    end

    subgraph "Destination Types"
        FQDN2["FQDN<br/>(dns_record)"]
        IP["IPAddress<br/>(dns_record)"]
        Service["Service<br/>(port)"]
        DomainRec["DomainRecord<br/>(registration)"]
    end

    FQDN -->|"dns_record"| BasicDNS
    FQDN -->|"dns_record"| PrefDNS
    FQDN -->|"dns_record"| SRV
    FQDN -->|"port (PortRelation)"| Service
    FQDN -->|"node (SimpleRelation)"| FQDN2
    FQDN -->|"registration (SimpleRelation)"| DomainRec

    BasicDNS -.->|"resolves to"| FQDN2
    BasicDNS -.->|"resolves to"| IP
    PrefDNS -.->|"mail server"| FQDN2
    SRV -.->|"service target"| FQDN2

The fqdnRels map in defines four relationship labels for FQDN assets:

Label Relation Type(s) Destination Type(s) Purpose
dns_record BasicDNSRelation, PrefDNSRelation, SRVDNSRelation FQDN, IPAddress DNS resolution (A, AAAA, CNAME, NS, MX, SRV)
port PortRelation Service Services listening on the FQDN
node SimpleRelation FQDN DNS hierarchy (subdomains)
registration SimpleRelation DomainRecord WHOIS/RDAP registration data

Key Implementation Detail: The dns_record label supports three distinct RelationType values, each corresponding to different DNS record types. BasicDNSRelation handles standard records (A, AAAA, CNAME, NS), PrefDNSRelation adds preference/priority for MX records, and SRVDNSRelation includes priority, weight, and port for service records.

Sources:

Asset Type: IPAddress

The IPAddress asset type represents individual IPv4 or IPv6 addresses. It supports connections to services via ports and PTR record reverse DNS lookups.

IPAddress Relationships

graph LR
    IP["IPAddress"]

    Service["Service"]
    FQDN["FQDN"]

    IP -->|"port<br/>(PortRelation)"| Service
    IP -->|"ptr_record<br/>(SimpleRelation)"| FQDN

The ipRels map in defines two relationship labels:

Label Relation Type Destination Type Purpose
port PortRelation Service Services listening on the IP address
ptr_record SimpleRelation FQDN Reverse DNS (PTR) records

Contrast with FQDN: While FQDN assets support forward DNS relationships (dns_record) that can resolve to IP addresses, IPAddress assets support reverse DNS relationships (ptr_record) that point back to FQDNs. Both asset types share the port relationship for connecting to services.

Sources:

Asset Type: Netblock

The Netblock asset type represents CIDR-notated IP address ranges. It models IP address allocation and ownership, connecting address blocks to their constituent IP addresses and registration records.

Netblock Structure

// From network/netblock.go
type Netblock struct {
    CIDR netip.Prefix `json:"cidr"`
    Type string        `json:"type"`
}

The struct uses Go's netip.Prefix type for type-safe CIDR representation. The Type field distinguishes between "IPv4" and "IPv6" address blocks.

Sources:

Netblock Interface Implementation

graph TB
    Asset["Asset Interface<br/>(asset.go)"]
    Netblock["Netblock Struct<br/>(network/netblock.go)"]

    subgraph "Interface Methods"
        Key["Key() string<br/>Returns CIDR.String()"]
        AssetType["AssetType() AssetType<br/>Returns model.Netblock"]
        JSON["JSON() ([]byte, error)<br/>Marshals to JSON"]
    end

    Asset -.->|"implements"| Netblock
    Netblock -->|"line 29-31"| Key
    Netblock -->|"line 34-36"| AssetType
    Netblock -->|"line 39-41"| JSON

    Key -->|"returns"| CIDRString["nb.CIDR.String()"]

The Key() method at returns the CIDR notation as a string (e.g., "192.168.1.0/24"), which serves as the unique identifier for the asset. The AssetType() method at returns the model.Netblock constant. The JSON() method at uses standard json.Marshal() serialization.

Sources:

Netblock Relationships

graph TB
    Netblock["Netblock"]

    IPAddress["IPAddress"]
    IPNetRecord["IPNetRecord"]

    Netblock -->|"contains<br/>(SimpleRelation)"| IPAddress
    Netblock -->|"registration<br/>(SimpleRelation)"| IPNetRecord

The netblockRels map in defines two relationship labels:

Label Relation Type Destination Type Purpose
contains SimpleRelation IPAddress Individual IP addresses within the CIDR block
registration SimpleRelation IPNetRecord WHOIS/RDAP registration for the netblock

The contains relationship enables modeling the hierarchical relationship between address blocks and individual addresses, supporting queries like "which IP addresses are contained in this netblock?"

Sources:

Netblock JSON Serialization

Example JSON output from a Netblock instance:

{
  "cidr": "198.51.100.0/24",
  "type": "IPv4"
}

The test suite at verifies serialization for both IPv4 and IPv6 netblocks, ensuring the CIDR field serializes correctly using netip.Prefix's string representation.

Sources:

Asset Type: AutonomousSystem

The AutonomousSystem asset type represents an autonomous system number (ASN) used in BGP routing. It models the organizational units that control IP routing on the Internet, such as ISPs, cloud providers, and large enterprises.

AutonomousSystem Structure

// From network/autonomous_system.go
type AutonomousSystem struct {
    Number int `json:"number"`
}

The struct contains a single field: the AS number (e.g., 64496 for a private ASN, or 15169 for Google's public ASN).

Sources:

AutonomousSystem Interface Implementation

Method Implementation Line Reference
Key() Returns strconv.Itoa(a.Number)
AssetType() Returns model.AutonomousSystem
JSON() Returns json.Marshal(a)

The Key() method converts the integer AS number to a string for use as the asset's unique identifier. This ensures that ASN 64496 has the key "64496".

Sources:

AutonomousSystem Relationships

graph LR
    AS["AutonomousSystem"]

    Netblock["Netblock"]
    AutnumRecord["AutnumRecord"]

    AS -->|"announces<br/>(SimpleRelation)"| Netblock
    AS -->|"registration<br/>(SimpleRelation)"| AutnumRecord

The autonomousSystemRels map in defines two relationship labels:

Label Relation Type Destination Type Purpose
announces SimpleRelation Netblock IP address blocks announced by the AS via BGP
registration SimpleRelation AutnumRecord WHOIS/RDAP registration for the AS number

The announces relationship models BGP announcements, enabling queries like "which netblocks does AS 15169 announce?" This is critical for attack surface mapping, as it reveals the IP space controlled by an organization.

Sources:

AutonomousSystem JSON Serialization

Example JSON output:

{
  "number": 64496
}

The test at verifies this serialization format.

Sources:

Network Asset Relationship Graph

The following diagram shows how all four network asset types interconnect, including cross-domain relationships to registration records and services:

graph TB
    subgraph "Network Assets"
        FQDN["FQDN"]
        IP["IPAddress"]
        Netblock["Netblock"]
        AS["AutonomousSystem"]
    end

    subgraph "Registration Assets"
        DomainRec["DomainRecord"]
        IPNetRec["IPNetRecord"]
        AutnumRec["AutnumRecord"]
    end

    subgraph "Digital Assets"
        Service["Service"]
    end

    AS -->|"announces"| Netblock
    AS -->|"registration"| AutnumRec

    Netblock -->|"contains"| IP
    Netblock -->|"registration"| IPNetRec

    FQDN -->|"dns_record (Basic)"| IP
    FQDN -->|"dns_record (Basic/Pref/SRV)"| FQDN
    FQDN -->|"node"| FQDN
    FQDN -->|"port"| Service
    FQDN -->|"registration"| DomainRec

    IP -->|"ptr_record"| FQDN
    IP -->|"port"| Service

Key Observations:

  1. Hierarchical Structure: AutonomousSystemNetblockIPAddress forms a three-level hierarchy of network address space
  2. DNS Bidirectionality: FQDNs resolve to IP addresses (dns_record), while IP addresses reverse-resolve to FQDNs (ptr_record)
  3. Registration Linkage: All three network primitive types (AS, Netblock, FQDN) link to corresponding registration record types for ownership data
  4. Service Connectivity: Both FQDN and IPAddress assets connect to Service assets via PortRelation
  5. Self-Referential FQDN: FQDNs can reference other FQDNs through both dns_record (CNAME, NS, MX, SRV) and node (subdomain hierarchy) relationships

Sources: , , ,

Interface Compliance Testing Pattern

All network asset implementations follow a consistent testing pattern that verifies interface compliance at compile time:

// From network/netblock_test.go
var _ model.Asset = Netblock{}       // Value receiver
var _ model.Asset = (*Netblock)(nil) // Pointer receiver

// From network/autonomous_system_test.go
var _ model.Asset = AutonomousSystem{}       // Value receiver
var _ model.Asset = (*AutonomousSystem)(nil) // Pointer receiver

This pattern uses Go's blank identifier assignment to verify that both value and pointer receivers satisfy the Asset interface. If the type does not implement all required methods, this code will fail at compile time, preventing interface violations from reaching runtime.

The tests also verify method behavior: - Key() correctness: , - AssetType() returns correct constant: , - JSON() serialization format: ,

Sources: ,

Implementation Summary

All network asset types share common implementation patterns:

Pattern Implementation Detail Example
Struct Simplicity Minimal fields, focused on identity Netblock: 2 fields, AS: 1 field
Type-Safe Keys Leverage Go stdlib types for validation netip.Prefix for Netblock CIDR
String-Based Keys Key() returns string representation AS.Key() uses strconv.Itoa()
Standard JSON Use json.Marshal() without custom logic No custom MarshalJSON methods
Relationship Clarity Clear semantic labels in relation maps "announces", "contains", "ptr_record"

This consistency simplifies client code: all network assets can be handled polymorphically through the Asset interface, with type-specific behavior expressed through the relationship taxonomy rather than custom methods.

Sources: ,