FortiGate
FortiGate Next Generation Firewall utilizes purpose-built security processors and threat intelligence security services from FortiGuard labs to deliver top-rated protection and high performance, including encrypted traffic.
Hatibi
Staff
Staff
Article Id 255761
Description

 

This article will show a configuration example with a Hub and spoke topology where a FortiGate acting as an SSL VPN client will establish a tunnel with the SSL VPN server in order to allow users that are LAN connected behind the Spoke(client) to be tunneled through SSL VPN and be able to reach destinations on the Hub.

 

Scope

 

FortiOS v7.0.x and newer versions.

FortiGate SSL VPN client and Server configuration

 

Solution

 

For this case, following network example will be used:

 

 

Netdiagram.png

- In such environments, customers can have FortiGates acting as SSL VPN clients in remote Branch offices that connect to a main HUB FortiGate located in the Headquarters. All LAN-connected hosts in the Branch offices would then be able to access resources on the Remote network through Policies matching traffic for specific LAN destinations.

- The Spoke FortiGate will use PSK and a PKI client certificate to authenticate.

- Split routing will be used in order for only traffic matching the destination network 20.20.20.0/24 to be routed through the tunnel and the other traffic to go through the internet. Once the tunnel is established and proper policy matched we will verify with debugs the connection and see the injected route learned from the Server in the Spoke FortiGate.

- Both FortiGates used in this example are v7.0.11

 

1) Configuration of HUB FortiGate (Server in Headquarters).

 

a) Generate and Import the Server Certificate and CA (issuer) certificate in FortiGate.

 

To generate certificates in a Microsoft environment, follow the Kb article below which shows an example to create an EAP server certificate for FortiAuthenticator.

The same concept can be used to generate Server certificates for FortiGate or other endpoints:

https://community.fortinet.com/t5/FortiAuthenticator/Technical-Tip-How-to-issue-EAP-certificate-with...

 

In this scenario, the certificates and private keys have been generated using XCA certificate generation tool (openSSL frontend).

 

Server certificate (CN = client2.lab.net)

CA certificate (issuer) (CN = global.lab.net)

 

Go to System -> Certificates -> Create/Import.

Select 'Certificate'.

Import the Server certificate.


servercert.png

After it is imported the certificate will appear under 'Local Certificate'.

 

localcert.png

Go to System -> Certificates -> Create/Import.

Select 'CA Certificate'

Import CA certificate:

 

Ca_cert.png

 

The certificate will appear under 'Remote CA Certificate' named as CA_Cert_1 in case this was the first imported case.

 

CA_remote.png

b) Configure the Local user and PKIuser

 

In this case, a local use called 'client2' will be used, which will represent the SSL VPN Spoke FortiGate when the tunnel will be established.

 

local_user.png

 

To enable certificate authentication we will need to create a PKI user. This option is not available in the GUI but it will appear after we create the first user through CLI:

 

config user peer
    edit "pk1"
        set ca "CA_Cert_1"
        set subject "CN = client2.lab.net"
    next
end

The user 'pk1' has been created and the issuing CA has been defined, which was previously imported and the subject parameter matching the Subject field in the Certificate 'CN = client2.lab.net'

 

The entry will now be available on GUI:

 

pki.png

c) Create the SSLVPN portal and configure the SSL VPN settings

 

A new portal called 'testportal2' will be created and split tunneling based on Policy Destination will be enabled.

Leave other settings as default:

 

portal.png

 

Configure the SSL VPN settings and add portal mapping:

 

ssl1.png

ssl2.png

Additionally, an authentication rule will be configured for the portal adding the certificate authentication requirement and defining the 'client2':

 

config vpn ssl settings
    set servercert "client2.lab.net" 
    set tunnel-ip-pools "SSLVPN_TUNNEL_ADDR1"
    set tunnel-ipv6-pools "SSLVPN_TUNNEL_IPv6_ADDR1"
    set source-interface "port1"
    set source-address "all"
    set source-address6 "all"
    set default-portal "full-access"
        config authentication-rule
            edit 1
               set users "client2"
                set portal "testportal2"
                set client-cert enable
                set user-peer "pk1"
            next
        end
    end

 

d) Create the firewall policy with the destination the remote subnet 20.20.20.0/24.

 

policyHub.png

 

CLI config:


config firewall policy
    edit 1
        set name "sslvpn2"
        set uuid xx
        set srcintf "ssl.root"
        set dstintf "port2" <---- Lan interface of HUB.
        set action accept
        set srcaddr "all"
        set dstaddr "Internal2" <----- Address object Internal LAN network of Hub.
        set schedule "always"
        set service "ALL"
        set nat enable
        set users "client2" <------ FortiGate Client.
    next
