Symptom
You've added an ingress rule for a port such as 8080 in the security list or network security group (NSG), but connections from outside still time out. SSH works fine, and the app works from inside the server with curl localhost:8080.
The usual cause: OCI platform images have a second firewall inside the operating system. The cloud rule and the host firewall both have to allow the traffic.
Step 1: check that the app is listening
On the instance:
sudo ss -ltnp | grep 8080
| Output | Meaning |
|---|---|
| Nothing | The app isn't running on that port. Fix the app first |
127.0.0.1:8080 | It's listening only on localhost, so outside traffic can't reach it. Bind to 0.0.0.0 |
0.0.0.0:8080 or *:8080 | Good. Move on |
Then test locally:
curl -I http://localhost:8080/
Step 2: see whether packets reach the instance
Open a second SSH session and run:
sudo tcpdump -ni any tcp port 8080
Now try connecting from your laptop:
nc -vz -w 5 <public-ip> 8080
| What tcpdump shows | Where the problem is |
|---|---|
| SYN packets arrive, with no reply | The host firewall is dropping them. Go to Step 3 |
| Nothing arrives | The network: go to Step 4 |
| SYN arrives, with a reply going out | Check the return route, or a firewall on the client's side |
This one test saves a lot of guessing. If tcpdump isn't installed, run sudo dnf install -y tcpdump or sudo apt install -y tcpdump.
Step 3: open the host firewall
Oracle Linux: firewalld
sudo firewall-cmd --state
sudo firewall-cmd --list-all
sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
sudo firewall-cmd --list-ports
Without --permanent, the rule disappears at reboot. Without --reload, a permanent rule doesn't apply yet.
Ubuntu: iptables
Ubuntu platform images on OCI use iptables rules saved in /etc/iptables/rules.v4, not ufw. First, list the rules with their numbers:
sudo iptables -L INPUT -n --line-numbers
The list usually ends with a REJECT rule. A new rule must go above that line, because the first match wins. If REJECT is on line 6:
sudo iptables -I INPUT 6 -m state --state NEW -p tcp --dport 8080 -j ACCEPT
sudo netfilter-persistent save
Adding a rule with -A puts it after the REJECT, where it never matches. That's the most common mistake here.
Caution
Don't run
iptables -For turn onufwon an OCI Ubuntu instance. Oracle's default rules protect access to services such as block storage and metadata, and removing or reordering them can leave the instance unable to boot or reach its volumes. Only add the rules you need.
Windows Server
New-NetFirewallRule -DisplayName "App 8080" -Direction Inbound -Protocol TCP -LocalPort 8080 -Action Allow
Get-NetTCPConnection -LocalPort 8080 -State Listen
Then test again:
nc -vz -w 5 <public-ip> 8080
SELinux can also block the app from starting
On Oracle Linux, if the app won't bind to a non-standard port, or it's a service such as nginx failing with Permission denied, check SELinux:
sudo ausearch -m avc -ts recent | tail
sudo semanage port -a -t http_port_t -p tcp 8080
semanage is in the policycoreutils-python-utils package. Don't turn SELinux off to work around this.
Step 4: if packets never arrive
Work through the network path in this order:
| Check | What to look for |
|---|---|
| Public IP | The instance has one, and you're using the right one |
| Internet gateway | The VCN has one, and it's enabled |
| Route table | The subnet has 0.0.0.0/0 to the internet gateway |
| Security list | An ingress rule for TCP with destination port 8080 |
| NSG | The rule is on the NSG that this VNIC actually belongs to |
| Your side | Your office network may block the outgoing port |
A common error is putting 8080 in the rule's source port range. Leave source ports as All.
oci network security-list get --security-list-id <ocid> \
--query 'data."ingress-security-rules"[?protocol==`6`]'
Network Path Analyzer can test the path for you. Security lists vs NSGs explains how the two rule types combine.
Quick reference
| Symptom | Likely layer |
|---|---|
Connection timed out | Security rule, routing or firewall dropping packets |
Connection refused | Reached the host, but nothing listens on the port, or a REJECT rule |
No route to host | Often a firewall REJECT with that message |
Works with localhost, not from outside | Bind address or host firewall |
| Works until reboot | The rule wasn't saved |
Warning
Don't open a port to
0.0.0.0/0just to test. Allow only your own IP (x.x.x.x/32) until you're sure the service is meant to be public, especially for database and admin ports.
Prevent it next time
- Add firewall commands to your cloud-init script, so new instances open the right ports when they're built.
- After any change, reboot one test instance to check that the rules survive.
- Keep app ports behind a load balancer, and use Bastion for admin access.