Runbook: Troubleshoot Port Forwarding
1 · Prerequisites
Confirm every item is in place before any state change.
- OPNsense 25.x with a public WAN IP
- Port-forward rule already configured and was previously working, or being newly added
- Internal destination host reachable from OPNsense
- External test source (mobile network, public VPS, or another ISP connection)
2 · Pre-checks
Read-only diagnostic commands. If any of these don't match expected output, stop and investigate further.
- · Capture a fresh encrypted config backup before any change
- · Confirm the WAN interface has a public IP and the ISP is not blocking the port (some residential ISPs block 25, 80, 443, 3389)
- · Confirm the internal host is up and listening on the destination port (
netstat -an | grep <port>orss -lntp | grep <port>) - · Disable the OPNsense web GUI on a non-standard port if you are forwarding 443 to avoid the anti-lockout/management collision
3 · Procedure
Execute each step in order. Verify the expected output of a step before moving to the next.
- 1Open Firewall > NAT > Port Forward and confirm the rule exists: WAN interface, source any (or restricted), destination WAN address, destination port, redirect target IP, redirect target port, NAT reflection settings.
- 2Open Firewall > Rules > WAN and confirm the auto-generated rule that matches the port-forward is present and enabled; if missing, click
Apply changeson the NAT page to regenerate it. - 3From the external test source, attempt to connect:
curl -v http://<wan_ip>:<port>ornc -vz <wan_ip> <port>. Note the result and capture the exact error. - 4At the OPNsense shell, run
pfctl -sn | grep <wan_ip>to see the NAT table andpfctl -sr | grep <port>to see the matching WAN rule. - 5Open Firewall > Log Files > Live View, filter on the WAN interface and destination port; check whether packets from the external source are arriving and what action OPNsense is taking.
- 6If the Live View shows a block, click the rule and inspect whether the block is on the WAN interface or a floating rule; fix the block (see opnsense-rb-troubleshoot-blocked-traffic).
- 7If packets arrive and are forwarded but no response is seen from the internal host, run
Diagnostics > Tablesand inspect the firewall state table for the matching 5-tuple; missing state suggests the internal host is not responding. - 8Test from OPNsense itself: from Diagnostics > Command Prompt,
curl http://<internal_ip>:<port>directly to the destination. If this fails, the internal service is the problem, not the port-forward. - 9If the issue is from an internal source trying to reach the public IP, enable NAT reflection: Firewall > NAT > Port Forward, edit the rule, set
NAT reflectiontoEnable (NAT + proxy)(orEnable (Pure NAT)if upstream routers need it). - 10Pure-NAT reflection has known limitations for protocols that embed source IPs (SIP, FTP, some games); document the trade-off and consider Split-DNS instead.
- 11Apply changes and re-test from the external and internal sources.
4 · Verification
Confirm the procedure actually fixed the problem.
- ✓
nc -vz <wan_ip> <port>from the external test source completes the handshake - ✓
curl -v http://<wan_ip>:<port>returns the expected HTTP response - ✓
pfctl -ss | grep <port>shows established states between the external source and the internal destination - ✓Internal source can reach the service via the public IP without hairpin warnings (if reflection is enabled)
5 · Rollback
If verification fails, undo the procedure in reverse order.
- ↶Disable the NAT rule on Firewall > NAT > Port Forward and apply; the associated WAN rule is removed automatically.
- ↶If reflection was added, revert the rule to its prior reflection setting and apply.
- ↶Restore the pre-change encrypted config backup if alias, alias URL table, or other related changes were made.
- ↶Notify the change owner that the port-forward is no longer functional.
6 · Escalation
When the runbook isn't enough, contact:
- · Escalate to the ISP if the port is silently blocked at the carrier level; common for 25, 80, 443, 3389 on residential plans.
- · Escalate to the destination host team if the host is up but not responding on the expected port; suspect host firewall (Windows Firewall, iptables, nftables, cloud security group).
- · Escalate to security if the request is to expose a service that is not approved for public exposure.
- · Escalate to the application vendor if the protocol is one known to break with reflection (SIP/VoIP, FTP active mode, IPsec NAT-T).
Purpose
This runbook diagnoses why an inbound port-forward from the public internet is not working on OPNsense. It covers the most common causes: a missing or disabled NAT rule, an auto-generated firewall rule that did not materialize, an ISP-blocked port, a destination host not listening, and the internal-vs-external hairpin case.
When to use this runbook
Use this runbook when an externally-hosted service (web, SSH, game server, mail relay, etc.) is not reachable via the public WAN IP, and you have reason to believe OPNsense’s port-forward is the most likely cause. If the service was working and stopped, also review the change record for recent ruleset or alias edits.
Pre-checks
- Capture a fresh encrypted config backup before any change.
- Confirm the WAN interface has a public IP (
ifconfig <wan_if>at the shell) and the ISP is not blocking the destination port (residential ISPs commonly block 25, 80, 443, 3389). - Confirm the internal host is up and listening on the destination port: from Diagnostics > Command Prompt, run
netstat -an | grep <port>on a Windows host via RDP orss -lntp | grep <port>over SSH on Linux. - If forwarding 443, move the OPNsense web GUI to a non-standard port first to avoid the management collision and the anti-lockout rule.
Procedure
- Confirm the NAT rule. Open Firewall > NAT > Port Forward. The rule should be: Interface WAN, Source any (or restricted alias), Destination WAN address, Destination port the public port, Redirect target IP the internal host, Redirect target port the internal port. Make a note of any
NAT reflectionsetting. - Confirm the auto-generated WAN rule. Open Firewall > Rules > WAN and confirm a matching pass rule exists for the same destination port. If it is missing, click Apply changes on the NAT page; OPNsense regenerates the auto-rule on apply.
- Test from the external source. From a phone on cellular data, a public VPS, or any other ISP, run
nc -vz <wan_ip> <port>orcurl -v http://<wan_ip>:<port>. Capture the exact error and time it. - Inspect the NAT and rule tables at the shell. Open Diagnostics > Command Prompt and run:
pfctl -sn | grep <wan_ip>— the NAT rulespfctl -sr | grep <port>— the firewall rules matching the portpfctl -ss | grep <port>— the live state table
- Watch Live View. Open Firewall > Log Files > Live View, filter on the WAN interface and destination port, and re-trigger from the external source. Note whether packets are arriving and what action OPNsense takes (block/pass/redirect).
- If Live View shows a block. Note the matching rule. If the block is on the WAN interface or a floating rule with
any/any, see opnsense-rb-troubleshoot-blocked-traffic for the diagnostic path. - If packets arrive but no state is created. The internal host is not responding. Confirm directly: from OPNsense,
curl http://<internal_ip>:<port>. If this fails, the issue is host-side firewall, the service not running, or wrong port. - If the issue is from an internal source. That is the hairpin/NAT reflection case. Edit the NAT rule on Firewall > NAT > Port Forward, set NAT reflection to
Enable (NAT + proxy)(preferred) orEnable (Pure NAT)if the proxy mode interferes with the protocol. Apply and re-test from inside. - Consider Split-DNS instead of reflection. Reflection is brittle for protocols that embed source IPs (SIP, active FTP, some games, IPsec). For most internal-to-public access, prefer DNS host overrides that resolve the public hostname to the internal IP.
- Re-test and confirm. From the external source, repeat the connection test. From an internal source, repeat the same test if reflection was the requested behavior. Both should succeed.
Verification
nc -vz <wan_ip> <port>from the external test source completes the handshake.curl -v http://<wan_ip>:<port>returns the expected HTTP response (or the expected protocol response for non-HTTP services).pfctl -ss | grep <port>shows established states between the external source and the internal destination.- Internal source can reach the service via the public IP without hairpin warnings (if reflection is enabled).
Rollback
- Disable the NAT rule on Firewall > NAT > Port Forward and apply; the associated WAN rule is removed automatically.
- If reflection was added, revert the rule to its prior reflection setting and apply.
- Restore the pre-change encrypted config backup if alias, alias URL table, or other related changes were made.
- Notify the change owner that the port-forward is no longer functional.
Escalation
- Escalate to the ISP if the port is silently blocked at the carrier level. Common for 25, 80, 443, and 3389 on residential plans; many ISPs will unblock on request for business plans.
- Escalate to the destination host team if the host is up but not responding on the expected port; suspect the host firewall (Windows Firewall, iptables, nftables, cloud security group).
- Escalate to security if the request is to expose a service that is not approved for public exposure in the change record.
- Escalate to the application vendor if the protocol is one known to break with reflection (SIP/VoIP, FTP active mode, IPsec NAT-T).