IPv6 support in CleanTalk Security for WordPress

    Recently, we wrote that we made IPv6 support in the antispam plugin . But not only spammers started using IPv6, for other types of attacks on sites, attackers also use them.

    We have implemented IPv6 support in the security plugin for WordPress . Updated methods for determining IP addresses, storing and transmitting information to the cloud.

    We had to teach the plugin to distinguish, standardize, look for subnets and store IPv6 addresses. Despite the mass of various ready-made solutions, I had to make my implementation and the main catch is that PHP can be built with various parameters, and indeed there may be an outdated version, so I had to do everything from scratch.

    As soon as the IP address gets to us, we check whether it is valid and its type.

    Then we determine whether it belongs to the IP frequency range or the CDN range (If the headers of specific CDNs exist). This was the main difficulty, since all this had to be implemented independently, and at the same time to remind ourselves what was happening.

    It was decided to make the search for subnets universal so that it can receive both IPv4 and IPv6 as input, and if desired, IPv7, if we survive. The only thing that is spelled out rigidly is the base of X-theta (octet for IPv4 and hexetat for IPv6). Naturally recursion ...

     /*
    	 * Check if the IP belong to mask.  Recursive.
    	 * Octet by octet for IPv4
    	 * Hextet by hextet for IPv6
    	 * @param ip string  
    	 * @param cird mixed (string|array of strings)
    	 * @param ip_type string
    	 * @param cird mixed (string|array of strings)
    	*/
    	static public function ip__mask_match($ip, $cidr, $ip_type = 'v4', $xtet_count = 0){
    		if(is_array($cidr)){
    			foreach($cidr as $curr_mask){
    				if(self::ip__mask_match($ip, $curr_mask, $ip_type)){
    					return true;
    				}
    			} unset($curr_mask);
    			return false;
    		}
    		if($ip_type == 'v4') $xtet_base = 8;
    		if($ip_type == 'v6') $xtet_base = 16;
    		// Calculate mask
    		$exploded = explode('/', $cidr);
    		// Exit condition
    		$xtet_end = ceil($exploded[1] / $xtet_base);
    		if($xtet_count == $xtet_end)
    			return true;
    		$mask = $exploded[1] - $xtet_base * $xtet_count >= 0 ? $xtet_base : $exploded[1] - $xtet_base * ($xtet_count - 1);
    		$mask = 4294967295 << ($xtet_base - $mask);
    		// Calculate first ip X-tet
    		$ip_xtet = explode($ip_type == 'v4' ? '.' : ':', $ip);
    		$ip_xtet = $ip_type == 'v4' ? $ip_xtet[$xtet_count] : hexdec($ip_xtet[$xtet_count]);
    		// Calculate first net X-tet
    		$net_xtet = explode($ip_type == 'v4' ? '.' : ':', $exploded[0]);
    		$net_xtet = $ip_type == 'v4' ? $net_xtet[$xtet_count] : hexdec($net_xtet[$xtet_count]);
    		$result = ($ip_xtet & $mask) == ($net_xtet & $mask);
    		if($result)
    			$result = self::ip__mask_match($ip, $cidr, $ip_type, $xtet_count + 1);
    		return $result;
    	}
    


    It should be noted that the function accepts only normalized IPv6 addresses and networks (a string or an array of network strings). For example, a network of Cloud Flare 2a06: 98c0 :: 0/29 will not work, it must be deployed in 2a06: 98c0: 0: 0: 0: 0: 0: 0/29

    Due to the fact that, from the local database firewall must choose addresses on the fly, with DB tools, not with PHP tools. The IPv6 address had to be divided into 4 columns, each of them in 32 bits, corresponds to one IPv4 address. Accordingly, with this structure, you can use the old sampling method, with binary operations.

    Also, changes were made to the Service Control Panel and databases, for the correct processing and display of information.

    Implemented IPv6 support for personal blacklists, security firewall and Traffic Control functions (IP blocking when a specified number of requests per unit time is reached).

    Also popular now: