> ## Documentation Index
> Fetch the complete documentation index at: https://docs.abusix.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Shared IPs behind carrier-grade NAT

> Set up Abusix Ops for networks where many customers share one public IP, such as CGNAT breakouts for FTTH, DSL or mobile access.

Many access networks use carrier-grade NAT (CGNAT). Customers get private IP addresses and share one public breakout IP. This page shows how to set up Abusix Ops so that reports about such a shared IP reach the customer who caused them, and where the limits are.

## 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.

CGNAT translates each customer's private IP to the shared public IP and a source port. Depending on your setup, each customer gets a fixed port range on the public IP, or ports are assigned dynamically per connection. Either way, the public IP alone doesn't tell you who sent the traffic. You need the **public IP, the source port and the time**, and a system that can look them up. In Abusix Ops, that system is your API, called through [API resolution](https://docs.abusix.com/docs/abusix-ops/customer-resolution.md).

> [!TIP]
>
> IPv6 removes the shared-IP problem at the source, because every customer gets their own addresses. CGNAT setups stay common, though, so the rest of this page assumes you keep CGNAT for now.

## How Abusix Ops handles reports

Abusix Ops handles every report in the same three steps:

1. **Parse.** Reports that reach Abusix Ops are parsed into [events](https://docs.abusix.com/docs/abusix-ops/reference/event-types.md), each with an event type such as Blocklist (`Blacklist`), `DNSBlocklist` or `Copyright`.
2. **Resolve.** Your [inbound processing](https://docs.abusix.com/docs/abusix-ops/inbound-processing.md) flow links each event to a customer ID through a resolver. See [Customer resolution](https://docs.abusix.com/docs/abusix-ops/customer-resolution.md).
3. **Group.** Case Group nodes in the flow group events into [cases](https://docs.abusix.com/docs/abusix-ops/cases.md). By default, Abusix Ops creates one case per customer and adds new events to the open case of that customer.

Cases can then run a [playbook](https://docs.abusix.com/docs/abusix-ops/playbooks.md) that automates the next steps or asks an agent for a decision.

## 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.

Abusix Ops does the matching and grouping, but it can't attribute reports without this data from your side.

## Recommended setup

### Step 1: Resolve customers through your API

> [!NOTE]
>
> We strongly recommend API resolution for CGNAT networks. It's the only way Abusix Ops can tell customers on a shared IP apart.

> [accordion] 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](https://www.rfc-editor.org/rfc/rfc4787) 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](https://www.rfc-editor.org/rfc/rfc7422).
>
> This is also why the timestamp in a report matters as much as the port. If the reporter's clock is off by a minute, the lookup can hit the wrong customer. [RFC 6302](https://www.rfc-editor.org/rfc/rfc6302) recommends that internet-facing servers log the source port and a timestamp accurate to the second from a reliable time source, such as NTP, for exactly this reason. Your API should match on IP, port and time together, and treat reports without a port as unattributable to a single customer.

Add an [API Caller](https://docs.abusix.com/docs/abusix-ops/node-reference.md#api-caller-node) node at the start of your inbound processing flow:

* 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.

Some reports may not contain a port. Decide what your API returns for those, for example an ID for the shared breakout IP itself, so they still end up together in one case.

See [API resolution](https://docs.abusix.com/docs/abusix-ops/customer-resolution.md) for the setup steps.

### 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:

1. A first API Caller node asks system A.
2. A [True/False](https://docs.abusix.com/docs/abusix-ops/node-reference.md#true-false-node) node checks the response captured on the event, for example whether a customer ID was returned.
3. If it wasn't, a second API Caller node asks system B. Add as many lookups as you have systems.

Each system only has to answer for the customers it knows. Abusix Ops asks them in order until one finds a match, so you can start resolving without first merging your data into one database.

> [!NOTE]
>
> 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

1. Add a True/False node after the resolution with the condition **event type equals Blocklist** (`Blacklist`). Add `DNSBlocklist` to the condition as well if you also receive DNS-based blocklist reports.
2. Connect the **true** path to a [Case Group](https://docs.abusix.com/docs/abusix-ops/node-reference.md#case-group-node) node with a new case group, for example **Blocklist**.
3. Save your draft and click **Activate**.

Each resolved customer gets one case in this group. The case shows every event for that customer, so you can see at a glance how many reports came in and from which reporters.

### Step 4: Track delisting with a playbook

Create a [playbook](https://docs.abusix.com/docs/abusix-ops/playbooks.md#creating-a-new-playbook) and attach it to the **Blocklist** case group. Add a [Manual](https://docs.abusix.com/docs/abusix-ops/node-reference.md#manual-node) node with decision paths that match your process, for example:

| Path | What happens next |
| - | - |
| **Delisted** | Connect a [Resolve](https://docs.abusix.com/docs/abusix-ops/node-reference.md#resolve-node) node to close the case as resolved |
| **Needs further investigation** | Connect the nodes your team uses to follow up, for example a [Mail Notification](https://docs.abusix.com/docs/abusix-ops/node-reference.md#mail-notification-node) to your network team |

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 on `Copyright` 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](https://docs.abusix.com/docs/abusix-ops/inbound-processing.md#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](https://docs.abusix.com/docs/abusix-ops/node-reference.md#static-resolver-node) 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.

> [!WARNING]
>
> IP resolution groups reports by shared IP, not by customer. It shows you how many reports each breakout IP gets and lets you track delisting, but it can't tell you which customer caused them. Plan to replace it with API resolution.

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.

## Recommendation: send all report sources to Abusix Ops

Reports that don't reach Abusix Ops can't be grouped into cases. If some sources, for example third-party feeds such as Shadowserver, arrive in a separate mailbox, forward that mailbox to your Abusix Ops forwarding address too, using aliases or server rules (forwarding from an email client is not supported). See [Getting started](https://docs.abusix.com/docs/abusix-ops/getting-started.md). Then check **Inbound Processing - Errors** to see which event types arrive and add branches for them.

## Related resources

* [Inbound Processing](https://docs.abusix.com/docs/abusix-ops/inbound-processing.md)
* [Customer resolution](https://docs.abusix.com/docs/abusix-ops/customer-resolution.md)
* [Cases](https://docs.abusix.com/docs/abusix-ops/cases.md)
* [Playbooks](https://docs.abusix.com/docs/abusix-ops/playbooks.md)
* [Node Reference](https://docs.abusix.com/docs/abusix-ops/node-reference.md)
* [Event Types Reference](https://docs.abusix.com/docs/abusix-ops/reference/event-types.md)


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.