end

 

2) Configuration of SPOKE FortiGate (Client in Branch office).

 

a) For the SPOKE configuration we will perform the same steps a) and b) identically with same parameters

 

Summarized:

 

- Import the Server certificate (CN = client2.lab.net).
- Import the CA certificate (issuer) (CN = global.lab.net).

- Configure Local user 'client2'.

- Configure PKI user 'pk1'.

 

config user peer
    edit "pk1"
        set ca "CA_Cert_1"
        set subject "CN = client2.lab.net"
    next
end

 

b) Configure the SSL VPN client.

 

In newer FOS v7.0.x there is an additional option in VPN > SSL VPN client.

Here, an SSL VPN tunnel interface has been created under the WAN(port1) of the Spoke FortiGate.

 

In the SSL VPN client configuration, the below settings have been created, where under the 'Serve' parameter, it will be necessary to specify the Public IP where the HUB FortiGate listens for connections.

 

sslvpn_client.png

CLI configuration:

 

config vpn ssl client
    edit "sslclient_to_srv"
        set interface "sslclient_port1"
        set user "client2"
        set psk ENC XXXXXX
        set peer "pk1"
        set server "X.X.X.X"
        set port 10443
        set certificate "client2.lab.net"
    next
end

 

c) Configure the Firewall policy.

 

Policy_spoke.png

 

CLI configuration:

 

edit 8
    set name "Policy_to_Server_ssl_tunnel"
    set uuid XX
    set srcintf "port2" <----- Lan interface Spoke.
    set dstintf "sslclient_port1"
    set action accept
    set srcaddr "all"
    set dstaddr "all"
    set schedule "always"
    set service "ALL"
    set nat enable
next

 

3) Validation of the configuration.

 

Once the configuration of the SSL VPN client on the SPOKE is finished and the Firewall policy is in place, the attempt to automatically establish the tunnel SPOKE <->HUB will be notified

 

a) Enabling the following debugs on Hub to verify what is happening:

 

diag debug reset

diag debug app sslvpn -1

diag debug app fnbamd -1

diag debug console timestamp enable

diag debug enable

 

Successful connection attempt:

 

