Skip to content

subs -ip can prefer MX/NS/SRV-derived IPs over direct A/AAAA (and only prints one address) #1111

@je-bugshell

Description

@je-bugshell

amass subs -names -ip can surface MX/NS/SRV-derived IPs on the original name (and only prints one); request: prefer direct A/AAAA + optionally print both

Huge thanks to @caffix (Jeff Foley) and everyone who contributes to Amass — you all are absolute heroes. ❤️

Quick context: I’m not a Go developer. I’m using AI to help me read the code and validate what I’m seeing, and I’m doing my best to keep this report accurate and easy to act on. If I’m misunderstanding intended semantics, please correct me and I’ll happily adjust/close.


TL;DR

When you run amass subs with -names and -ip, the IP shown next to a name is not always that name’s own A/AAAA. In some cases it can come from traversing related DNS records (e.g., MX/NS/SRV) and then returning an A/AAAA from the target hostname instead.

This can produce output that looks like “this domain has AAAA = …”, but the address is actually from mail/DNS infrastructure.

Separately (but related), subs appears to short-circuit on the first match per name, so it prints only one address even if both A and AAAA exist.


Environment

  • Amass: v5.0.1
  • Command: amass subs -names -ip ...
  • Data source: asset-db graph populated by Amass

What I observed

Running:

amass subs -names -ip -d example.com

Sometimes yields an output line like:

example.com 2001:db8::3456

At a glance, that reads like “example.com has AAAA = 2001:db8::3456”.

But in the graph DB:

  • example.com has a direct A record to 1.2.3.4
  • the IPv6 2001:db8::3456 exists, but it’s attached to an MX target hostname (mail protection host), not directly to example.com

So the IPv6 is “real” in the graph — it’s just not the apex name’s AAAA.


DB evidence

Outgoing dns_record edges from example.com

The example.com FQDN has an outgoing dns_record edge with:

  • rr_type = 1 (A) → IPAddress { "type": "IPv4", "address": "1.2.3.4" }

It also has MX/NS edges to other FQDNs.

The IPv6 exists but is linked to MX targets

The IPv6 entity exists:

  • IPAddress { "type": "IPv6", "address": "2001:db8::3456" }

Back-links show it’s associated with the mail protection hostname via AAAA (rr_type = 28):

  • mx-gateway.example.netrr_type = 282001:db8::3456
  • mail-edge.example.netrr_type = 28...

Code path (why I think this happens)

amass/internal/subs/cli.go attaches IPs using:

  • amassnet.NamesToAddrs(db, qtime, names...)

In amass/internal/net/addr.go, NamesToAddrs:

  • walks outgoing edges labeled dns_record for each FQDN
  • inspects relation types + RR types
  • short-circuits on the first successful match (continue loop), effectively returning a single IP per name
  • for PrefDNSRelation with RRType 15 (MX) or 2 (NS), and SRVDNSRelation with RRType 33, it calls oneMoreName(...), which traverses the target FQDN and returns the target’s A/AAAA

So depending on edge ordering / which traversal succeeds first, the IP printed next to example.com can come from:

  • direct A/AAAA on example.com, or
  • an A/AAAA on an MX/NS/SRV target hostname

What I expected / what would be less surprising

1) Prefer the name’s direct A/AAAA deterministically

A behavior that would match typical user expectations:

  1. Prefer direct A/AAAA (RRType 1/28) on the name itself
  2. If none, try CNAME chain (RRType 5) and use the target’s A/AAAA
  3. If still none, fall back to MX/NS/SRV target traversal and use their A/AAAA

That would avoid cases where an apex name that has a direct A prints an unrelated MX-derived AAAA.

2) (Optional) print both A and AAAA when both exist

If the name has both A and AAAA, it’d be great if subs -ip could emit both on one line, e.g.:

example.com 1.2.3.4, 2001:db8::abcd

(Separator can match existing formatter behavior.)


Why this matters

  • The current output can be interpreted as “this name resolves to this IP”, when it can actually mean “this name has an MX/NS/SRV target that resolves to this IP”.
  • The “first match wins” behavior can make output feel inconsistent across runs / DB states.
  • Showing both A and AAAA (when present) is often what operators want when inventorying endpoints.

Notes / offer to help

Again, thank you @caffix for the project. Appreciate you taking a look.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions