From 3858fa25bf98f18036406a74190ede313bbab136 Mon Sep 17 00:00:00 2001 From: jano3 <jano@bob.co.za> Date: Wed, 29 Jan 2025 10:42:57 +0200 Subject: [PATCH] Add IP utils --- ip_utils/ip_utils.go | 166 +++++++++++++++++++++++++++++++++++++++++++ utils/utils.go | 1 + 2 files changed, 167 insertions(+) create mode 100644 ip_utils/ip_utils.go diff --git a/ip_utils/ip_utils.go b/ip_utils/ip_utils.go new file mode 100644 index 0000000..a72f734 --- /dev/null +++ b/ip_utils/ip_utils.go @@ -0,0 +1,166 @@ +package ip_utils + +import ( + "fmt" + "gitlab.bob.co.za/bob-public-utils/bobgroup-go-utils/errors" + "net" + "os" + "strings" +) + +// ==================================================================================================== +// region Payfast +// ==================================================================================================== + +// GetPayFastIPs returns a slice of string containing the current IP addresses +// associated with host names published by PayFast. +func getPayFastIPs() []string { + hostnames := []string{ + "www.payfast.co.za", + "w1w.payfast.co.za", + "w2w.payfast.co.za", + "sandbox.payfast.co.za", + "api.payfast.co.za", + "ips.payfast.co.za", + } + + ips := []string{} + + for _, v := range hostnames { + addresses, err := net.LookupIP(v) + if err != nil { + // Swallow and continue. + continue + } + + for _, a := range addresses { + ips = append(ips, a.String()) + } + } + + return ips +} + +func VerifyPayfastSourceIP(sourceIP string) bool { + ips := getPayFastIPs() + for _, v := range ips { + if v == sourceIP { + return true + } + } + + // If we got here, it means the lookup failed, so let's check the IP ranges as defined by Payfast + // Define the list of IP ranges as CIDR blocks - this is obtained from Payfast's documentation + ipRanges := []string{ + "197.97.145.144/28", + "41.74.179.192/27", + "102.216.36.0/28", + "102.216.36.128/28", + "144.126.193.139/32", + } + + // Now verify + if isValidIP(sourceIP, ipRanges) { + return true + } + + return false +} + +// endregion Payfast + +// ==================================================================================================== +// region Bob Pay +// ==================================================================================================== + +const ( + bobPayDevIP = "13.245.84.126" + bobPaySandboxIP = "13.246.115.225" + bobPayProdIP = "13.246.100.25" +) + +func VerifyBobPaySourceIP(sourceIP string) bool { + env := os.Getenv("ENVIRONMENT") + + switch env { + case "dev": + return sourceIP == bobPayDevIP + case "stage": + return sourceIP == bobPaySandboxIP + case "prod": + return sourceIP == bobPayProdIP + } + + return false +} + +// endregion Bob Pay + +// ==================================================================================================== +// region Cloudflare +// ==================================================================================================== + +func VerifyCloudflareSourceIP(sourceIP string) bool { + ipRanges := []string{ + "173.245.48.0/20", + "103.21.244.0/22", + "103.22.200.0/22", + "103.31.4.0/22", + "141.101.64.0/18", + "108.162.192.0/18", + "190.93.240.0/20", + "188.114.96.0/20", + "197.234.240.0/22", + "198.41.128.0/17", + "162.158.0.0/15", + "104.16.0.0/13", + "104.24.0.0/14", + "172.64.0.0/13", + "131.0.72.0/22", + } + + // Now verify + if isValidIP(sourceIP, ipRanges) { + return true + } + + return false +} + +// endregion Cloudflare + +// ==================================================================================================== +// region Helpers +// ==================================================================================================== + +func isValidIP(ipStr string, ipRanges []string) bool { + ip := net.ParseIP(ipStr) + if ip == nil { + return false + } + + for _, cidr := range ipRanges { + _, subnet, err := net.ParseCIDR(cidr) + if err != nil { + fmt.Println("Error parsing CIDR:", err) + continue + } + + if subnet.Contains(ip) { + return true + } + } + + return false +} + +func ValidateIPAddress(ipAddress string) (cleanedIPAddress string, err error) { + ipAddress = strings.ToLower(strings.TrimSpace(ipAddress)) + ip := net.ParseIP(ipAddress) + if ip == nil { + return "", errors.Error("invalid IP address") + } + return ipAddress, nil +} + +// endregion Helpers diff --git a/utils/utils.go b/utils/utils.go index 40bf5be..2c8d90b 100644 --- a/utils/utils.go +++ b/utils/utils.go @@ -308,6 +308,7 @@ func DetermineDaysLeft(fromDateLocal time.Time, toDateLocal time.Time) int { return int(math.Floor(toDate.Sub(fromDate).Hours() / 24)) } +// ValidateIPAddress in this package is deprecated. Use ip_utils.ValidateIPAddress instead. func ValidateIPAddress(ipAddress string) (cleanedIPAddress string, err error) { ipAddress = strings.ToLower(strings.TrimSpace(ipAddress)) ip := net.ParseIP(ipAddress) -- GitLab