Symptoms
- Package updates, external API calls and OS Management fail from private subnets.
- Backups to Object Storage fail, or instances can't reach OCI APIs without public IPs.
- Started after a networking change or a Terraform apply.
1. Read the subnet's route table
SUBNET=ocid1.subnet.oc1..aaaa
RT=$(oci network subnet get --subnet-id $SUBNET --query 'data."route-table-id"' --raw-output)
oci network route-table get --rt-id $RT --query 'data."route-rules"' --output table
What you expect for a private subnet:
| Destination | Target | Purpose |
|---|---|---|
0.0.0.0/0 | NAT gateway | Internet egress |
All <region> Services in Oracle Services Network | Service gateway | Object Storage, OCI APIs |
| On-premises CIDRs | DRG | Hybrid |
If the 0.0.0.0/0 rule is missing or points at an internet gateway (which does not work for private IPs), fix it.
2. Check the NAT gateway
oci network nat-gateway list --compartment-id $COMP --vcn-id $VCN \
--query 'data[].{name:"display-name", state:"lifecycle-state", block:"block-traffic", ip:"nat-ip"}' --output table
block-traffic: truestops all traffic through the gateway. Someone may have used it as an "emergency stop". Unblock it:
oci network nat-gateway update --nat-gateway-id ocid1.natgateway.oc1..aaaa --block-traffic false
- If the NAT gateway was deleted, create one and point the route rule at it:
NAT=$(oci network nat-gateway create --compartment-id $COMP --vcn-id $VCN --display-name natgw-prod \
--query 'data.id' --raw-output --wait-for-state AVAILABLE)
oci network route-table update --rt-id $RT --force --route-rules \
"[{\"destination\":\"0.0.0.0/0\",\"destinationType\":\"CIDR_BLOCK\",\"networkEntityId\":\"$NAT\"}]"
Warning
route-table update --route-rulesreplaces the whole list. Fetch the current rules first and include every rule you need to keep, or you will cut DRG and service gateway routes too.
A new NAT gateway gets a new public IP. Partners that allow-list your egress IP must be told, or reserve a public IP and assign it when creating the gateway.
3. Service gateway for Oracle services
oci network service-gateway list --compartment-id $COMP --vcn-id $VCN \
--query 'data[].{name:"display-name", block:"block-traffic", services:services[]."service-name"}'
Without a service gateway route, private instances reach Object Storage through the NAT gateway instead. If neither works, backups and agents fail.
4. Security lists and NSGs
Egress must be allowed. Stateful rules handle return traffic automatically; stateless rules need explicit return rules.
oci network security-list get --security-list-id $SL --query 'data."egress-security-rules"' --output table
oci network nsg rules list --nsg-id $NSG --direction EGRESS --output table
A security list with no egress rules, or an NSG change that removed 0.0.0.0/0 egress, blocks everything.
5. Verify from the instance
curl -s -m 5 https://ifconfig.me ; echo
curl -sI -m 5 https://objectstorage.eu-frankfurt-1.oraclecloud.com | head -1
The first should return the NAT gateway's public IP.
Prevent it next time
- Manage VCN routing and gateways in Terraform with review; never edit route tables in the console during business hours.
- Use a reserved public IP for the NAT gateway so egress IP survives recreation.
- Add a monitoring alarm or synthetic check from inside a private subnet.
- Document that
block-trafficis an incident lever and who may use it.