When to use this
Connections between two OCI hosts (or from on-premises) time out, and every rule "looks right". Instead of reading rules again, collect evidence: flow logs show every accepted and rejected flow at the VNIC.
Step 1: enable flow logs on the subnet
Console: Logging > Logs > Enable service log, service Networking: VCN flow logs (in newer consoles, flow logs are configured through capture filters), resource = the subnet, category = all records.
CLI, with an existing log group:
cat > flowlog-config.json <<'EOF'
{
"source": {
"sourceType": "OCISERVICE",
"service": "flowlogs",
"resource": "ocid1.subnet.oc1.ap-mumbai-1.aaaa...",
"category": "all"
},
"compartmentId": "ocid1.compartment.oc1..aaaa..."
}
EOF
oci logging log create --log-group-id ocid1.loggroup.oc1.ap-mumbai-1.aaaa... \
--display-name flow-app-subnet --log-type SERVICE \
--configuration file://flowlog-config.json --is-enabled true
Option names vary between console versions and CLI releases; check oci logging log create --help for your build. Enable it on both the source and destination subnets if they differ.
Tip
Flow logs cost ingestion and storage. Enable them for the investigation, or permanently only on critical subnets with a short retention.
Step 2: reproduce, then search for rejects
Reproduce the failing connection a few times, wait a few minutes for records to arrive, then in Logging > Search:
search "ocid1.compartment.oc1..aaaa.../ocid1.loggroup.oc1.ap-mumbai-1.aaaa.../ocid1.log.oc1.ap-mumbai-1.aaaa..."
| where data.action = 'REJECT'
| where data.destinationPort = 1521
| sort by datetime desc
Useful fields in each record:
| Field | Meaning |
|---|---|
data.action | ACCEPT or REJECT |
data.sourceAddress, data.sourcePort | Who started the flow |
data.destinationAddress, data.destinationPort | Target |
data.protocol | 6 = TCP, 17 = UDP, 1 = ICMP |
data.vnicocid | Which VNIC logged it |
data.status | OK, NODATA or SKIPDATA for the capture window |
Summarise to find the pattern quickly:
search "<compartment>/<loggroup>/<log>"
| where data.action = 'REJECT'
| stats count() as drops by data.sourceAddress, data.destinationAddress, data.destinationPort
| sort by drops desc
Step 3: interpret what you see
| What flow logs show | Meaning | Where to look |
|---|---|---|
| REJECT at the destination VNIC | Ingress rule on destination's security list or NSG doesn't allow it | Destination subnet security list + VNIC's NSGs |
| REJECT at the source VNIC | Egress rule on source denies it | Source security list + NSGs |
| ACCEPT at source, nothing at destination | Packet never arrived: routing, DRG, LPG, firewall appliance, or wrong IP | Route tables, DRG route distributions, LPG troubleshooting |
| ACCEPT at both, app still fails | Not the VCN: OS firewall (firewalld, Windows Firewall), service not listening, TLS | ss -ltnp, host firewall |
| ACCEPT request, REJECT reply | Stateless rule in one direction only | Add the matching stateless return rule, or make the rule stateful |
Remember how the rules combine: a VNIC allows traffic if any security list on its subnet or any NSG it's in allows it. A missing rule anywhere doesn't block if another rule allows; there are no deny rules.
Step 4: double-check with Network Path Analyzer
Network Path Analyzer (Networking > Network Command Center > Network Path Analyzer) simulates a flow from source to destination and reports the security rule or route that blocks it. Use it to confirm the fix before re-testing, and flow logs to confirm real traffic afterwards.
Common findings
- On-premises source range missing from the database subnet's ingress rule (the rule allows the VCN CIDR only).
- NSG rule allows the port but uses the wrong NSG as source (the app VNIC is in a different NSG).
- Stateless egress without the matching ingress for return traffic.
- Load balancer health checks rejected because backends only allow the client CIDR, not the LB subnet.
Prevent it next time
- Keep a short-retention flow log on shared and database subnets so evidence exists before the incident.
- Prefer NSGs scoped to roles (app, db, lb) over wide security lists; they're easier to read in flow logs too.
- Related: security lists vs NSGs.