<?php

// Example durucuk@testserver:~$ whois -h whois.durukanbal.com test.com

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

// önceliği 10 mysqli senbolinden önce yüklenmesi gerek
if ( extension_loaded ( "mysqlnd" ) === FALSE ) 
{
	if ( dl ( "mysqlnd.so" ) === FALSE )
	{
		die ( "Ölümcül hata mysqlnd senbolü yüklenemedi !!!" );
	}
}
// önceliği 20
if ( extension_loaded ( "mysqli" ) === FALSE ) 
{
    if ( dl ( "mysqli.so" ) === FALSE )
	{
		die ( "Ölümcül hata mysqli senbolü yüklenemedi !!!" );
	}
}
// önceliği 10
if ( extension_loaded ( "pcntl" ) === FALSE ) 
{
    if ( dl ( "pcntl.so" ) === FALSE )
	{
		die ( "Ölümcül hata pcntl senbolü yüklenemedi !!!" );
	}
}

/*
if (!extension_loaded('pdo_mysql')) {
    dl('pdo_mysql.so');
}
*/

// Önbellek dizini kontrol ediliyor, eğer yoksa oluşturuluyor
if ( file_exists ( "/var/cache/MasterWhoisServer" ) === FALSE ) 
{
    mkdir ( "/var/cache/MasterWhoisServer", 0777, TRUE );
}

// $host = '0.0.0.0'; // Dinlemek için localhost
$host = '::'; // Dinlemek için localhost IPv6 ve IPv4 Ortak trafik
$port = 43; // Dinlemek için localport

$sock = socket_create 
(
	AF_INET6, 
	SOCK_STREAM, 
	SOL_TCP
);

if ( $sock === FALSE ) 
{
    echo "socket_create() failed: reason: " . socket_strerror ( socket_last_error() ) . "\n";
}

// 10 saniye boyunca karşıdan yanıt gelmese timeout
socket_set_option
(
	$sock, 
	SOL_SOCKET, 
	SO_RCVTIMEO, 
	array
	(
		'sec' => 10, 
		'usec' => 0
	)
);

// 10 saniye boyunca karşıya veri yazılmassa dinlemiyordur buda deadlock'a neden olur
socket_set_option
(
	$sock, 
	SOL_SOCKET, 
	SO_SNDTIMEO, 
	array
	(
		'sec' => 10, 
		'usec' => 0
	)
);


// IPv6 Trafiğinin ve IPv4 Trafiğinin ortak olarak dinlenmesi gerektiğini belirtir
// Son parametre 0 olması ortak Trafiği 1 olarak ayarlanması sadece IPv6 Trafiği temsil eder.
socket_set_option
(
	$sock, 
	IPPROTO_IPV6, 
	IPV6_V6ONLY, 
	FALSE
);

// Servis kapandığında portun bekleme durumuna geçmeden yanıt vermesi için eklendi
socket_set_option
(
	$sock, 
	SOL_SOCKET, 
	SO_REUSEADDR, 
	TRUE
);

// Soketi belirli bir IP ve porta bağla ve işletim sistemin onayını al
if ( socket_bind ( $sock, $host, $port ) === FALSE )
{
	die ( "Soket bağlantısı başarısız: " . socket_strerror ( socket_last_error() ) . "\n" );
}

// Soketi dinlemeye başla ve /proc/sys/net/core/somaxconn daki maxumum backlog değerini al
socket_listen ( $sock, SOMAXCONN );

