DEV Community

Cover image for How to Set Up an SSL VPN on a FortiGate 40F (Step-by-Step)
Abderrahim El Ouariachi
Abderrahim El Ouariachi

Posted on Edited on

How to Set Up an SSL VPN on a FortiGate 40F (Step-by-Step)

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"
Enter fullscreen mode Exit fullscreen mode

Some basics for the rest of the guide:

  • Each config ... end block opens and closes a configuration section.
  • Press Tab to complete a command and ? to list options.
  • show prints the changes you made in a section, and show full-configuration includes 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Why srcaddr "all" plus a group? In a user-based policy the group does the real filtering. all just 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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Confirm that the SSL VPN is listening:

diagnose sys tcpsock | grep 10443
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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>
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

Check the session on the firewall

get vpn ssl monitor
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode
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
Enter fullscreen mode Exit fullscreen mode

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)