EC2 Agents: CIDR vs FQDN (Wildcard) Allowlists — with Ansible & Rapid7 Examples + SG/NACL Capabilities

Executive Summary

CIDR allowlists control who (IPs) can talk to your instances, ideal for inbound automation traffic you own (Ansible control nodes, bastions, VPN egress).

FQDN / wildcard allowlists control where (domains) your instances/agents can call out to — essential for SaaS backends that sit behind CDNs/anycast (e.g., *.rapid7.com) whose IPs change.

Rule of thumb: Use Security Groups for precise, stateful, instance-level CIDR control (inbound + outbound). Use NACLs for coarse, subnet-level gates. Use a DNS-aware firewall/proxy (or AWS Network Firewall) for domain/wildcard egress control. SGs/NACLs cannot match hostnames.

Security Groups vs NACLs — What They Allow (and Don’t)

Feature Security Groups (SG) Network ACLs (NACL)
Type Stateful, attached to ENIs/instances Stateless, applied to subnets
Direction Inbound + Outbound; return traffic auto-allowed Inbound + Outbound; return traffic must be explicitly allowed
Matching By CIDR/IP or SG references (same VPC); no FQDN By CIDR/IP only; no FQDN, no SG refs
Evaluation Set-based, implicit deny if no match Numbered rules, first match wins
Granularity Fine-grained per-instance/role Coarse, per-subnet boundary
Logging No native decision logs (use VPC Flow Logs to observe traffic) No per-rule logs (use VPC Flow Logs)
What They’re Great At Microsegmentation, app tiers, restricting admin ports (SSH/WinRM) Global subnet allow/deny baselines (e.g., block known-bad CIDRs)
Limitations No FQDN/wildcards, no DPI/TLS intercept, no user-aware auth No FQDN/wildcards, stateless complexity, subnet-wide scope

Security Groups — You Can:

  • Restrict inbound SSH/WinRM to known CIDRs or referenced SGs.
  • Limit outbound by port and CIDR (e.g., only 80/443 to NAT).
  • Express tier-to-tier rules with SG references (web → app → db).

Security Groups — You Cannot:

  • Match FQDNs/wildcards (e.g., *.rapid7.com).
  • Do DPI, TLS inspection, or user/session-aware decisions.
  • Produce per-rule decision logs (observe via VPC Flow Logs instead).

NACLs — You Can:

  • Set coarse subnet boundaries (deny/allow by CIDR/port).
  • Block obvious inbound vectors at the subnet edge.
  • Use rule numbering for deterministic first-match behavior.

NACLs — You Cannot:

  • Match FQDNs/wildcards or reference SGs.
  • Rely on state; explicitly allow return traffic/ephemeral ports.
  • Target individual instances (NACLs affect the whole subnet).

When to Use CIDR vs FQDN (Wildcard)

CIDR/IP Allowlists — Use When

  • Controlling inbound admin access to EC2 (SSH/WinRM/RPC).
  • Your control plane has static egress (bastion, VPN, Ansible Tower).
  • You need deterministic peer-to-peer app tier microsegmentation.

FQDN/Wildcard Allowlists — Use When

  • Agents must call outbound to SaaS/CDN (dynamic IPs, anycast).
  • Vendor publishes hostnames and requires HTTPS/TLS without interception.
  • You need stable policy that survives provider IP rotation.

Example A — Ansible (Agentless)

Traffic Pattern

  • Linux targets: Ansible control node → EC2 over SSH 22/tcp.
  • Windows targets: control node → EC2 over WinRM 5986/tcp (TLS) (or SSH on supported builds).

What to Allow

  • Target EC2 Security Group (Inbound):
    • Allow 22/tcp from your control-node/bastion CIDR(s) (Linux).
    • Allow 5986/tcp from your control-node/bastion CIDR(s) (Windows).
  • Outbound on targets: allow to OS/package mirrors (or route via your internal repo/proxy).
  • Control node egress: optionally allow to Galaxy/PyPI or pin to internal mirrors.

Why CIDR Fits

Ansible is push-based and agentless. You own the control-plane IPs; the key is restricting inbound management ports on targets. No vendor SaaS domains are required for the automation channel itself.

Checklist (Opinionated)

  • [ ] Target SG: 22/tcp (Linux) from control-node CIDR(s) only.
  • [ ] Target SG: 5986/tcp (WinRM TLS) from control-node CIDR(s) only.
  • [ ] Prohibit 0.0.0.0/0 on management ports; prefer bastion + SG referencing.
  • [ ] Outbound to package mirrors (via NAT/proxy or internal repos).

Example B — Rapid7 Insight Agent (Agent-Based)

Traffic Pattern

  • EC2 → Rapid7 cloud over HTTPS 443 to region-specific hostnames (beaconing, telemetry, updates, uploads).
  • Optional Collector: EC2 → Collector on 5508, 6608, 8037; Collector → Rapid7 over 443.
  • Vendors commonly require no SSL interception (preserve certificate chain/TLS pinning).

What to Allow

  • Outbound (from EC2 or through your proxy/NAT): allow 443/tcp to documented Rapid7 endpoints for your region (often expressed as wildcards such as *.endpoint.ingress.rapid7.com, *.insight.rapid7.com).
  • If using Collector: allow EC2 → Collector ports 5508/6608/8037, and Collector egress 443 to Rapid7.

Why FQDN/Wildcard Fits

The Rapid7 backend is SaaS and frequently CDN/anycast fronted; IPs change. IP-based allowlists are brittle. Enforce hostname/wildcard egress on a DNS-aware proxy or AWS Network Firewall. SGs/NACLs can’t match FQDNs.

Checklist (Opinionated)

  • [ ] Outbound SG: permit 443/tcp to Internet via NAT/proxy.
  • [ ] Egress firewall/proxy policy: allow Rapid7 hostnames/wildcards; exclude from SSL inspection per vendor guidance.
  • [ ] If Collector: open 5508/6608/8037 to the Collector; allow Collector egress 443.

AWS-Native Controls — Putting It Together

For Ansible

  • Security Groups: precise inbound CIDR to 22 / 5986.
  • NACLs: optional subnet baseline (coarse allow/deny).
  • Egress: to repos/mirrors via NAT/proxy (optional domain control there).

For Rapid7 (and similar SaaS agents)

    <l