// Whois Server Yaşam döngüsü
while ( TRUE )
{
    // İstemci bağlantılarından herhangi birini kabul et
    $client = socket_accept ( $sock );

	if ( $client === FALSE )
	{
		continue;
	}
	
	
	$pid = pcntl_fork();
	
	
	if ( $pid == -1 )
	{
        // Fork işlemi başarısız oldu ana sürec yeni sürece geçmek zorunda
		// Bu durum saldırı geldiğini veya server kaynağının yetersiz olduğu gösterir
		$result = "The server is very busy, please try again later.";
		socket_write ( $client, $result, strlen ( $result ) );
		socket_close ( $client );
		continue;
    }
	else if ( $pid > 0 )
	{
		// Ana süreç yeni accept için var olan süreci aktarak işlemi sonlandırı
		// bu durum backlog düşürmek için verimli sunucu kapesitesi kullanımı için verimsizdir
		socket_close ( $client );
	}
	else if ( $pid == 0 )
	{
		
		if ( CheckMemory ( 100 ) === TRUE )
		{
			
		}
		else if ( CheckMemory ( 100 ) === FALSE )
		{
			socket_close ( $client );
			continue;
		}
		
		// Cocuk sürec burda görev alır ana sürecten bağımsız olarak kendi işlemlerini yürütür
		// İstemciden domain adını al
		$ClientVerisi = socket_read ( $client, 1024 );
		
		if ( $ClientVerisi === FALSE )
		{
			// OKUMA HATASI veya DEADLOCK
			// Belirtilen süre içerisinde veriyi vermiyor
			// Slowsloris attağı yapıyor olabilir veya internet bağlantısı problemi
			// oluşmuş olabilir
			
			// $errorCode = socket_last_error($client);
			// $errorMsg = socket_strerror($errorCode);
			socket_close ( $client );
			
			// Çocuk süreci tamamlandı
			exit(0);
		}
		
		$domain = trim ( $ClientVerisi );
		
		$DomainSubFlag = FALSE;
		
		// Gelen değer gerçekten bir domain adresimi kontrol edelim
		if ( filter_var ( $domain, FILTER_VALIDATE_DOMAIN, FILTER_FLAG_HOSTNAME ) === FALSE )
		{
			$DomainSubFlag = FALSE;
		}
		else
		{
			// $domain = "a.a.a.aaaa.aa.net";
			$parts = explode ( '.', $domain );

			// Eğer domain en az iki parçadan oluşuyorsa (ana domain ve TLD)
			if ( count ( $parts ) >= 2 ) 
			{
				$domain = $mainDomain = $parts [ count ( $parts ) - 2 ] . '.' . $parts [ count ( $parts ) - 1 ];
				// echo $mainDomain;  // Bu örnekte "aa.net" çıktısını alacaksınız.
				$DomainSubFlag = TRUE;
			} 
			else 
			{
				// Tek parçadan oluşanlar bu alana düşer test.com için test gibi veya com gibi
				// echo "Geçersiz domain!";
				$DomainSubFlag = FALSE;
			}
		}
		
		if ( $DomainSubFlag == FALSE )
		// if ( TRUE ) // Pass geç
		{
			// $domain adresinde domain adı yok anlaşılamayan bir değer
			$whois_data = "The requested item could not be found in the database!\r\n";
			
			socket_write 
			( 
				$client, 
				$whois_data, 
				strlen ( $whois_data ) 
			);
			
			$domain = FALSE;
			
			socket_close ( $client );
			continue;
		}

		$cacheFile = "/var/cache/MasterWhoisServer/" . md5 ( $domain ) . ".txt";
		
		// Eğer önbellek dosyası mevcutsa ve son değiştirilme tarihi 1 saatten daha eski değilse
		if 
		( 
			file_exists ( $cacheFile ) 
			AND 
			( 
				filemtime ( $cacheFile ) > ( time() - ( 60 * 60 * 1 ) ) 
			) 
		) 
		{
			$result = file_get_contents ( $cacheFile );
		} 
		else 
		{
			// Veri önbellekte bulunamadı, bu nedenle işlemi yap ve önbelleğe ekle
			
			// Veritabanı bağlantı bilgileri
			$host	  = getenv ( 'DB_IP_HOST' ); // DB01 SQL Server
			$user     = getenv ( 'DB_USERNAME' );
			$password = getenv ( 'DB_PASSWORD' );
			$dbname   = getenv ( 'DB_DBNAME' );
			
			// Veritabanı bağlantısı
			$baglanti = new mysqli ( $host, $user, $password, $dbname );

			// Bağlantı hatası kontrolü
			if ( $baglanti->connect_error ) 
			{
				die ( "Bağlantı hatası: " . $baglanti->connect_error );
			}
			
			// Karekter kodlamasını değiştirmek
			$baglanti->set_charset("utf8");
			
			// SQL sorgusu
			$sql = 
			"
				SELECT 
					*
				FROM 
					`whois-db`.cs_whois_server_domain_information
				WHERE 
					item_name = '".$domain."'
				LIMIT 1
			";
			$result = $baglanti->query ( $sql );

			if ( $result->num_rows > 0 ) 
			{
				// Verileri çekme
				while ( $row = $result->fetch_assoc() ) 
				{
					$datetimeUpdateTime = new DateTime ( $row [ "item_update_time" ] );
					$datetimeCreateTime = new DateTime ( $row [ "item_create_time" ] );
					$datetimeExpiryTime = new DateTime ( $row [ "item_expiry_time" ] );
					
					$whois_data = "Domain Name: " . strtoupper ( $row [ "item_name" ] ) ."\r\n";
					$whois_data .= "Registry Domain ID: " . $row [ "item_identity" ] . "\r\n";
					$whois_data .= "Registrar WHOIS Server: " . $row [ "item_whois_server" ] . "\r\n";
					$whois_data .= "Registrar URL: " . $row [ "item_registrar_url" ] . "\r\n";
					$whois_data .= "Updated Date: " . $datetimeUpdateTime->format ( 'Y-m-d\TH:i:s\Z' ) . "\r\n";
					$whois_data .= "Creation Date: " . $datetimeCreateTime->format ( 'Y-m-d\TH:i:s\Z' ) . "\r\n";
					$whois_data .= "Registry Expiry Date: " . $datetimeExpiryTime->format ( 'Y-m-d\TH:i:s\Z' ) . "\r\n";
					$whois_data .= "Registrar: " . $row [ "item_registrar" ] . "\r\n";
					$whois_data .= "Registrar IANA ID: " . $row [ "item_iana_id" ] . "\r\n";
					$whois_data .= "Registrar Abuse Contact Email: " . $row [ "item_abuse_contact_email" ] . "\r\n";
					$whois_data .= "Registrar Abuse Contact Phone: " . $row [ "item_abuse_phone_number" ] . "\r\n";
					
					foreach ( json_decode ( $row [ "item_status" ], TRUE ) as $index => $data )
					{
						$whois_data .= "Domain Status: " . $data . "\r\n";
					}
					
					foreach ( json_decode ( $row [ "item_nameservers" ], TRUE ) as $index1 => $data1 )
					{
						$whois_data .= "Name Server: " . $data1 . "\r\n";
					}
					
					$whois_data .= "DNSSEC: " . $row [ "item_dnssec" ] . "\r\n";
					$whois_data .= "URL of the ICANN Whois Inaccuracy Complaint Form: " . $row [ "item_whois_inaccuracy_url" ] . " \r\n";
					$whois_data .= ">>> Last update of whois database: " . date ( "Y-m-d\TH:i:s\Z" ) . " <<< \r\n";
					
				}
				
				// Veriyi bu alan içerisine kayıt et
				// $whois_data = "The requested item could not be found in the database!\r\n";
			} 
			else 
			{
				// The requested item could not be found in the database!\r\n
				// echo "Sonuç bulunamadı!";
				$whois_data = "The requested item could not be found in the database!\r\n";
			}

			// Bağlantıyı kapatma
			$baglanti->close();
			
			$result = $whois_data;
			file_put_contents ( $cacheFile, $result, LOCK_EX );
		}
		
		// Veriyi istemciye gönder
		socket_write ( $client, $result, strlen ( $result ) );

		// İstemci bağlantısını kapat
		socket_close ( $client );
		
		// çocuk süreci tamamlandı
		exit(0);
		
	} // pid = 0
}

