Ran in to problems getting a VPN up and running between GCP and a FortiGate 60-E that was behind a NAT gateway (with ports udp/500 + udp/4500 forwarded). On the GCP side, these messages would show up in the logs:
remote host is behind NAT
generating IKE_AUTH response 1 [ N(AUTH_FAILED) ]
looking for peer configs matching GCP.VPN.GATEWAY.IP[%any]...203.0.113.77[192.168.1.1]
This error means that GCP connected to the Peer VPN gateway successfully, but it in the IKEv2 headers, it identified itself by the private IP rather than the expected public one. AWS is not picky about this, but with GCP, the Peer VPN gateway must identify itself by using the same external IP address of the NAT device.
Most vendors have long supported an option to manually override the IP address for such scenarios. In Cisco IOS or IOS-XE, this can be controlled in the IKEv2 profile with the identity local address option:
crypto ikev2 profile GCP_IKEV2_PROFILE
match address local interface GigabitEthernet1
identity local address MY.PUBLIC.IP.ADDRESS
authentication remote pre-share
authentication local pre-share
keyring local GCP_KEYRING
lifetime 36000
dpd 20 5 on-demand
!
With Palo Alto, this is configured in the IKE Gateway, Local Identification field:

For the sake of argument, we’ll say that CheckPoint uses the “Statically NATed IP” field to influence Local ID, although this doesn’t actually work.

Fortigate does offer “Local ID” field in version 6.4.6 and higher, under the Phase 1 proposal:

Seems nice and straightforward, but even after changing this setting, the VPN tunnel still won’t establish. Logs on the GCP end change slightly and now show this:
looking for peer configs matching GCP.VPN.GATEWAY.IP[%any]...203.0.113.77[203.0.113.77]
The private IP is no longer showing, so it seems the issue should be solved. Instead, GCP reports a “Peer not responding” message. The Fortigate actually reports Phase 1 success, waits a few seconds, and then starts the negotiation all over. So not very helpful.
I configured a test VPN between the FortiGate and a Palo Alto, which then gave a very specific and extremely useful error message:
IKE phase-1 negotiation is failed. When pre-shared key is used, peer-ID must be type IP address. Received type FQDN
Now this explains the problem! Even though the FortiGate is sending the correct IP address in the IKEv2 header, it’s being sent as the wrong identity type. The 5 identity types are listed in RFC 7815:
- ID_IPV4_ADDR = 32 bit IPv4 address
- ID_IPV6_ADDR = 128 bit IPv6 address
- ID_FQDN = DNS hostname
- ID_RFC822_ADDR = e-mail address
- ID_KEY_ID = octet stream
If Fortigate were smart, it would either default to IPv4 address type or auto-determine this based on the text inputted in to the field. But it seems to simply default to FQDN. Oddly, there is a CLI option called “localid-type” under the Phase1-interface that clear is intended to provide this functionality:
FGT60E1234567890 # config vpn ipsec phase1-interface
FGT60E1234567890 (phase1-interface) # edit gcp
FGT60E1234567890 (gcp) # set localid-type
auto Select ID type automatically.
fqdn Use fully qualified domain name.
user-fqdn Use user fully qualified domain name.
keyid Use key-id string.
address Use local IP address.
But, similar to CheckPoint, it just doesn’t work, and can be considered a broken feature.
Since GCP does not support FQDN authentication, VPNs between GCP and FortiGates behind a NAT are not possible at this time.
All you need to do to get this to work
is remove the local ID so that it is blank, then using the CLI execute the following command in your fortigate
execute update-eip
this will make your Fortigate present its public IP instead of the Natted Private one
LikeLike
there is a fix for this
simply leave the localID field empty
and using the CLI enter the following command into your Fortigate
execute update-eip
Your’e welcome!
LikeLike
Thanks for the post. I’ve run into the same issue with my Azure VM FortiGate that is trying to establish a tunnel to GCP. I now know that I don’t have to troubleshoot further and that I need to start looking into other options.
LikeLike