Exclusive Access · Invitation Only

Gateway NAT & Internet Access

A node connects your private fabric to the public internet. Tenant workloads sit on a private subnet whose addresses are not routable on the internet, while the node holds an uplink with a public IP. NAT rewrites addresses as traffic crosses that boundary, so a whole tenant subnet can reach the internet over one shared public IP and so you can publish internal services on it.

Translation happens in the packet path, in the same pass as the firewall and routing decisions, so nothing is proxied and no extra hop is added. Throughput depends on your traffic profile and hardware — measure it for your workload rather than assuming a figure.

NAT is opt-in. With no rules in place, source NAT is off and the data path is unchanged, so you enable internet access one subnet at a time.

Which nodes can do this

All of them. There is one kind of node: every node hosts workloads, and every node can sit at the edge, translate addresses and exchange routes with your upstream routers.

Earlier versions asked you to pick Compute or Gateway when the node was installed, and the choice could not be changed afterwards. That is gone — see Nodes. Nodes running an older version are migrated on update with nothing for you to do.

What still varies is your topology, not the software: a node needs an uplink to the outside world before it can be an edge for anything, and NAT is opt-in per subnet either way.

The two directions

Everything on this page is one of two movements, and they use different rules.

Outbound — many workloads, one public address. A workload opens a connection to the internet. The node replaces the workload's private source address with its own public one, remembers the conversation, and puts the original address back on the replies. The internet sees only your public address. This is masquerade, below.

Inbound — one public port, one internal service. Something on the internet connects to your public address on a chosen port, and the node sends it to a specific workload. This is a port forward, and it is the only way traffic starts from outside; masquerade alone does not let anyone in.

outbound   workload ─► node (source becomes public) ─► internet
inbound    internet ─► node (destination becomes the workload) ─► workload

They are independent. A subnet with masquerade can reach out without publishing anything, and a published service works whether or not that subnet also has masquerade.

Where the firewall fits

NAT decides where a packet goes; the firewall decides whether it may. Both apply — publishing a service does not exempt it from firewall policy, so an inbound port forward still needs a rule permitting the traffic if your default action is deny. Plan the two together: a forward with no matching allow rule is a service that appears configured and answers nothing.

Publishing a service (inbound)

A port forward maps one public address and port to **one workload address and port**. It is available through the API:

curl -k -X POST "$NODE/api/v1/forward" \
  -H "Authorization: Bearer $TOKEN" -H "Content-Type: application/json" \
  -d '{"dest_ip":"203.0.113.10","dest_port":443,"target_ip":"10.20.0.50","target_port":8443}'

dest_ip and dest_port are what the outside world connects to; target_ip and target_port are the workload that should receive it. The ports do not have to match — publishing 443 to an application listening on 8443 is normal.

List, read and remove them the same way:

curl -k "$NODE/api/v1/forward" -H "Authorization: Bearer $TOKEN"          # {"port_forwards":[ ... ]}
curl -k "$NODE/api/v1/forward/<id>" -H "Authorization: Bearer $TOKEN"     # {"port_forward":{ ... }}
curl -k -X DELETE "$NODE/api/v1/forward/<id>" -H "Authorization: Bearer $TOKEN"

The list shows only port forwards, each with the same four fields plus its id. Masquerade rules live in gateway snat list, below, which shows both kinds.

One public port goes to one target. To publish several services, add a forward for each, using a different public port or a different public address.

Masquerade (shared public IP)

Masquerade (source NAT) lets an entire private LAN subnet reach the internet through a single public IP. When a tenant on the subnet opens an outbound connection, the node rewrites the packet's source address to the WAN interface's IP and tracks the flow; replies arriving at that public IP are translated back to the original tenant. TCP, UDP, and ICMP echo (ping) are all masqueraded.

Add a rule by giving the LAN subnet as a CIDR and the WAN egress interface:

sudo cenvero-str-ctl gateway snat add 10.50.0.0/24 --wan cnv-nic-0

The public IP is taken from the WAN interface itself, so you name the interface rather than an address. The response confirms the stored rule:

{
  "status": "added",
  "id": 1,
  "type": "snat",
  "source_cidr": "10.50.0.0/24",
  "interface": "cnv-nic-0"
}