// Ana Soketi kapat
socket_close ( $sock );

exit();


function CheckMemory ( $minFreeMemoryMB = 100 ) 
{
	$maxSocketLimit = intval
	(
		shell_exec
		(
			"/usr/bin/netstat -anop | wc -l"
		)
	);
	
	if ( $maxSocketLimit >= 3000 )
	{
		return FALSE;
	}
	
	
    // Sistemdeki boş belleği al (MB cinsinden)
    $freeMemory = intval 
	( 
		shell_exec 
		(
			"free -m | awk 'NR==2{print $4}'"
		)
	);

    // Boş belleğin, belirlenen minimum bellekten büyük olup olmadığını kontrol et
    if ( $freeMemory < $minFreeMemoryMB ) 
	{
        return FALSE;
    }
    
	
    // Maksimum kullanıcı süreçleri limitini kontrol et
    $maxProcesses = intval 
	( 
		shell_exec ( '/bin/bash -c "ulimit -u"' ) 
	);
    $currentProcesses = intval 
	( 
		shell_exec ( 'ps aux --no-headers | wc -l' ) 
	);
	
    if ( $currentProcesses >= $maxProcesses ) 
	{
        return FALSE;
    }
	

    return TRUE;
}



?>




-- MySQL dump 10.13  Distrib 8.0.19, for Win64 (x86_64)
--
-- Host: 222.333.111.222    Database: whois-db
-- ------------------------------------------------------
-- Server version	5.7.30-33-57-log

