T Techclick ← All lessons
Fortinet · FortiGate · Interactive lesson

VDOM one box, many firewalls

Ticket: tenant-a-op can edit addresses in TENANT-B, and TENANT-A still has no internet even though “the vdom-link is up.” A VDOM object is not isolation. Isolation is interfaces assigned to that VDOM, an admin whose accprofile is scope vdom with only that VDOM listed, and an inter-VDOM link that still has a route plus accept policy on both ends. Lab: TENANT-A LAN 10.20.20.0/24, TENANT-B LAN 10.30.30.0/24, root WAN 192.0.2.0/24.

16 min read · L2 primary · Quiz at end

After this page you can

Lessons · FortiGate series · VDOM tenants and admins

This page vs zone/policy and the other VDOM lesson

This lesson is how one chassis becomes two tenants: VDOM split, admin profiles, inter-VDOM links. Packet → session still lives on zone/policy/NAT. Route leak between dummy-root and a single tenant is the sibling VDOM page.

Zones, policy, NAT · VDOM tenant split (route leak) · Command center

Hero · one chassis, two tenant panes, one global pane
One firewall chassis with three glass panes labeled TENANT-A, TENANT-B and GLOBAL, two operators at separate consoles
Mood, not a wiring diagram. Exact split is in the SVG: port2 in TENANT-A, port3 in TENANT-B, wan1 in root, vdom-links as a pair of virtual interfaces. Artwork labels are not FortiOS objects.
Quick answer

A VDOM is a virtual FortiGate: its own policies, routing table and VPN. Enable with config system global / set vdom-mode multi-vdom (you are logged out). Global still owns interface-to-VDOM assignment, firmware, HA and admin accounts. A tenant operator is config system admin with a profile that has set scope vdom (built-in prof_admin or custom) and a VDOM list — super_admin is the leak. An inter-VDOM link is two virtual interfaces (AVlnk0 / AVlnk1); traffic still needs a route and an accept policy in each VDOM. Proof: diagnose sys vd list, show system admin, then a tenant login that cannot enter Global or the other VDOM. Lab: TENANT-A 10.20.20.0/24, TENANT-B 10.30.30.0/24, root WAN 192.0.2.0/24.

Why creating a VDOM is not isolation

The day-one ticket is always the same: “We created TENANT-A, so they cannot see TENANT-B.” Wrong. config vdom / edit TENANT-A only names a context. Until you move an interface into it, all traffic still hits root. Until you bind the admin to a vdom-scope profile, that operator is still a global pair of hands.

Three silent-leak states look identical from the GUI (green VDOM list):

A VDOM name in the dropdown is not a security boundary

The boundary is: interface membership (global), routing table (per VDOM), firewall policy (per VDOM), admin accprofile + vdom list. Miss any one and the ticket is “they can still see the other tenant.”

VDOM, global, profile, link — four objects

A VDOM is an independent virtual unit: separate security policies and, in NAT mode, separate routing and VPN. FortiOS 6.2+ exposes this as vdom-mode: no-vdom (default), split-vdom (fixed root + FG-traffic), multi-vdom (root plus the tenants you create). Most models start at 10 VDOMs; more is a license. The management VDOM cannot be deleted.

In multi-VDOM you also pick a VDOM type: Traffic (packets), Admin (management only, no through-traffic, at most one), or LAN extension. This lab uses Traffic VDOMs plus root as the shared-WAN / management VDOM.

Path · split, then bind admin, then vdom-link, then prove
Four glass panels labeled Split, Bind admin, VDOM link, Prove
Feel of the order. Exact FortiOS objects — accprofile scope, AVlnk0/AVlnk1, diagnose sys vd list — are in the SVGs. Do not read the Bind-admin panel as “creating the VDOM isolates the operator.”

VDOM

config vdom / edit TENANT-A. GUI: Global › System › VDOM. Type Traffic. Own policy, RIB, VPN. Not an interface.

Global

Firmware, HA, interface-to-VDOM map, admin accounts, some DNS/logging. Only a super_admin created at global sees this.

Admin profile

config system accprofile. Built-in super_admin (undeletable, full box) vs prof_admin / custom with set scope vdom. GUI: System › Admin Profiles.

VDOM link

config system vdom-link creates a pair (name0/name1). Each end is an interface in one VDOM. Still needs IP, route, policy.