List the NAT rules in place — this shows both masquerade rules and any published port-forwards:

cenvero-str-ctl gateway snat list
{
  "nat_rules": [
    {
      "id": 1,
      "type": "snat",
      "source_ip": "10.50.0.0/24",
      "interface": "cnv-nic-0"
    }
  ]
}

Remove a rule by its id:

sudo cenvero-str-ctl gateway snat remove 1

With no masquerade rule, outbound traffic from a private network is not translated — and it does not leave: the node drops it on the uplink (see below). Add one rule per LAN subnet you want to give internet access — or create the network with --host-gateway --snat, which adds the rule for you (out the configured uplink), keeps it in place and removes it with the network; see The host gateway.

Private addresses never leave untranslated

A packet from one of your networks whose range is private (10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16, or the shared 100.64.0.0/10) is dropped when it would leave on the uplink still carrying that private source address — that is, when no masquerade rule translated it. The internet could not answer it anyway, and providers treat private source addresses leaving a server as abuse, up to locking the server. It applies to every network on the node, whoever owns it.

  • The uplink is the interface named in gateway_wan_interface, or, when none is set, the interface of the node's default route — on a node the installer set up, the management bridge. Traffic is checked on the network card it finally leaves through: the uplink itself when it is a card the node manages (cnv-nic-…), or the managed cards under it when the uplink is a bridge (the management bridge and its card) or a bond of them.
  • The agent log says which uplinks are checked and on which interfaces, when the agent starts and whenever that changes. It warns, by name, about an uplink that is not checked: one that is not a card the node manages, nor a bridge or bond of them, and a gateway_wan_interface that names an interface this node does not have (correct the setting, or clear it to use the default route). On such an uplink, or if your uplink is a VLAN interface, do not rely on the check: give every private network that needs the internet a masquerade rule.
  • A network that contains the node's own address on its uplink — a management network that overlaps one of your networks, say — is not checked, because checking it would cut the node's own traffic off. The agent log warns about it with the address; change the network's range, or give it a masquerade rule.
  • Translated traffic leaves with the uplink's public address and is not affected, and neither is a network whose range is public (a block your provider routes to you), a public address a virtual machine holds, or the node's own traffic.
  • Traffic between your networks, and to the node, stays inside the node and is not affected.
  • A VLAN interface on top of the uplink's network card — a provider's private VLAN, for instance — is a network of its own: traffic the node sends into it is not affected, whatever its source address.

If your provider routes private ranges to an upstream NAT router of its own — so private source addresses are expected to leave the server — switch the check off, then restart the agent:

sudo cenvero-str-ctl config set allow_untranslated_private_egress true
sudo systemctl restart cenvero-stratum

Set it back to false to drop such traffic again.

Public addresses are never translated. A virtual machine holding one of the public addresses your provider routes to you (see Public Addresses) sends from that address unchanged — even if a masquerade rule's subnet happens to include it.

When a connection cannot be translated

Each new outbound connection needs a free source port on the public address toward its destination. In the rare case that every candidate port toward one destination is already in use, the node drops the new connection's packet rather than sending it out with the workload's private address — the client simply retries. Established connections are unaffected.

Ping works the same way. Two workloads pinging the same outside host with the same ICMP identifier would collide on one translation, so the second one's request is dropped rather than letting its replies be delivered to the first. Pinging tools pick a fresh identifier per run, so this is seen only when two clients happen to pick the same one at the same time.

Hairpin NAT (reaching your own public IP)

Hairpin NAT (also called NAT loopback) handles the case where a tenant on the LAN reaches one of your own published services by its public address. Suppose you publish an internal service on the node's public IP, and a client on the same LAN connects to that public IP instead of the internal address. Without hairpin, the server's reply would return straight to the client without passing back through the node, and the connection would break.

With hairpin, the node rewrites both ends of the forward packet: the destination is translated to the internal host (as with any published service), and the source is translated to the node's own LAN address. The reply then comes back to the node, which reverses both translations, so the client sees a consistent, working conversation.