/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!50503 SET NAMES utf8mb4 */;
/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */;
/*!40103 SET TIME_ZONE='+00:00' */;
/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */;
/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */;

--
-- Table structure for table `cs_whois_server_domain_information`
--

DROP TABLE IF EXISTS `cs_whois_server_domain_information`;
/*!40101 SET @saved_cs_client     = @@character_set_client */;
/*!50503 SET character_set_client = utf8mb4 */;
CREATE TABLE `cs_whois_server_domain_information` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `item_name` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `item_type` varchar(30) COLLATE utf8mb4_unicode_ci NOT NULL,
  `item_identity` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `item_whois_server` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `item_registrar_url` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `item_update_time` datetime DEFAULT NULL,
  `item_create_time` datetime DEFAULT NULL,
  `item_expiry_time` datetime DEFAULT NULL,
  `item_registrar` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `item_iana_id` bigint(20) DEFAULT NULL,
  `item_abuse_contact_email` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `item_abuse_phone_number` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `item_status` json DEFAULT NULL,
  `item_nameservers` json DEFAULT NULL,
  `item_dnssec` varchar(30) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  `item_whois_inaccuracy_url` varchar(100) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `item_name` (`item_name`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
/*!40101 SET character_set_client = @saved_cs_client */;

--
-- Dumping data for table `cs_whois_server_domain_information`
--

LOCK TABLES `cs_whois_server_domain_information` WRITE;
/*!40000 ALTER TABLE `cs_whois_server_domain_information` DISABLE KEYS */;
INSERT INTO `cs_whois_server_domain_information` VALUES (1,'test.test','domain','2138514_DOMAIN_COM-VRSN','testwhois.durukanbal.com','https://durukanbal.com','2023-09-09 15:39:04','2023-09-09 15:39:04','2023-09-09 15:39:04','Durukanbal A.Ş',292,'abuse@durukanbal.com','0444 111 2 333','[\"clientDeleteProhibited https://icann.org/epp#clientDeleteProhibited\", \"clientTransferProhibited https://icann.org/epp#clientTransferProhibited\", \"clientUpdateProhibited https://icann.org/epp#clientUpdateProhibited\", \"serverDeleteProhibited https://icann.org/epp#serverDeleteProhibited\", \"serverTransferProhibited https://icann.org/epp#serverTransferProhibited\", \"serverUpdateProhibited https://icann.org/epp#serverUpdateProhibited\"]','[\"ns1.test.test\", \"ns2.test.test\", \"ns3.test.test\", \"ns4.test.test\"]','unsigned','https://www.icann.org/wicf/');
/*!40000 ALTER TABLE `cs_whois_server_domain_information` ENABLE KEYS */;
UNLOCK TABLES;
/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */;

/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */;

-- Dump completed on 2024-01-14 11:45:39
Categories: PHP language

62 Comments

Leave a Reply

Avatar placeholder