The problem
Behind a CGNAT breakout, hundreds or thousands of customers reach the internet through the same public IP. When one of them is infected or acts maliciously:- The shared IP gets listed on blocklists, and every customer behind it is affected, not only the one causing the abuse.
- Abuse reports from other sources, for example copyright notices, also pile up on that same IP.
- Without a way to map the IP back to a customer, every report looks like it belongs to one and the same customer.
How Abusix Ops handles reports
Abusix Ops handles every report in the same three steps:- Parse. Reports that reach Abusix Ops are parsed into events, each with an event type such as Blocklist (
Blacklist),DNSBlocklistorCopyright. - Resolve. Your inbound processing flow links each event to a customer ID through a resolver. See Customer resolution.
- Group. Case Group nodes in the flow group events into cases. By default, Abusix Ops creates one case per customer and adds new events to the open case of that customer.
What your network needs
API resolution only works if your own systems can answer the question “who used this public IP and source port at this time?”. That means you need to:- Log your CGNAT translations. For every customer, record which public IP and source port (or port range) they used, and when. With dynamic port assignment, a customer gets a new source port for each new connection, so the log has to be detailed enough to match a single connection.
- Expose the lookup through an API. Abusix Ops calls it with the IP, port and timestamp from the event and expects a customer ID back.
Recommended setup
Step 1: Resolve customers through your API
We strongly recommend API resolution for CGNAT networks. It’s the only way Abusix Ops can tell customers on a shared IP apart.
Why only a time-based lookup works
Why only a time-based lookup works
Which customer uses a given public IP and port changes quickly, often within seconds or minutes. A fixed mapping, such as a static list of IPs and ports, can’t keep up. Only your own NAT logs, queried for the exact time of the event, can. The reasons:
- Every new connection can get a new source port. With dynamic allocation, the CGNAT picks a port per connection. When a customer’s connection closes, for example an HTTPS session to a web server, the next connection to the same server goes out on a different port, sometimes seconds later.
- Ports are reused by other customers. Once a mapping times out, the CGNAT frees the port and can hand it to the next customer who needs one. Idle timeouts are short for some protocols. For UDP, RFC 4787 allows mappings to expire after about two minutes. So the same IP and port can belong to different customers a few minutes apart.
- Port blocks are reassigned too. Many CGNATs hand out blocks of ports instead of single ports, which cuts logging volume. In dynamic port block allocation, a block is allocated when a customer starts sending traffic and released when they go idle, and then another customer can get it. Only a deterministic setup, where every customer has a fixed port range, keeps the mapping stable. See RFC 7422.
- Abusix Ops sends data from the event, such as the IP address, the event timestamp and the port, to your API. Behind CGNAT, send all three: your API needs the source port to tell customers on the same IP apart.
- Your API returns a customer ID. This can be your real customer ID or a pseudonymized ID if you don’t want to share customer identities with Abusix Ops. It can also return a contract ID, a tenant ID and other customer data.
Step 2: Chain API callers when your customer data is scattered
You don’t need a central IP-to-customer database to use API resolution. If the data lives in several systems, for example one NAT log per region, or separate systems for FTTH, DSL and mobile, chain one API Caller per system in your flow:- A first API Caller node asks system A.
- A True/False node checks the response captured on the event, for example whether a customer ID was returned.
- If it wasn’t, a second API Caller node asks system B. Add as many lookups as you have systems.
The True/False condition depends on what your API returns when it finds no match. Use the Test button on the API Caller node to see the response and build the condition on it. Events that still have no customer ID at the end of the chain show up as unresolved in Inbound Processing - Errors.
Step 3: Route blocklist events to their own case group
- Add a True/False node after the resolution with the condition event type equals Blocklist (
Blacklist). AddDNSBlocklistto the condition as well if you also receive DNS-based blocklist reports. - Connect the true path to a Case Group node with a new case group, for example Blocklist.
- Save your draft and click Activate.
Step 4: Track delisting with a playbook
Create a playbook and attach it to the Blocklist case group. Add a Manual node with decision paths that match your process, for example:
New blocklist cases then appear in the Decision needed tab of the cases list. Agents pick a path in the case detail view, and the case history records the decision.
Step 5: Add branches for other event types
Repeat step 3 on the false path for other high-volume event types, for example a True/False node onCopyright that routes to a Copyright case group with its own playbook. Events that match no branch end up in Inbound Processing - Errors, where you can see which event types to add next. See Unassigned events.
Fallback: resolve by IP
If your API isn’t ready yet, for example during a trial, you can start with a Static Resolver node that maps the event IP to the customer ID. Each public IP then becomes its own “customer”, so all reports about a shared breakout IP end up in one case. Steps 3 to 5 work the same way. When your API is ready, replace the Static Resolver with the API Caller chain from steps 1 and 2. The rest of the flow stays the same.Limits
- Attribution to a single customer needs port and time. Behind CGNAT, the IP alone doesn’t identify a customer. Abusix Ops can only attribute a report to one customer if the report contains the source port and timestamp, and your API can map IP, port and time to a customer.
- Some reports may not contain a source port. Whether a report has one depends on the reporter’s tooling. Some common log sources don’t record source ports, for example the default SSH daemon logs, and XARF recommends but doesn’t require them. Check the raw event of a few reports in a case to see whether your reporters include ports.
- The same customer shows up with many ports. One IP with different source ports can be many customers, and one customer can appear with a new port on every connection. Grouping by IP and port without a NAT log lookup doesn’t separate customers reliably.
- The Static Resolver can’t combine IP, port and time. It maps event fields to IDs as they are, so it can’t look up a customer from IP and port together, or at a point in time. For CGNAT attribution, use API resolution.
- Third-party delisting happens outside Abusix Ops. Abusix Ops doesn’t request delisting from blocklists run by other operators. Your team does that with each blocklist operator. Abusix Ops tracks the work as a case and records the decision through the Manual node.