Hairpin is automatic — there is no separate command. For IPv4 it engages when:

  • a masquerade rule covers the LAN subnet (this is what tells the node its own address on that subnet), and
  • the client and the published service's target host are both on that subnet.

If there is no masquerade rule for the subnet, a published service still works normally from outside; only the same-subnet loopback case relies on hairpin. Hairpin NAT is IPv4 only. See the API reference for publishing a service with a port-forward rule.

Two workloads on the same node stay on that node

This is the case worth knowing about if you host several customers on one server.

One workload calls another's public address — a VPS calling an API next door, say. Both addresses are on your node. That traffic is turned around **inside the node**. It does not go out to your provider's router and come back.

What that buys you:

Latencya local hop instead of a round trip off the box
Your uplinkuntouched, so it stays free for traffic that genuinely leaves
Provider bandwidthnot consumed — the packets never reach the provider

It is still fully accounted. Usage is measured in the packet path, not at the uplink, so both workloads are metered exactly as they would be for external traffic. Bandwidth limits, shared pools, monthly quotas and the node's licensed speed ceiling all apply to it. Keeping traffic local speeds it up; it does not make it invisible or free.

This is not a mode you turn on — it is what happens when both addresses are on the same node.

Private addresses behave differently, on purpose. Traffic between the private networks of two different tenants is refused, because private addresses are not reachable from outside and blocking them is real separation. Public addresses are reachable from the internet by definition, so refusing the local shortcut between two of them would not separate anything — it would only make the same conversation slower.

NAT64 (IPv6-only clients)

NAT64 lets an IPv6-only tenant reach an IPv4-only service on the internet. The client sends traffic to an IPv4 destination embedded in the well-known NAT64 prefix 64:ff9b::/96; the node translates the IPv6 packet to IPv4 (sourced from a shared IPv4 pool address) and translates the reply back to IPv6. This covers TCP and UDP.

NAT64 is off by default. Turn it on by first configuring an IPv4 pool address, then enabling it:

sudo cenvero-str-ctl nat64 configure 203.0.113.10
sudo cenvero-str-ctl nat64 enable

The pool address is the public IPv4 address that translated flows are sourced from. To use a prefix other than the well-known one, pass it as a second argument:

sudo cenvero-str-ctl nat64 configure 203.0.113.10 64:ff9b::/96

Check the current state and the number of active flows:

cenvero-str-ctl nat64 status
{
  "enabled": true,
  "prefix": "64:ff9b::/96",
  "v4_pool": "203.0.113.10",
  "active_bindings": 0,
  "scope": "TCP/UDP (ICMP + fragmentation not translated)"
}

Disable it to return the node to its previous behavior:

sudo cenvero-str-ctl nat64 disable

NAT64 translates TCP and UDP. ICMP and fragmented datagrams are passed through untranslated rather than dropped. IPv6-only clients typically rely on a DNS64 resolver to synthesize 64:ff9b:: addresses for IPv4-only names; DNS64 is a resolver function and is configured separately from NAT64.

ICMP / ping

Tenants behind a masquerade rule can ping IPv4 hosts on the internet. ICMP echo requests are source-NATed to the WAN IP alongside TCP and UDP, and the matching echo replies are translated back to the originating tenant, so ordinary ping connectivity checks work through the node.

This covers ICMP echo (ping) only. It rides on the same masquerade rule — there is no separate command to enable it — so as soon as a subnet has a masquerade rule, its tenants can ping out. ICMP error messages are not translated.

Command reference

Mutating commands require root, so prefix them with sudo; the read-only list and status commands do not.

CommandAction
gateway snat add <lan-cidr> --wan <iface>Masquerade a private LAN subnet out the WAN interface's public IP
gateway snat listList NAT rules (masquerade and published port-forwards)
gateway snat remove <id>Remove a NAT rule by id
nat64 configure <v4-pool> [prefix]Set the IPv4 pool address (and optional /96 prefix)
nat64 enableEnable NAT64 (requires a configured pool)
nat64 disableDisable NAT64 (forwarding reverts to unchanged)
nat64 statusShow NAT64 state, prefix, pool, and active flow count

See also

↓ This page as JSON ↓ All documentation as JSON