Shore Up
a mail sorter at a public window taking a letter addressed to a street address and rerouting it through a hidden door to a specific desk inside the building
FirewallsSecurity

Configure a Virtual IP for Port Forwarding on a FortiGate

Ketan Aagja7 min read
No ratings yet

A Virtual IP (VIP) on a FortiGate is how you take traffic arriving at a public address and port and redirect it to an internal host — classic destination NAT (port forwarding). This guide walks the standard one-to-one VIP with port forwarding, both in the GUI and the CLI, and shows how to verify and roll it back.

Before you run this

What this does: It creates a firewall VIP object that maps a public IP:port to an internal IP:port, then a firewall policy that permits that traffic. Once both exist, anyone who can reach your public IP on that port reaches your internal server. Treat that as what it is — you are opening a hole through the perimeter.

Environment I assume: A standalone FortiGate on FortiOS 7.4, one internet-facing interface named wan1, and an internal interface named lan. If your interfaces are named differently (port1, internal, an SD-WAN zone), substitute your own names. Menu paths and CLI here are for the 7.4 family; 7.2 is nearly identical but confirm anything that looks off against your build.

Privileges: You need an administrator account with write access to firewall objects and policies. A read-only or profile-restricted admin cannot create these.

Do this safely:

  • Keep a separate console or out-of-band session open (the serial console port, or a management interface on a network you control). A bad policy or an interface mistake can cut you off from the GUI.
  • Back up the running config first. In the GUI: System → Configuration → Backup, save the file locally. A CLI backup exists too (execute backup config …); check the FortiOS CLI reference for the destination arguments if you go that route. The GUI backup is the reliable, version-stable path.
  • Make the change in a maintenance window. Publishing a service and adding an accept policy is a real security and traffic change.
  • Roll back by restoring that backup (System → Configuration → Restore), or by deleting the policy and VIP as shown at the end. Deleting is straightforward and reversible as long as you kept the backup.
  • Test on a lab FortiGate or a VM (FortiGate-VM) before you do it on the production box, and read each command before you paste it.

Nothing here is silently destructive, but an accept policy from wan1 is exactly the kind of rule you want to get right the first time.

The plan

Say you want to publish an internal web server at 192.168.1.10:443 to the internet on your public address 203.0.113.10:443. You need two things:

  1. A VIP object that defines the mapping (external IP:port → internal IP:port).
  2. A firewall policy from wan1 to lan whose destination is that VIP.

The VIP does the DNAT. You reference it in the policy's destination address field — you do not manually configure destination NAT anywhere else.

GUI method

Step 1 — Create the VIP.

  1. Go to Policy & Objects → Virtual IPs.
  2. Click Create New → Virtual IP.
  3. Name: VIP-WebServer-443 (use a name that says what it is).
  4. Interface: select wan1, or leave it as any if you prefer the VIP not to be tied to one interface. Tying it to the ingress interface is the clearer, mainstream choice.
  5. Type: Static NAT.
  6. External IP address/range: 203.0.113.10 to 203.0.113.10 (a single address).
  7. Map to IPv4 address/range: 192.168.1.10.
  8. Enable Port Forwarding.
  9. Protocol: TCP.
  10. External service port: 443.
  11. Map to IPv4 port: 443.
  12. Click OK.

Step 2 — Create the firewall policy.

  1. Go to Policy & Objects → Firewall Policy → Create New.
  2. Name: Inbound-WebServer-HTTPS.
  3. Incoming Interface: wan1.
  4. Outgoing Interface: lan.
  5. Source: all (or, better, a narrower address group if you know who should reach it).
  6. Destination: select your VIP, VIP-WebServer-443. This is the field that makes the DNAT happen.
  7. Schedule: always.
  8. Service: HTTPS (match the port you forwarded).
  9. Action: ACCEPT.
  10. NAT: leave source NAT off for a straightforward inbound publish. Turn it on only if your internal server can't route replies back to the original client (that's a hairpin/return-path problem, not the common case).
  11. Enable logging (Log Allowed Traffic → All Sessions while testing).
  12. Click OK.

CLI method

The same result from the CLI:

config firewall vip
    edit "VIP-WebServer-443"
        set extip 203.0.113.10
        set extintf "wan1"
        set portforward enable
        set protocol tcp
        set extport 443
        set mappedip "192.168.1.10"
        set mappedport 443
    next
end

extip is the public address, mappedip is the internal host, and portforward enable is what lets you translate the port. Without portforward enable, a Static NAT VIP forwards all ports one-to-one.

Now the policy that permits it:

config firewall policy
    edit 0
        set name "Inbound-WebServer-HTTPS"
        set srcintf "wan1"
        set dstintf "lan"
        set srcaddr "all"
        set dstaddr "VIP-WebServer-443"
        set action accept
        set schedule "always"
        set service "HTTPS"
        set logtraffic all
    next
end

edit 0 tells FortiOS to assign the next free policy ID. The VIP goes in dstaddr — that is the whole trick.

One thing to know: the FortiGate applies the VIP's DNAT before it evaluates policy destination, so your service should match the external port. Here external and internal ports are both 443, so it's moot; if you were mapping external 8443 to internal 443, the service in the policy matches the external port (8443).

Verify it worked

Confirm the objects exist and read back correctly:

get firewall vip VIP-WebServer-443
show firewall policy

From an outside host (or a phone off Wi-Fi), connect to 203.0.113.10:443 and confirm you reach the service.

Then watch the FortiGate translate a live session. Filter the session table for your forwarded port and list it:

diagnose sys session filter dport 443
diagnose sys session list

In a matching session you should see the original destination (203.0.113.10) and the translated destination (192.168.1.10) — that's the DNAT in action. Clear the filter afterward with diagnose sys session filter clear.

If traffic isn't arriving, check policy hit counts in Policy & Objects → Firewall Policy (add the Bytes/Sessions columns), and confirm your ISP or upstream device is actually delivering that public IP to the FortiGate.

Undo / rollback

You cannot delete a VIP while a policy references it, so remove the policy first. Find the policy ID (show firewall policy), then:

config firewall policy
    delete <policy-id>
end

config firewall vip
    delete "VIP-WebServer-443"
end

In the GUI, delete the policy under Firewall Policy, then the VIP under Virtual IPs.

If anything else looks wrong, restore the configuration backup you took at the start via System → Configuration → Restore. That's the clean way back to where you started.

For exact field definitions and any options I didn't cover (VIP groups, load-balancing VIPs, ARP reply behaviour), see the FortiOS Administration Guide section on Virtual IPs and the FortiOS CLI Reference for firewall vip on the Fortinet Document Library.

Written by
Ketan Aagja

Runs enterprise networks and security for a living, and writes Shore Up to turn two decades of hands-on Linux, Windows and mail-server work into guides you can actually use.

More about the author →

Was this article helpful?

Tap a star — no sign-in needed.

Be the first to rate this article.