In this post I would like to show you a scenario to use Google Cloud’s API with your Check Point CloudGuard instance to create or delete custom (static) routes.
How does Check Point handle Failover in Google Cloud
During your Check Point CloudGuard HA deployment, you may notice that there are some new routes created in each VPC where the instance is connected to, starting with: x-chkp-<VPC-NAME>-to-member-<a/b>.
Since there is no Layer2 network in cloud environments and the cluster has no VIP (Virtual IP), these routes will make sure that your traffic is always directed to the active member.
These are “high priority” routes according to the CloudGuard deployment documentation.
(sc1.checkpoint.com/documents/)
The integrated HA daemon is monitoring the cluster status of each member and if a failover occurs it will delete or create routes:
-
- If member A becomes the active member, it will create high priority routes that will direct all outbound traffic in the internal networks to itself.
Note: A lower priority number equals a higher priority for the route. - If member B becomes the active member, it will remove the high priority routes created by member A. The result is that existing, lower priority routes will be affected and route all outbound traffic in the internal networks to themselves.
- If member A becomes the active member, it will create high priority routes that will direct all outbound traffic in the internal networks to itself.
The routing changes are done with API calls to the GCP’s API service and the expected failover times are about 40 seconds (depending on the GCP API).
Why static routes?
In some scenarios you may have a VPN to your on-premise network or to a cloud proxy, e.g. Zscaler or Symantec WSS, and the traffic from your backend VPC needs to be routed into the VPN tunnel as shown in figure 1:
Let’s say you have a route based VPN connection and everything (0.0.0.0/0) is sent into the tunnel in Google Cloud towards your on-premise gateway.
Let’s also assume that on the peer site you just want to send your backend network 172.17.20.0/24 towards Google Cloud.
In this scenario, once you initiate a connection from your backend VPC into the tunnel, the packet arrives from the remote GW to its destination and the response packet goes all the way back into your frontend VPC. GCP is checking your routing table but cannot find a route for 172.17.20.0/24 pointing to the CloudGuard instances, so the packet will simply hit the 0.0.0.0/0 route towards the VPN. On the peer site, the gateway sees an incoming packet on the VPN interface but from an internal IP. Therefore the gateway will or should simply drop it as a spoofed packet because it is still the response packet.
To eliminate this back-and-forth routing, you need to create a static route in your frontend VPC for your backend network pointing to your CloudGuard instance.
You should implement the static routes exactly the same as the x-chkp routes with priority 1 pointing to member A and priority 2 to member B in your frontend VPC subnetwork:
– network 172.17.20.0/24 pointing to member A with priority 1
– network 172.17.20.0/24 pointing to member B with priority 2
Make sure that you name the routes with either “-a” or “-b” at the end to identify them quickly.
How to automate
The only thing we need to do now is to automatically check the cluster status and call the API to either delete or create priority 1 route to member A.
For this we are using two simple bash scripts running as a cronjob on the members.
You can use the following script for member „a“ and place it in the /bin folder or wherever you prefer.
This script checks if the status of member A is active or not. If the status is active, you need to check if there is a route pointing to this member for the backend network. If there is no route found, a new one is created.
Please make sure you replace the values marked with <> with your GCP values.
#!/bin/bash -f source /opt/CPshrd-<VERSION>/tmp/.CPprofile.sh #gets the hostname hostname=$(hostname) #gets the Member status status=$(cphaprob stat | grep local | awk '{print $5}' | cut -c 1-6) #gets the token bearer token=$(curl_cli -s http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token -H "Metadata-Flavor: Google" | jq '."access_token"') #gets the next hop instance from the route instance=$(curl_cli -s -H "Authorization: Bearer "$token https://www.googleapis.com/compute/v1/projects/<YOUR PROJECT NAME>/global/routes/<ROUTE NAME> --insecure | jq '."nextHopInstance"' | awk -F / '{print $NF}' | cut -d '"' -f 1) #gets the destination of the desired route destination=$(curl_cli -s -H "Authorization: Bearer "$token https://www.googleapis.com/compute/v1/projects/<YOUR PROJECT NAME>/global/routes/<ROUTE NAME> --insecure | jq -r '."destRange"') #defines the network range from your backend VPC network="172.17.20.0/24" #getting the zone the vm is running in zone=$(curl_cli -s http://metadata.google.internal/computeMetadata/v1/instance/zone -H "Metadata-Flavor: Google" |awk -F"/" '{print $4}') #log file log=/var/log/gcp_logs/log_$(date +"%Y_%m_%d").txt #old logs to remove (older than 3 days) old_log=$(find /var/log/gcp_logs -maxdepth 1 -type f -mtime +3 -name log_*.txt' -execdir rm -- '{}' \;) #if status is Active if [ $status == ACTIVE ] then #check if the route for the backend network already exists and pointing to this member if [ $instance == $hostname ] && [ $destination == $network ] then #if true, write into Log file echo "$(date +"%Y_%m_%d %H:%M") : route $network to $instance in $zone exists for <VPC NAME>" >> $log #remove old log files $old_log else #if false, create the route echo "$(date +"%Y_%m_%d %H:%M") : creating route for network $network to $hostname in $zone for <VPC NAME>" >> $log curl_cli -s -H "Authorization: Bearer "$token -X POST -d '{"destRange":"'$network'","name":"<ROUTE_NAME>","network":"global/networks/<VPC_NAME>","priority":"1","nextHopInstance":"https://www.googleapis.com/compute/v1/projects/<YOUR PROJECT NAME>/zones/'$zone'/instances/'$hostname'"}' https://www.googleapis.com/compute/v1/projects/<YOUR_PROJECT_NAME>/global/routes --insecure --header "Content-Type: application/json" >> $log fi fi exit
For the status of member B, the script below can be used. If member B is active, it will simply just delete the route to member A and the traffic will hit the priority 2 route. No following actions are required for the priority 2 route, as this will always remain and has no impact to the traffic at all if member B is not active.
Please make sure you replace the values marked with <>.
#!/bin/bash -f source /opt/CPshrd-<VERSION>/tmp/.CPprofile.sh hostname="<HOSTNAME_OF_MEMBER_A>" node=$(cphaprob stat | grep local | awk '{print $6}') status=$(cphaprob stat | grep local | awk '{print $5}' | cut -c 1-6) token=$(curl_cli -s http://169.254.169.254/computeMetadata/v1/instance/service-accounts/default/token -H "Metadata-Flavor: Google" | jq '."access_token"') instance=$(curl_cli -s -H "Authorization: Bearer "$get_token https://www.googleapis.com/compute/v1/projects/<PROJECT_NAME>/global/routes/<ROUTE_NAME_MEMBER_A> --insecure | jq '."nextHopInstance"' | awk -F / '{print $NF}' | cut -d '"' -f 1) destination=$(curl_cli -s -H "Authorization: Bearer "$get_token https://www.googleapis.com/compute/v1/projects/<PROJECT_NAME>/global/routes/<ROUTE_NAME_MEMBER_A> --insecure | jq -r '."destRange"') network="172.17.20.0/24" past=$(date +"%Y_%m_%d" --date="-3 days") zone="<ZONE_OF_MEMBER_A>" #log file log=/var/log/gcp_logs/log_$(date +"%Y_%m_%d").txt #old logs to remove (older than 3 days) old_log=$(find /var/log/gcp_logs -maxdepth 1 -type f -mtime +3 -name log_*.txt' -execdir rm -- '{}' \;) if [ $status == ACTIVE ] then if [ $instance == $hostname ] && [ $destination == $network ] then echo "$(date +"%Y_%m_%d %H:%M") : deleting existing route $network to inactive member" >> $log curl_cli -s -H "Authorization: Bearer "$get_token -X DELETE https://www.googleapis.com/compute/v1/projects/<PROJECT_NAME>/global/routes/<ROUTE_NAME_MEMBER_A> --insecure >> $log $old_log fi fi exit
After you have placed the script for both members you can add it to the crontab and run it for example every 30sec.
This is just an example to automate this specific scenario. Of course there are some other scenarios where you could use the API to automate your processes.
flying_squirrel
flying_squirrel ist Senior Security Engineer bei AVANTEC. Er beschäftigt sich am liebsten mit Fortinet und Check Point. Doch auch Lösungen wie Vectra und besonders die Arbeit mit APIs interessieren ihn sehr. Privat lässt alles rund um Home-Automatisierungen sein Herz höher schlagen.