Want to reach your local network from anywhere in the world? In this guide, I'll show you how, using a FortiGate 40F and SSL VPN, configured entirely from the command line. Every step is a block you can copy, review and keep in version control.
Heads up: SSL VPN was removed from FortiOS 7.6.3 and later on lower-end models (including the 40F), which are pushed toward IPsec instead. The commands in this guide apply to FortiOS 7.2 and 7.4. Syntax can differ on other branches, so check with
?and tab completion on your own build.A note on values: every address, name and secret below is an example. Replace anything in
<ANGLE_BRACKETS>and change the example subnets to match your network. Never publish or reuse real credentials, public IPs or certificate fingerprints.
What is an SSL VPN?
An SSL VPN lets you connect to a private network that isn't directly reachable from the internet. Traffic is encrypted with TLS (the successor to SSL) and carried over HTTPS, so it usually passes through firewalls that block other VPN protocols.
Why the CLI instead of the web UI?
- Repeatable: paste the same blocks on a second firewall or after a factory reset.
- Reviewable: you can diff and comment a text file. You can't diff a series of screenshots.
- Precise: the CLI shows every option, including the ones the GUI hides.
Prerequisites
- A FortiGate 40F with admin access
- A Linux machine, or any device with FortiClient, to test the connection
- A free TCP port for the VPN (we'll use
10443) - (If behind a router) access to the router to configure port forwarding
Example values used in this guide
| Item | Example value |
|---|---|
| WAN interface | wan |
| LAN interface | lan |
| LAN subnet | 10.20.0.0/24 |
| VPN client pool |
10.10.10.2 – 10.10.10.254
|
| VPN listen port | 10443 |
| User group | SSL-VPN-GROUP |
| Portal | SSL-VPN-PORTAL |
| Example user | alice |
Step 0: Open the console and back up
You can reach the CLI in three ways:
- the CLI Console (
>_icon) in the top bar of the web UI - SSH to the FortiGate's management address
- the serial console cable
Back up the current configuration before changing anything:
execute backup config flash "before-ssl-vpn"
Some basics for the rest of the guide:
- Each
config ... endblock opens and closes a configuration section. - Press Tab to complete a command and ? to list options.
-
showprints the changes you made in a section, andshow full-configurationincludes defaults.
Step 1: Create the user and group
Create one account per person. Shared accounts make it impossible to tell who did what, or to revoke one person's access.
config user local
edit "alice"
set type password
set passwd "<STRONG_PASSWORD>"
next
end
config user group
edit "SSL-VPN-GROUP"
set member "alice"
next
end
To add a user to an existing group later without removing the other members, use append:
config user group
edit "SSL-VPN-GROUP"
append member "bob"
next
end
Two-factor authentication. This guide leaves it off to keep the demo short. In production, turn it on. For example, with a FortiToken (mobile or hardware):
config user local
edit "alice"
set two-factor fortitoken
set fortitoken "<TOKEN_SERIAL>"
set email-to "<USER_EMAIL>"
next
end
Check your build's options with set two-factor ?.
Step 2: Create the tunnel IP pool
Clients that connect receive an address from this range. Pick a subnet that doesn't overlap any network the FortiGate already knows about.
config firewall address
edit "SSL-VPN-RANGE"
set type iprange
set start-ip 10.10.10.2
set end-ip 10.10.10.254
next
end
Step 3: Create the SSL VPN portal
The portal defines what a connected user gets. Here we want tunnel mode with no split tunneling, so all client traffic goes through the firewall.
config vpn ssl web portal
edit "SSL-VPN-PORTAL"
set tunnel-mode enable
set web-mode disable
set ip-pools "SSL-VPN-RANGE"
set split-tunneling disable
set limit-user-logins enable
next
end
| Option | Value | Why |
|---|---|---|
tunnel-mode |
enable |
Gives the client a full VPN tunnel |
web-mode |
disable |
Removes the browser portal and its extra attack surface. Enable it only if you use bookmarks. |
split-tunneling |
disable |
All client traffic is sent through the tunnel and your firewall policies |
limit-user-logins |
enable |
One session per user |
ip-pools |
SSL-VPN-RANGE |
Where clients get their address |
The portal also leaves "save password", "auto-connect" and "keep-alive" off by default. Leave them that way.
Step 4: Configure the SSL VPN settings
config vpn ssl settings
set status enable
set port 10443
set source-interface "wan"
set source-address "all"
set servercert "Fortinet_Factory"
set https-redirect enable
set tunnel-ip-pools "SSL-VPN-RANGE"
set idle-timeout 300
config authentication-rule
edit 1
set groups "SSL-VPN-GROUP"
set portal "SSL-VPN-PORTAL"
next
end
end
| Option | Value | Notes |
|---|---|---|
port |
10443 |
Avoid 443, which can conflict with the management interface |
source-interface |
wan |
The interface that listens for VPN connections |
source-address |
all |
Fine for a lab. Restrict it in production (see below). |
servercert |
Fortinet_Factory |
The built-in default. Clients will see a certificate warning. Replace it in production. |
https-redirect |
enable |
Redirects plain HTTP to the SSL VPN |
idle-timeout |
300 |
Logs out idle users after 300 seconds. 0 means never. |
authentication-rule |
group → portal | Only SSL-VPN-GROUP members get SSL-VPN-PORTAL
|
Check the fallback mappings
FortiOS ships with default portal mappings, and users who don't match your rule may still be mapped to a default portal. List them:
show vpn ssl settings
Review the authentication-rule entries and the default-portal value. Remove any mapping you don't need, or point unmatched users at a portal that gives no access if your build has one (show vpn ssl web portal lists what exists).
Restrict who can reach the VPN
Allowing any host to reach a login page on the internet invites scanning and brute-force attempts. Limit the source, either to known addresses:
config firewall address
edit "VPN-ALLOWED-SOURCES"
set type iprange
set start-ip <ALLOWED_START_IP>
set end-ip <ALLOWED_END_IP>
next
end
config vpn ssl settings
set source-address "VPN-ALLOWED-SOURCES"
end
or to specific countries:
config firewall address
edit "VPN-ALLOWED-COUNTRIES"
set type geography
set country "<TWO_LETTER_COUNTRY_CODE>"
next
end
config vpn ssl settings
set source-address "VPN-ALLOWED-COUNTRIES"
end
Step 5: Create the firewall policies
You need two policies, both coming in from the tunnel interface ssl.root:
- one for traffic to the local network behind the firewall
- one for traffic going out through the WAN (internet access for clients, because split tunneling is off)
First, create an address object for the LAN you want to expose, so the first policy doesn't have to use all:
config firewall address
edit "LAN-SUBNET"
set type ipmask
set subnet 10.20.0.0 255.255.255.0
next
end
Then the policies:
config firewall policy
edit 0
set name "SSL-VPN-LAN-ACCESS"
set srcintf "ssl.root"
set dstintf "lan"
set srcaddr "all"
set dstaddr "LAN-SUBNET"
set groups "SSL-VPN-GROUP"
set action accept
set schedule "always"
set service "ALL"
set nat enable
set logtraffic all
next
edit 0
set name "SSL-VPN-WAN-ACCESS"
set srcintf "ssl.root"
set dstintf "wan"
set srcaddr "all"
set dstaddr "all"
set groups "SSL-VPN-GROUP"
set action accept
set schedule "always"
set service "ALL"
set nat enable
set logtraffic all
next
end
Why
srcaddr "all"plus a group? In a user-based policy the group does the real filtering.alljust means "from any address in the tunnel".About NAT on the LAN policy: with
nat enable, LAN hosts see the firewall's own address instead of the VPN client's. That keeps routing simple. If you disable NAT, your LAN hosts need a return route to the VPN pool.
Don't leave service "ALL" in production
ALL services to a whole subnet is convenient for a lab and dangerous if a password leaks. Allow only what each user needs:
config firewall policy
edit <POLICY_ID>
set service "HTTPS" "SSH"
set dstaddr "<SPECIFIC_SERVER>"
next
end
Create one policy per role (admins, developers, contractors), each with its own group and destinations. This is the principle of least privilege. It matters even more here because the demo has two-factor authentication off.
Check the routing
Tunnel clients need the FortiGate to know how to reach the internet and the LAN. Confirm there is a default route out of wan:
get router info routing-table all
Step 6: Verify the configuration
Before testing from a client, review what you entered:
show vpn ssl settings
show vpn ssl web portal SSL-VPN-PORTAL
show firewall policy
Confirm that the SSL VPN is listening:
diagnose sys tcpsock | grep 10443
Step 7: Connect with a client
FortiClient (Windows, macOS, iOS, Android)
Create an SSL-VPN connection with:
| Field | Value |
|---|---|
| Remote gateway | <ROUTER_PUBLIC_IP_OR_DDNS_NAME> |
| Customize port | 10443 |
| Username | your own account |
You'll be prompted for the password each time, because the portal doesn't allow saving it.
Linux with openfortivpn
sudo apt install openfortivpn
The first time, you need to trust the firewall's certificate. Run the command with a wrong or missing --trusted-cert and it will print the certificate's hash:
openfortivpn <VPN_ADDRESS>:10443 -u alice 2>&1 | grep trusted-cert
# Output:
# ERROR: --trusted-cert <SHA256_FINGERPRINT>
Verify that this hash matches your firewall's certificate before trusting it (for example, by viewing the certificate on the FortiGate). Then connect:
sudo openfortivpn <VPN_ADDRESS>:10443 \
-u alice \
--trusted-cert <SHA256_FINGERPRINT>
You'll be prompted for the password. Avoid -p 'PASSWORD' on the command line, since it ends up in your shell history and is visible in the process list. If you use /etc/openfortivpn/config to store settings, keep the password out of it and restrict the file:
sudo chmod 600 /etc/openfortivpn/config
Check the session on the firewall
get vpn ssl monitor
You should see the user, the source address and an address from your pool.
Step 8: Forward the port (if the firewall is behind a router)
If your FortiGate sits behind a router (for example, a home or ISP router) instead of having a public IP directly on its WAN interface, the router has to pass the VPN traffic through. Create a port forwarding rule on the router:
| Setting | Value |
|---|---|
| Protocol | TCP |
| External port | 10443 |
| Internal IP | The FortiGate's WAN interface IP |
| Internal port | 10443 |
Then connect using the router's public IP (or a domain name pointing to it) instead of the firewall's internal IP.
Note: port forwarding won't work if your ISP uses CGNAT (you don't have a real public IP). If your public IP changes often, use a dynamic DNS name. FortiGate can update a FortiGuard DDNS name itself, so you don't have to publish an IP address anywhere.
Troubleshooting from the CLI
If the client can't connect, watch what the firewall sees. The first command shows whether traffic arrives at all:
diagnose sniffer packet wan 'tcp port 10443' 4
For authentication and tunnel problems, enable the SSL VPN debug, reproduce the problem, then switch it off:
diagnose debug application sslvpn -1
diagnose debug enable
# ...try to connect...
diagnose debug disable
diagnose debug reset
| Symptom | Likely cause | What to check |
|---|---|---|
| Timeout or "server unreachable" | Port forward missing, CGNAT, wrong port, stale DDNS | The sniffer shows no packets: check the router and DNS |
| Certificate warning | Default certificate in use | Expected until you install a trusted certificate |
| Login rejected | Wrong password, user disabled, user not in the group |
show user local, show user group
|
| Connects but reaches nothing | Policy or route missing |
show firewall policy, get router info routing-table all
|
| Redirect warning | Admin HTTP port conflicts with the redirect | Keep the VPN on 10443 and review the admin HTTP port |
Rollback
If something goes wrong, undo the changes in this order. Take a backup first if you made changes since Step 0.
config firewall policy
delete "SSL-VPN-LAN-ACCESS"
delete "SSL-VPN-WAN-ACCESS"
end
config vpn ssl settings
set status disable
end
Or restore the backup you took at the start from the web UI (System → Configuration → Revisions).
Conclusion
You now have a working SSL VPN on your FortiGate 40F, configured and verified from the console. Before using it in production, I recommend:
- enabling two-factor authentication for every user
- restricting access by source address or country, and by destination subnet and service
- using a certificate from a trusted CA instead of the factory default
- adding security profiles (antivirus, IPS, web filter) to the policies, since the demo uses none
- reviewing the default portal mappings so unmatched users get nothing
- planning your move to IPsec, because SSL VPN is gone from the 40F on FortiOS 7.6.3 and later
Questions or suggestions? Leave a comment below!
Top comments (0)