2023-05-08 17:10:13 [3162:root:13]User Agent: FortiSSLVPN
2023-05-08 17:10:13 [3162:root:13]rmt_logincheck_cb_handler:1283 user 'client2' has a matched local entry.
2023-05-08 17:10:13 [3162:root:13]sslvpn_auth_check_usrgroup:2978 forming user/group list from policy.
2023-05-08 17:10:13 [3162:root:13]sslvpn_auth_check_usrgroup:3024 got user (1) group (0:0).
2023-05-08 17:10:13 [3162:root:13]sslvpn_validate_user_group_list:1890 validating with SSL VPN authentication rules (1), realm ().
2023-05-08 17:10:13 [3162:root:13]sslvpn_validate_user_group_list:1975 checking rule 1 cipher.
2023-05-08 17:10:13 [3162:root:13]sslvpn_validate_user_group_list:1983 checking rule 1 realm.
2023-05-08 17:10:13 [3162:root:13]sslvpn_validate_user_group_list:1994 checking rule 1 source intf.
2023-05-08 17:10:13 [3162:root:13]sslvpn_validate_user_group_list:2033 checking rule 1 vd source intf.
2023-05-08 17:10:13 [3162:root:13]sslvpn_validate_user_group_list:2526 rule 1 done, got user (1:1) group (0:0) peer group (0).
2023-05-08 17:10:13 [3162:root:13]sslvpn_validate_user_group_list:2534 got user (1:1) group (0:0) peer group (0).
2023-05-08 17:10:13 [3162:root:13]sslvpn_validate_user_group_list:2876 got user (1:1), group (0:0) peer group (0).
2023-05-08 17:10:13 [3162:root:13]fam_cert_send_req:1109 do certificate peer check first(2).
2023-05-08 17:10:13 [3162:root:13]fam_cert_send_req:1181 doing certificate checking for 1 peer(s).
2023-05-08 17:10:13 [2341] handle_req-Rcvd auth_cert req id=691969652, len=1101, opt=0
2023-05-08 17:10:13 [974] __cert_auth_ctx_init-req_id=691969652, opt=0
2023-05-08 17:10:13 [103] __cert_chg_st- 'Init'
2023-05-08 17:10:13 [140] fnbamd_cert_load_certs_from_req-1 cert(s) in req.
2023-05-08 17:10:13 [661] __cert_init-req_id=691969652
2023-05-08 17:10:13 [710] __cert_build_chain-req_id=691969652
2023-05-08 17:10:13 [257] fnbamd_chain_build-Chain discovery, opt 0x13, cur total 1
2023-05-08 17:10:13 [273] fnbamd_chain_build-Following depth 0
2023-05-08 17:10:13 [308] fnbamd_chain_build-Extend chain by system trust store. (good: 'CA_Cert_1')
2023-05-08 17:10:13 [273] fnbamd_chain_build-Following depth 1
2023-05-08 17:10:13 [287] fnbamd_chain_build-Self-sign detected.
2023-05-08 17:10:13 [99] __cert_chg_st- 'Init' -> 'Validation'
2023-05-08 17:10:13 [831] __cert_verify-req_id=691969652
2023-05-08 17:10:13 [832] __cert_verify-Chain is complete.
2023-05-08 17:10:13 [457] fnbamd_cert_verify-Chain number:2
2023-05-08 17:10:13 [471] fnbamd_cert_verify-Following cert chain depth 0
2023-05-08 17:10:13 [533] fnbamd_cert_verify-Issuer found: CA_Cert_1 (SSL_DPI opt 1)
2023-05-08 17:10:13 [471] fnbamd_cert_verify-Following cert chain depth 1
2023-05-08 17:10:13 [675] fnbamd_cert_check_group_list-checking group with name 'pk1'
2023-05-08 17:10:13 [490] __check_add_peer-check 'pk1'
2023-05-08 17:10:13 [366] peer_subject_cn_check-Cert subject 'CN = client2.lab.net, CN = client2.lab.net'
2023-05-08 17:10:13 [294] __RDN_match-Checking 'CN' val 'client2.lab.net' -- match.
2023-05-08 17:10:13 [324] __cert_subject_RDN_compare-Total matched RDNs in cert: 1
2023-05-08 17:10:13 [391] peer_subject_cn_check-Subject is good.
2023-05-08 17:10:13 [497] __check_add_peer-'pk1' check ret:good
2023-05-08 17:10:13 [612] __peer_user_clear_unmatched-Clear all user(s) other than 'pk1'
2023-05-08 17:10:13 [631] __peer_user_clear_unmatched-
2023-05-08 17:10:13 [191] __get_default_ocsp_ctx-def_ocsp_ctx=(nil), no_ocsp_query=0, ocsp_enabled=0
2023-05-08 17:10:13 [738] fnbamd_cert_check_group_list-Peer users
2023-05-08 17:10:13 [741] fnbamd_cert_check_group_list- 'pk1' ('N/A','N/A')
2023-05-08 17:10:13 [867] __cert_verify_do_next-req_id=691969652
2023-05-08 17:10:13 [99] __cert_chg_st- 'Validation' -> 'Done'
2023-05-08 17:10:13 [912] __cert_done-req_id=691969652
2023-05-08 17:10:13 [1652] fnbamd_auth_session_done-Session done, id=691969652
2023-05-08 17:10:13 [957] __fnbamd_cert_auth_run-Exit, req_id=691969652
2023-05-08 17:10:13 [1689] create_auth_cert_session-fnbamd_cert_auth_init returns 0, id=691969652
2023-05-08 17:10:13 [1608] auth_cert_success-id=691969652
2023-05-08 17:10:13 [1059] fnbamd_cert_auth_copy_cert_status-req_id=691969652
2023-05-08 17:10:13 [1067] fnbamd_cert_auth_copy_cert_status-Matched peer user 'pk1'
2023-05-08 17:10:13 [833] fnbamd_cert_check_matched_groups-checking group with name 'pk1'
2023-05-08 17:10:13 [895] fnbamd_cert_check_matched_groups-matched
2023-05-08 17:10:13 [1098] fnbamd_cert_auth_copy_cert_status-Leaf cert status is unchecked.
2023-05-08 17:10:13 [1186] fnbamd_cert_auth_copy_cert_status-Cert st 2c0, req_id=691969652
2023-05-08 17:10:13 [216] fnbamd_comm_send_result-Sending result 0 (nid 672) for req 691969652, len=2149
2023-05-08 17:10:13 [3162:root:13]__auth_cert_cb:895 certificate check OK.
2023-05-08 17:10:13 [3162:root:13]__auth_cert_cb:912 certificate check OK, matched peer [pk1].
2023-05-08 17:10:13 2023-05-08 17:10:13 [1553] destroy_auth_cert_session-id=691969652
2023-05-08 17:10:13 [3162:root:13]sslvpn_update_user_group_list:1720 Remove user(s) and group(s) do not set matched peer [pk1].
[1032] fnbamd_cert_auth_uninit-req_id=691969652
2023-05-08 17:10:13 2023-05-08 17:10:13 [131] fnbamd_peer_ctx_free-Freeing peer ctx 'pk1'
[3162:root:13]sslvpn_update_user_group_list:1724 got user (1:1), group (0:0) peer group (0) after update.
2023-05-08 17:10:13 [3162:root:13]sslvpn_authenticate_user:183 authenticate user: [client2]
2023-05-08 17:10:13 [3162:root:13]sslvpn_authenticate_user:197 create fam state
2023-05-08 17:10:13 [3162:root:13]user 'client2' uses 2FA: ctx->peer_two_factor = 0, ctx->peer_name.peername = 1, ctx->is_two_factor = 0
2023-05-08 17:10:13 [3162:root:13]fam_auth_send_req:882 found node client2:1:pk1, valid:1
2023-05-08 17:10:13 [3162:root:13][fam_auth_send_req_internal:426] Groups sent to FNBAM:
2023-05-08 17:10:13 [3162:root:13]group_desc[0].grpname = client2
2023-05-08 17:10:13 [3162:root:13][fam_auth_send_req_internal:438] FNBAM opt = 0X301420
2023-05-08 17:10:13 local auth is done with user 'client2', ret=0
2023-05-08 17:10:13 [3162:root:13]fam_auth_send_req_internal:514 fnbam_auth return: 0
2023-05-08 17:10:13 [3162:root:13][fam_auth_send_req_internal:539] Authenticated groups (1) by FNBAM with auth_type (1):
2023-05-08 17:10:13 [3162:root:13]Received: auth_rsp_data.grp_list[0] = 16777218
2023-05-08 17:10:13 [3162:root:13][fam_auth_send_req_internal:652] The user client2 is authenticated.
2023-05-08 17:10:13 [3162:root:13]Auth successful for user [client2] with matched user-peer [pk1]
2023-05-08 17:10:13 [3162:root:13]fam_do_cb:665 fnbamd return auth success.
2023-05-08 17:10:13 [3162:root:13]SSL VPN login matched rule (1).
2023-05-08 17:10:13 [3162:root:13]User Agent: FortiSSLVPN
2023-05-08 17:10:13 [3162:root:13]rmt_web_session_create:1209 create web session, idx[0]
2023-05-08 17:10:13 [3162:root:13]login_succeeded:536 redirect to hostcheck
2023-05-08 17:10:13 [3162:root:13]User Agent: FortiSSLVPN
2023-05-08 17:10:13 [3162:root:13]deconstruct_session_id:709 decode session id ok, user=[client2], group=[],authserver=[],portal=[testportal2],host[X.X.X.Y],realm=[],csrf_token=[B0FEE0F19A14662E198D8689F019133D],idx=0,auth=1,sid=27f04e3b,login=1683558613,access=1683558613,saml_logout_url=no,pip=no,grp_
info=[ATJgjh],rmt_grp_info=[]
2023-05-08 17:10:13 [3162:root:13]deconstruct_session_id:709 decode session id ok, user=[client2], group=[],authserver=[],portal=[testportal2],host[X.X.X.Y],realm=[],csrf_token=[B0FEE0F19A14662E198D8689F019133D],idx=0,auth=1,sid=27f04e3b,login=1683558613,access=1683558613,saml_logout_url=no,pip=no,grp_
info=[ATJgjh],rmt_grp_info=[]
2023-05-08 17:10:13 [3162:root:13]deconstruct_session_id:709 decode session id ok, user=[client2], group=[],authserver=[],portal=[testportal2],host[X.X.X.Y],realm=[],csrf_token=[B0FEE0F19A14662E198D8689F019133D],idx=0,auth=1,sid=27f04e3b,login=1683558613,access=1683558613,saml_logout_url=no,pip=no,grp_
info=[ATJgjh],rmt_grp_info=[]
2023-05-08 17:10:13 [3162:root:13]req: /remote/fortisslvpn_xml?dual_stack=1
2023-05-08 17:10:13 [3162:root:13]deconstruct_session_id:709 decode session id ok, user=[client2], group=[],authserver=[],portal=[testportal2],host[X.X.X.Y],realm=[],csrf_token=[B0FEE0F19A14662E198D8689F019133D],idx=0,auth=1,sid=27f04e3b,login=1683558613,access=1683558613,saml_logout_url=no,pip=no,grp_
info=[ATJgjh],rmt_grp_info=[]
2023-05-08 17:10:13 [3162:root:13]deconstruct_session_id:709 decode session id ok, user=[client2], group=[],authserver=[],portal=[testportal2],host[X.X.X.Y],realm=[],csrf_token=[B0FEE0F19A14662E198D8689F019133D],idx=0,auth=1,sid=27f04e3b,login=1683558613,access=1683558613,saml_logout_url=no,pip=no,grp_
info=[ATJgjh],rmt_grp_info=[]
2023-05-08 17:10:13 [3162:root:13]rmt_fortisslvpn_xml_cb_handler:1139 Client requests dual stack tunnel
2023-05-08 17:10:13 [3162:root:13]sslvpn_reserve_dynip:1476 tunnel vd[root] ip[X.X.X.X] app session idx[0]
2023-05-08 17:10:13 [3162:root:13]form_ipv4_pol_split_tunnel_addr:79 Matched policy (id = 1) to add ipv4 split tunnel routing address
2023-05-08 17:10:13 [3162:root:13]req: /remote/sslvpn-tunnel2
2023-05-08 17:10:13 [3162:root:13]sslvpn_tunnel2_handler,59, Calling rmt_conn_access_ex.
2023-05-08 17:10:13 [3162:root:13]deconstruct_session_id:709 decode session id ok, user=[client2], group=[],authserver=[],portal=[testportal2],host[X.X.X.Y],realm=[],csrf_token=[B0FEE0F19A14662E198D8689F019133D],idx=0,auth=1,sid=27f04e3b,login=1683558613,access=1683558613,saml_logout_url=no,pip=no,grp_
info=[ATJgjh],rmt_grp_info=[]
2023-05-08 17:10:13 [3162:root:13]normal tunnel2 request received.
2023-05-08 17:10:13 [3162:root:13]sslvpn_tunnel2_handler,173, Calling tunnel2.
2023-05-08 17:10:13 [3162:root:13]tunnel2_enter:1289 0x7fa7f7f56500:0x7fa7f7322000 sslvpn user[client2],type 1,logintime 0 vd 0 vrf 0
2023-05-08 17:10:13 [3162:root:13]tun dev (ssl.root) opened (33)
2023-05-08 17:10:13 [3162:root:13]fsv_associate_fd_to_ipaddr:2022 associate X.X.X.X to tun (ssl.root:33)
2023-05-08 17:10:13 [3162:root:13]proxy arp: scanning 6 interfaces for IP X.X.X.X
2023-05-08 17:10:13 [3162:root:13]Cannot determine ethernet address for proxy ARP
2023-05-08 17:10:13 [3162:root:13]Will add auth policy for policy 1 for user client2:
2023-05-08 17:10:13 [3162:root:13]Add auth logon for user client2:, matched group number 1

 