Say this out loud

The chassis is global. Each VDOM is a firewall. The admin profile is the key. The vdom-link is just two interfaces — policy still has to accept both sides.

How a packet and an admin walk the split

Two paths, same chassis. A packet from 10.20.20.10 never sees TENANT-B’s policy table. An admin whose VDOM list is only TENANT-A never sees Global or TENANT-B, and can only HTTPS in on an interface that lives in TENANT-A (or the console).

Flow 1 · lab chassis — TENANT-A, TENANT-B, root
Physical FortiGate · global: interfaces, HA, admins, vdom-mode TENANT-A · Traffic port2 10.20.20.1/24 host 10.20.20.10 AVlnk0 10.255.1.2/30 admin tenant-a-op own policy + RIB root · mgmt / WAN wan1 192.0.2.1/24 AVlnk1 10.255.1.1/30 BVlnk1 10.255.2.1/30 admin global-ops FortiGuard / shared NAT TENANT-B · Traffic port3 10.30.30.1/24 host 10.30.30.10 BVlnk0 10.255.2.2/30 admin tenant-b-op own policy + RIB Packet 10.20.20.10 → 203.0.113.80 never enters TENANT-B. Ingress port2 (TENANT-A) → policy LAN-to-AVlnk → AVlnk0 → AVlnk1 (root) → policy AVlnk-to-WAN + SNAT → wan1. No TENANT-A↔TENANT-B link in this lab on purpose. Shared WAN is not east-west. Leak: tenant-a-op accprofile super_admin, or vdom list includes TENANT-B, or port3 still in root. Source: FortiOS Administration Guide — VDOM overview; Inter-VDOM routing configuration example: Internet access.

Read the three panes, then the gold chassis bar is implied above them. Arrows are vdom-links, not physical cables.

Flow 2 · admin key vs packet path
global-ops accprofile super_admin created in config global sees all VDOMs + Global backup / restore allowed tenant-a-op accprofile tenant-admin set scope vdom set vdom TENANT-A login via port2 only Leak super_admin on a tenant or vdom TENANT-A TENANT-B or scope global custom can edit the other tenant Per-VDOM admin cannot use super_admin. Multi-VDOM assignment is created at global. They log in only through an interface assigned to their VDOM (allowaccess https ssh) or the console. HTTPS to wan1 (root) as tenant-a-op fails even with a correct password — wrong VDOM on the ingress intf. VDOM administrators do not see global settings or unassigned VDOMs. That is the GUI proof. Source: FortiOS — Administrator profiles; Create per-VDOM administrators; config system accprofile scope.

Left is the MSSP operator. Middle is the tenant. Right is the ticket you are here to close.

ObjectLab valueIf missing
vdom-modemulti-vdomNo second VDOM. split-vdom is a different product: root + FG-traffic only.
TENANT-ATraffic · port2 10.20.20.1/24Host ARP fails, or packets still match root policy.
TENANT-BTraffic · port3 10.30.30.1/24Same. Do not leave port3 in root “for now.”
root WANwan1 192.0.2.1/24 gw 192.0.2.254No FortiGuard, no shared internet. Management VDOM needs a path out.
AVlnkAVlnk0 10.255.1.2 · AVlnk1 10.255.1.1 /30No path from TENANT-A to WAN. Ping across the pair is not internet.
tenant-a-opaccprofile tenant-admin · vdom TENANT-Asuper_admin = can edit TENANT-B. That is the original ticket.

Independent vs shared-WAN vs split-vdom

Pick the topology the contract actually bought. Mixing them is the usual “they have internet through my VDOM” ticket.

NeedUseSkip
One management plane, one traffic planesplit-vdom: root is management-only (no through-traffic); FG-traffic is the data VDOMCreating extra named VDOMs. split-vdom is two fixed contexts.
Two tenants, each with its own WANmulti-vdom, independent VDOMs, no vdom-link. Move a WAN port into each tenant.Shared root NAT. That re-introduces a common policy domain.
Two tenants, one ISP on the chassis (this lab)multi-vdom + vdom-link from each tenant into root + policy/NAT in rootAssigning wan1 into TENANT-A and hoping TENANT-B “uses it.”
East-west between tenantsA dedicated vdom-link TENANT-A↔TENANT-B, policies on both ends, explicit addresses — treat it as a DMZHairpinning both tenants through root without a deny between them.
MSSP tenant operatorCustom accprofile scope vdom (or prof_admin), VDOM list = that tenant only, login on that tenant’s intfsuper_admin “just for onboarding.” It never gets taken back.
Inter-VDOM constraints

