Dual stack FortiClient VPN’s are not fun; and a default massive security hole exists that I’m guessing most CISO’s/CIO’s don’t pay attention to since many people still barely know what IPv6 is. I’m going to explain this security issue first, because the fix is setting up dual stack VPN access, even if you don’t intend to offer IPv6 service, so if you just came for the setup, scroll down past my rant.
In any case, here’s the scenario:
- FortiGate protecting something. Has current software on it; 5.4.3 at the time of this writing (Feb 2017)
- End user has a device with FortiClient software on it; current software version 5.4.1.0840 (Feb 2017) for Windows client. Their clients for other platforms are dated compared to Windows, so no reason to assume those behave differently.
- End user has FortiClient VPN access to FortiGate firewall for IPv4 service and access to protected network/data
- FortiGate VPN profile is intentionally configured to NOT permit split tunneling
- FortiGate policy is intentionally configured to NOT permit VPN users from talking to internet
So here we go, most firewall admins, and their superiors, set things up as described above in order to protect the environment from a remote VPN user from allowing unauthorized access to the protected network via their computer. With split tunneling disabled, and policy blocking access to the internet through the firewall, one may think all is well since the split tunneling block and policy block would not permit malware or similar things on the end user’s computer from talking to the computer over the internet at the same time the VPN is connected.
In theory, that would be accurate, if the user only has an IPv4 connection the internet, AND the FortiClient is working as intended.
The Backdoor Into Your Network
Well, that all changes if the user has IPv6. If the end user is connected to an ISP that doesn’t suck, they will have both IPv4 and IPv6 internet connectivity, and FortiClient / FortiGate as configured above, do nothing to prevent the other protocol from simultaneous use. So, lets say I’ve hacked your end user’s computer, and I’m watching it via IPv6. If they happily VPN into your protected environment, and hey, they even use two factor, because you’re extra precautious, your split tunnel block and policy kick in, then, ooops…. ol’ FortiClient will do absolutely nothing about my IPv6 session with their computer. I will continue watching what they do, and can now start digging around in your network through their computer, which is now connected to the protected area.
The Fix (or how to configure dual stack VPN if that’s all you’re here for)
The fix to keeping intruders that control your users’ computers out of your network while users are VPN’d in is to set up dual stack addressing for your VPN users, whether you have IPv6 service, or intend to offer it, or not. You MUST give your end user an IPv6 address so that you can then enforce no IPv6 split tunneling and no IPv6 internet access.
Fortinet does not make this easy, in fact it’s downright difficult to stumble into the right configuration to even allow you to do this. I’ll also point out that this specifically will NOT work if your remote users are not using “Mode Config” where the firewall hands them addresses from a pre-defined range. Why not? Because the f’ing FortiClient doesn’t even have boxes to let you put in static IPv6 addresses, or radio buttons to select to use DHCPv6. It may be possible to add these things manually via backup, xml file edit, import, similar to what you have to do on MacOS to get the correct tunnel settings installed, but I haven’t experimented with that yet.
So, I guess we’re doing Mode Config… First thing, define the VPN, normal setup, add IPv4 and IPv6 ranges for connected users:
If you need to, and you shouldn’t, you can use non-public IPv6 space as a last resort, but you can get address space for I think free, so there’s no reason to do that. You can also always change it later. If you’re only doing this for security reasons, then it really doesn’t matter what space you use, even if you use the IPv6 documentation prefix like I did above (RFC 3849), because you’re not going to have IPv6 on any of your firewall’s interfaces, so the space is only going to exist between your VPN client and your FortiGate and be unable to go anywhere. Just make it easier on yourself and get your own real space now though; carve it up, assign, don’t let it go anywhere via policy.
Okay, so the above gets saved, and you’re thinking hey, I’m good now, I added v6 space so my FortiClients will get some of that when they connect. Nope; without an IPv6 phase 2 selector, the client is going to get nothing related to IPv6 from the server, nor is the enforcement of no IPv6 split tunneling going to occur, so nothing changes.
Well, how do you add an IPv6 phase 2 selector given there’s no “Add:” button next to Phase 2 Selectors? Well that’s a problem. This is where you stupidly have to take the VPN definition out of mode config:
Turn off that box, click the check box. Ooooh, look what we have now, and add button. Click add, and give yourself a new v6 subnet local and remote of ::/0 since we’re just going to be doing mode config in a few minutes anyway:
Save, now you should see this when you edit your VPN profile:
Okay, now we’re getting somewhere. Now you need to re-edit the first section and turn Mode Config back on:
Now, finally, when a VPN user connects, they will be talking to the firewall over IPv4, they will receive both an IPv4 and IPv6 address from your relevant ranges, split tunneling is disabled for both protocols so they’ll only be sending traffic to and from the firewall, assuming FortiClient is doing its job properly, and your policy will be blocking both IPv4 and IPv6 traffic from going to the internet.
I assume a similar situation would exist if you had a v6-only VPN and a user connected from a network with IPv4 and IPv6, i.e. nearly any network, so you’d probably need to apply the same recommended config to add IPv4 to prevent the same issue.
Finally, if you decided to use real IPv6 addresses because you have real IPv6 service, then simply add the necessary policy to let your user get to what they need to over v6.
CLI stuff for cool people
If you’re curious what occurred behind the scenes so that you can do the same change via CLI and not deal with the web interface’s BS, here’s my resulting config which you’ll need to adjust as needed (shared secret, interface, parameters, addresses, etc):
config vpn ipsec phase1-interface edit "DualStack VPN" set type dynamic set interface "port1" set keylife 7200 set mode aggressive set peertype one set mode-cfg enable set proposal aes256-sha256 set dpd on-idle set comments "VPN Staff" set dhgrp 14 set xauthtype auto set authusrgrp "VPN Staff" set peerid "asdf" set ipv4-start-ip 192.0.2.1 set ipv4-end-ip 192.0.2.10 set dns-mode auto set ipv6-start-ip 2001:db8::1 set ipv6-end-ip 2001:db8::10 set psksecret ENC adsf next end config vpn ipsec phase2-interface edit "DualStack VPN" set phase1name "DualStack VPN" set proposal aes256-sha256 set dhgrp 14 set keepalive enable set keylifeseconds 3600 next edit "DualStack VPN v6" set phase1name "DualStack VPN" set proposal aes256-sha256 set dhgrp 14 set keepalive enable set src-addr-type subnet6 set dst-addr-type subnet6 set keylifeseconds 3600 next end
That will hopefully get you to the right place without the GUI mess. Maybe. 🙂