b) Validation on HUB FortiGate.

 

Go to Dashboard -> Network -> SSL VPN.

It will be possible to see the SSL VPN spoke tunnel represented by Local user 'client2'.

 

Client_validation.png

 

c) Route injection validation on SPOKE FortiGate.

 

In the Branch office FortiGate, it is possible to verify that it has dynamically added a route to the remote subnet 20.20.20.0/24 learned from the HUB.

 

firewall # get router info routing-table database
Codes: K - kernel, C - connected, S - static, R - RIP, B - BGP
O - OSPF, IA - OSPF inter area
N1 - OSPF NSSA external type 1, N2 - OSPF NSSA external type 2
E1 - OSPF external type 1, E2 - OSPF external type 2
i - IS-IS, L1 - IS-IS level-1, L2 - IS-IS level-2, ia - IS-IS inter area
> - selected route, * - FIB route, p - stale info

Routing table for VRF=0
S *> 0.0.0.0/0 [10/0] via Y.Y.Y.Y, port1, [1/0]
C *> 10.10.10.0/24 is directly connected, port3
C *> X.X.X.X/20 is directly connected, port1
C *> X.X.X.X/32 is directly connected, sslclient_port1
S *> 20.20.20.0/24 [10/0] is directly connected, sslclient_port1, [1/0]
C *> X.X.X.X/32 is directly connected, VPN
C *> 192.168.10.0/24 is directly connected, port2


In the same manner, it is possible to have multiple other branches which are possible to reference as 'client3' or 'branch3' and so on in a Hub and Spoke topology.

 

More details and options for this type of setup are provided in the Fortinet documentation below:

https://docs.fortinet.com/document/fortigate/7.0.9/administration-guide/508779/fortigate-as-ssl-vpn-...