You cannot build a vdom-link between two Layer-2 transparent VDOMs. At least one end must be NAT. Hardware NPUs expose npu0_vlink0/1 for accelerated links; software config system vdom-link is the lab default. Source: FortiOS inter-VDOM routing notes.

Runbook Side A / B / C

Side A is VDOMs and interfaces. Side B is admin profiles. Side C is the vdom-link, policy, and proof. Do not start at C — a link into a VDOM that still owns no LAN port is a black hole.

Side A — enable multi-vdom, create tenants, move ports

  1. Turn on multi-vdom

    System › Settings › Virtual Domains (toggle). CLI: config system global / set vdom-mode multi-vdom. You are logged out. vdom-mode is a hidden command — type it in full; it will not tab-complete. Source: FortiOS Administration Guide — VDOM overview; Community TT: How to enable multiple VDOMs.

  2. Create TENANT-A and TENANT-B

    Log back in as a super_admin. Global › System › VDOM › Create New. Type Traffic. CLI config vdom / edit TENANT-A. Management VDOM stays root unless you have a reason to move FortiGuard.

  3. Move interfaces (global)

    Global › Network › Interfaces. port2 → VDOM TENANT-A, IP 10.20.20.1/24, allowaccess ping https ssh. port3 → TENANT-B 10.30.30.1/24. wan1 stays root 192.0.2.1/24. Address lives on the member, not on the VDOM name.

CLI — Side A
config system global
    set vdom-mode multi-vdom
end
# logged out — log back in as super_admin

config vdom
    edit TENANT-A
    next
    edit TENANT-B
    next
end
config global
    config system interface
        edit "port2"
            set vdom "TENANT-A"
            set ip 10.20.20.1 255.255.255.0
            set allowaccess ping https ssh
            set role lan
        next
        edit "port3"
            set vdom "TENANT-B"
            set ip 10.30.30.1 255.255.255.0
            set allowaccess ping https ssh
            set role lan
        next
        edit "wan1"
            set vdom "root"
            set ip 192.0.2.1 255.255.255.0
            set allowaccess ping https ssh
            set role wan
        next
    end
end
config vdom
    edit root
        config router static
            edit 1
                set gateway 192.0.2.254
                set device "wan1"
            next
        end
    next
end

Side B — profiles then per-VDOM admins

https://10.20.20.1/ · Global › System › Administrators › Create New › Administrator
Training mock · not live

System › Administrators › Create New › Administrator

tenant-a-op

tenant-a-op · Local User
tenant-admin
TENANT-A
root, TENANT-B — removed

Source: FortiOS Administration Guide — Create per-VDOM administrators (Global VDOM, System › Administrators, Type Local User, Virtual Domains field). Profile is prof_admin or custom — not super_admin. Multi-VDOM assignment is created at global.

  1. Custom vdom-scope profile

    System › Admin Profiles › Create Newtenant-admin. CLI set scope vdom, then fwgrp / netgrp read-write, loggrp read. Built-in prof_admin is already VDOM-scoped if you do not want a custom profile. Source: FortiOS — Administrator profiles; config system accprofile.

  2. Bind tenant-a-op and tenant-b-op

    Virtual Domains = that tenant only. Repeat for TENANT-B. Keep global-ops as the only super_admin. Per-VDOM admins cannot backup/restore the box.

CLI — Side B
config global
    config system accprofile
        edit "tenant-admin"
            set scope vdom
            set fwgrp read-write
            set netgrp read-write
            set loggrp read
            set utmgrp read-write
        next
    end
    config system admin
        edit "tenant-a-op"
            set accprofile "tenant-admin"
            set vdom "TENANT-A"
            set password ENC <set_on_box>
        next
        edit "tenant-b-op"
            set accprofile "tenant-admin"
            set vdom "TENANT-B"
            set password ENC <set_on_box>
        next
    end
end
Do not put super_admin on a tenant account

When creating an administrator at the VDOM level, super_admin cannot be used — FortiOS blocks it. The leak is creating the account at global with super_admin or adding a second VDOM to the list “so they can help.” Remove TENANT-B from tenant-a-op before you call it isolated.

Side C — vdom-link, policy both sides, prove

https://192.0.2.1/ · Global › Network › Interfaces › Create New › VDOM link
Training mock · not live

Network › Interfaces › Create New › VDOM link

AVlnk

TENANT-A
10.255.1.2/255.255.255.252
root
10.255.1.1/255.255.255.252

Source: FortiOS — Inter-VDOM routing configuration example: Internet access (Global › Network › Interfaces › Create New › VDOM link). OK creates AVlnk0 and AVlnk1. You still need routes and firewall policies in each VDOM. Repeat as BVlnk for TENANT-B (10.255.2.0/30).

  1. Link pair + IPs

    config system vdom-link / edit AVlnk. Then config system interface on AVlnk0 (TENANT-A, 10.255.1.2/30) and AVlnk1 (root, 10.255.1.1/30), allowaccess ping. Same for BVlnk.

  2. Routes and accept on both ends

    TENANT-A: default via 10.255.1.1 device AVlnk0. Policy LAN(port2)→AVlnk0 accept + NAT if you hide behind the link IP. Root: policy AVlnk1→wan1, src 10.20.20.0/24, accept, nat enable to 192.0.2.1. Reverse: wan1 is not a path into TENANT-A unless you add a VIP + policy — out of scope here.

  3. Prove isolation, then prove internet

    Login as tenant-a-op on https://10.20.20.1. No Global menu, no TENANT-B. Then from 10.20.20.10 HTTPS to 203.0.113.80; in TENANT-A diagnose sys session filter src 10.20.20.10 / listvd=TENANT-A. In TENANT-B the same filter is empty.

CLI — Side C (TENANT-A shared WAN; mirror for TENANT-B)
config global
    config system vdom-link
        edit "AVlnk"
        next
    end
    config system interface
        edit "AVlnk0"
            set vdom "TENANT-A"
            set ip 10.255.1.2 255.255.255.252
            set allowaccess ping
        next
        edit "AVlnk1"
            set vdom "root"
            set ip 10.255.1.1 255.255.255.252
            set allowaccess ping
        next
    end
end
config vdom
    edit TENANT-A
        config router static
            edit 1
                set gateway 10.255.1.1
                set device "AVlnk0"
            next
        end
        config firewall policy
            edit 1
                set name "LAN-to-AVlnk"
                set srcintf "port2"
                set dstintf "AVlnk0"
                set srcaddr "all"
                set dstaddr "all"
                set action accept
                set schedule "always"
                set service "ALL"
                set nat enable
                set logtraffic all
            next
        end
    next
    edit root
        config firewall address
            edit "TENANT_A_LAN"
                set subnet 10.20.20.0 255.255.255.0
            next
        end
        config firewall policy
            edit 10
                set name "AVlnk-to-WAN"
                set srcintf "AVlnk1"
                set dstintf "wan1"
                set srcaddr "TENANT_A_LAN"
                set dstaddr "all"
                set action accept
                set schedule "always"
                set service "ALL"
                set nat enable
                set logtraffic all
            next
        end
    next
end
Green proof

diagnose sys vd list shows TENANT-A / TENANT-B / root. show system admin tenant-a-op has accprofile tenant-admin and only TENANT-A. Tenant GUI has no Global. Session list in TENANT-A has the flow; TENANT-B does not. That is the close — not “the VDOM exists.”

One flow after go-live

Host 10.20.20.10 SYN to 203.0.113.80:443. Ingress port2, VDOM TENANT-A. Session miss. RIB default via 10.255.1.1, egress AVlnk0. Policy LAN-to-AVlnk accept, SNAT to 10.255.1.2 (if NAT on that policy). Packet arrives AVlnk1 in root. Root RIB default via 192.0.2.254, egress wan1. Policy AVlnk-to-WAN matches TENANT_A_LAN, accept, SNAT to 192.0.2.1. Two sessions, two vd= values. Reply reverses both hooks. TENANT-B’s table never sees the 5-tuple.

Admin path: tenant-a-op HTTPS to 10.20.20.1 (port2). Local-in in TENANT-A. GUI is VDOM:TENANT-A only. Same user to 192.0.2.1 is a miss — wan1 is root. global-ops HTTPS to wan1 sees the VDOM switcher.

Proof · isolation is two empty-or-not session tables, not a dashboard tile
Engineer at a monitor showing two isolated tenant panes with green isolated checkmarks
Ops feel. The actual evidence is diagnose sys vd list, show system admin, tenant GUI scope, and diagnose sys session list with vd=TENANT-A. Artwork checkmarks are not FortiOS.
Proof commands — run in the right VDOM
get system status
# Virtual domain configuration: multiple / vdom-mode

config global
diagnose sys vd list
show system admin tenant-a-op
# accprofile tenant-admin
# vdom TENANT-A     <— TENANT-B must not appear

config vdom
edit TENANT-A
diagnose sys session filter clear
diagnose sys session filter src 10.20.20.10
diagnose sys session list
# vd=TENANT-A  policy_id=1
next
edit TENANT-B
diagnose sys session filter src 10.20.20.10
diagnose sys session list
# empty — if you see the flow here, the interface is in the wrong VDOM
end

Traps + proof

SymptomLikely causeProof
tenant-a-op edits TENANT-B objectssuper_admin, scope global, or set vdom lists both tenantsshow system admin tenant-a-op. Fix the list; do not “train them not to click.”
VDOM created, packets still hit root policyInterface still set vdom rootconfig global / show system interface port2 — look at set vdom.
vdom-link up, no internetMissing route or accept on one side. Link is L3, not a permit.Ping 10.255.1.1 from TENANT-A works; debug flow in root shows policy 0.
tenant-a-op cannot HTTPS inLogging in on wan1 (root) or port3 (TENANT-B). Per-VDOM admin must use an intf in their VDOM.Try https://10.20.20.1. Console still works.
Enabling VDOM kicked everyone offExpected. set vdom-mode logs you out. Management VDOM must still have a path to FortiGuard.Log back in. get system status. Confirm mgmt VDOM has a default route.
Empty session in the VDOM you are debuggingCLI still in root, or HA standbyconfig vdom / edit TENANT-A first. Standby has no forwarding table.
Cannot create link, both VDOMs transparentFortiOS refuses L2-to-L2 vdom-link (loop risk)Put at least one end in NAT. Source: inter-VDOM routing constraints.
Tenant sees a profile they cannot editGlobal security profiles are read-only inside a VDOMEdit from Global, or clone a VDOM-local profile. Not a permission bug.
Do not assign wan1 to TENANT-A to “give them internet”

That steals the shared ISP from TENANT-B and from FortiGuard on root. Shared WAN is a vdom-link plus root policy. Independent WAN is a second physical (or VLAN) moved into that tenant.

Pilot checklist

Knowledge check

Six judgment items. Submit once. Reasons point back at the section to re-read.

Q1

Ticket: tenant-a-op can edit address objects in TENANT-B. The VDOM objects exist. What do you inspect first?

Correct: c. Creating TENANT-A does not bind the operator. Isolation is scope vdom plus a VDOM list that is only TENANT-A. Re-read Why creating a VDOM is not isolation and Flow 2.
Q2

AVlnk0/AVlnk1 ping. Host 10.20.20.10 still times out to 203.0.113.80. What is missing?

Correct: b. The pair of virtual interfaces is not a firewall policy. Both VDOMs still first-match accept. Re-read Flow 1, How to choose, and Side C.
Q3

How do you create an administrator who can see every VDOM and change global settings?

Correct: a. FortiOS: a global administrator that has access to all VDOMs and global settings must be created at global and must use super_admin. Per-VDOM creation cannot use super_admin. Re-read Flow 2 and Side B.
Q4

tenant-a-op password is right. HTTPS to 192.0.2.1 (wan1) fails. First explanation?

Correct: d. Official: per-VDOM administrators access the FortiGate through a network interface assigned to their VDOM, with management access enabled. Re-read Flow 2 and Traps.
Q5

When is split-vdom the right mode instead of multi-vdom?

Correct: b. split-vdom is two fixed VDOMs. multi-vdom is root plus the tenants you create (this lab). Inter-VDOM links are a multi-vdom tool. Re-read How to choose.
Q6

What actually proves TENANT-A traffic stayed out of TENANT-B?

Correct: c. Admin scope plus per-VDOM session tables are the wire. Ping to the gateway is local-in. Re-read Side C, Runtime, and Traps.

Sources

Related: Zones, policy, NAT · VDOM tenant split · FortiGate command center · FortiGate interview