mirror of
https://github.com/getnamingo/registry.git
synced 2025-08-03 00:01:50 +02:00
677 lines
No EOL
38 KiB
PHP
677 lines
No EOL
38 KiB
PHP
<?php
|
|
// Include the Swoole extension
|
|
if (!extension_loaded('swoole')) {
|
|
die('Swoole extension must be installed');
|
|
}
|
|
|
|
use Swoole\Server;
|
|
|
|
$c = require_once 'config.php';
|
|
require_once 'helpers.php';
|
|
$logFilePath = '/var/log/namingo/whois.log';
|
|
$log = setupLogger($logFilePath, 'WHOIS');
|
|
|
|
// Initialize the PDO connection pool
|
|
$pool = new Swoole\Database\PDOPool(
|
|
(new Swoole\Database\PDOConfig())
|
|
->withDriver($c['db_type'])
|
|
->withHost($c['db_host'])
|
|
->withPort($c['db_port'])
|
|
->withDbName($c['db_database'])
|
|
->withUsername($c['db_username'])
|
|
->withPassword($c['db_password'])
|
|
->withCharset('utf8mb4')
|
|
);
|
|
|
|
// Create a Swoole TCP server
|
|
$server = new Server('0.0.0.0', 43);
|
|
$server->set([
|
|
'daemonize' => false,
|
|
'log_file' => '/var/log/namingo/whois_application.log',
|
|
'log_level' => SWOOLE_LOG_INFO,
|
|
'worker_num' => swoole_cpu_num() * 2,
|
|
'pid_file' => '/var/run/whois.pid',
|
|
'max_request' => 1000,
|
|
'dispatch_mode' => 2,
|
|
'open_tcp_nodelay' => true,
|
|
'max_conn' => 1024,
|
|
'heartbeat_check_interval' => 60,
|
|
'heartbeat_idle_time' => 120,
|
|
'buffer_output_size' => 2 * 1024 * 1024, // 2MB
|
|
'enable_reuse_port' => true,
|
|
'package_max_length' => 8192, // 8KB
|
|
'open_eof_check' => true,
|
|
'package_eof' => "\r\n"
|
|
]);
|
|
$log->info('server started.');
|
|
|
|
// Register a callback to handle incoming connections
|
|
$server->on('connect', function ($server, $fd) use ($log) {
|
|
$log->info('new client connected: ' . $fd);
|
|
});
|
|
|
|
// Register a callback to handle incoming requests
|
|
$server->on('receive', function ($server, $fd, $reactorId, $data) use ($c, $pool, $log) {
|
|
// Get a PDO connection from the pool
|
|
$pdo = $pool->get();
|
|
$privacy = $c['privacy'];
|
|
$parsedQuery = parseQuery($data);
|
|
$queryType = $parsedQuery['type'];
|
|
$queryData = $parsedQuery['data'];
|
|
|
|
// Handle the WHOIS query
|
|
try {
|
|
switch ($queryType) {
|
|
case 'domain':
|
|
// Handle domain query
|
|
$domain = $queryData;
|
|
|
|
if (!$domain) {
|
|
$server->send($fd, "please enter a domain name");
|
|
$server->close($fd);
|
|
}
|
|
if (strlen($domain) > 68) {
|
|
$server->send($fd, "domain name is too long");
|
|
$server->close($fd);
|
|
}
|
|
// Convert to Punycode if the domain is not in ASCII
|
|
if (!mb_detect_encoding($domain, 'ASCII', true)) {
|
|
$convertedDomain = idn_to_ascii($domain, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
|
|
if ($convertedDomain === false) {
|
|
$server->send($fd, "Domain conversion to Punycode failed");
|
|
$server->close($fd);
|
|
} else {
|
|
$domain = $convertedDomain;
|
|
}
|
|
}
|
|
if (!preg_match('/^(?:(xn--[a-zA-Z0-9-]{1,63}|[a-zA-Z0-9-]{1,63})\.){1,3}(xn--[a-zA-Z0-9-]{2,63}|[a-zA-Z]{2,63})$/', $domain)) {
|
|
$server->send($fd, "domain name invalid format");
|
|
$server->close($fd);
|
|
}
|
|
$domain = strtoupper($domain);
|
|
|
|
// Extract TLD from the domain and prepend a dot
|
|
$parts = explode('.', $domain);
|
|
$tld = "." . end($parts);
|
|
|
|
// Check if the TLD exists in the domain_tld table
|
|
$stmtTLD = $pdo->prepare("SELECT COUNT(*) FROM domain_tld WHERE tld = :tld");
|
|
$stmtTLD->bindParam(':tld', $tld, PDO::PARAM_STR);
|
|
$stmtTLD->execute();
|
|
$tldExists = $stmtTLD->fetchColumn();
|
|
|
|
if (!$tldExists) {
|
|
$server->send($fd, "Invalid TLD. Please search only allowed TLDs");
|
|
$server->close($fd);
|
|
return;
|
|
}
|
|
|
|
// Check if domain is reserved
|
|
$stmtReserved = $pdo->prepare("SELECT id FROM reserved_domain_names WHERE name = ? LIMIT 1");
|
|
$stmtReserved->execute([$parts[0]]);
|
|
$domain_already_reserved = $stmtReserved->fetchColumn();
|
|
|
|
if ($domain_already_reserved) {
|
|
$server->send($fd, "Domain name is reserved or restricted");
|
|
$server->close($fd);
|
|
return;
|
|
}
|
|
|
|
// Fetch the IDN regex for the given TLD
|
|
$stmtRegex = $pdo->prepare("SELECT idn_table FROM domain_tld WHERE tld = :tld");
|
|
$stmtRegex->bindParam(':tld', $tld, PDO::PARAM_STR);
|
|
$stmtRegex->execute();
|
|
$idnRegex = $stmtRegex->fetchColumn();
|
|
|
|
if (!$idnRegex) {
|
|
$server->send($fd, "Failed to fetch domain IDN table");
|
|
$server->close($fd);
|
|
return;
|
|
}
|
|
|
|
// Check for invalid characters using fetched regex
|
|
if (strpos(strtolower($parts[0]), 'xn--') === 0) {
|
|
$label = idn_to_utf8(strtolower($parts[0]), IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
|
|
} else {
|
|
$label = strtolower($parts[0]);
|
|
}
|
|
if (!preg_match($idnRegex, $label)) {
|
|
$server->send($fd, "Domain name invalid IDN characters");
|
|
$server->close($fd);
|
|
return;
|
|
}
|
|
|
|
$query = "SELECT * FROM registry.domain WHERE name = :domain";
|
|
$stmt = $pdo->prepare($query);
|
|
$stmt->bindParam(':domain', $domain, PDO::PARAM_STR);
|
|
$stmt->execute();
|
|
|
|
if ($f = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
|
$f['crdate'] = (new DateTime($f['crdate']))->format('Y-m-d\TH:i:s.v\Z');
|
|
if (isset($f['lastupdate']) && $f['lastupdate'] !== null) {
|
|
$f['lastupdate'] = (new DateTime($f['lastupdate']))->format('Y-m-d\TH:i:s.v\Z');
|
|
} else {
|
|
$f['lastupdate'] = '';
|
|
}
|
|
$f['exdate'] = (new DateTime($f['exdate']))->format('Y-m-d\TH:i:s.v\Z');
|
|
|
|
$query2 = "SELECT tld FROM domain_tld WHERE id = :tldid";
|
|
$stmt2 = $pdo->prepare($query2);
|
|
$stmt2->bindParam(':tldid', $f['tldid'], PDO::PARAM_INT);
|
|
$stmt2->execute();
|
|
|
|
$tld = $stmt2->fetch(PDO::FETCH_ASSOC);
|
|
|
|
$query3 = "SELECT name,iana_id,whois_server,url,abuse_email,abuse_phone FROM registrar WHERE id = :clid";
|
|
$stmt3 = $pdo->prepare($query3);
|
|
$stmt3->bindParam(':clid', $f['clid'], PDO::PARAM_INT);
|
|
$stmt3->execute();
|
|
|
|
$clidF = $stmt3->fetch(PDO::FETCH_ASSOC);
|
|
|
|
// Check if the domain name is non-ASCII or starts with 'xn--'
|
|
$isNonAsciiOrPunycode = !mb_check_encoding($f['name'], 'ASCII') || strpos($f['name'], 'xn--') === 0;
|
|
|
|
$res = "Domain Name: ".strtoupper($f['name'])
|
|
."\n";
|
|
|
|
// Add the Internationalized Domain Name line if the condition is met
|
|
if ($isNonAsciiOrPunycode) {
|
|
// Convert the domain name to UTF-8 and make it uppercase
|
|
$internationalizedName = idn_to_utf8($f['name'], 0, INTL_IDNA_VARIANT_UTS46);
|
|
$res .= "Internationalized Domain Name: " . mb_strtoupper($internationalizedName) . "\n";
|
|
}
|
|
|
|
$res .= "Registry Domain ID: D".$f['id']."-".$c['roid']
|
|
."\nRegistrar WHOIS Server: ".$clidF['whois_server']
|
|
."\nRegistrar URL: ".$clidF['url']
|
|
."\nUpdated Date: ".$f['lastupdate']
|
|
."\nCreation Date: ".$f['crdate']
|
|
."\nRegistry Expiry Date: ".$f['exdate']
|
|
."\nRegistrar: ".$clidF['name']
|
|
."\nRegistrar IANA ID: ".$clidF['iana_id']
|
|
."\nRegistrar Abuse Contact Email: ".$clidF['abuse_email']
|
|
."\nRegistrar Abuse Contact Phone: ".$clidF['abuse_phone'];
|
|
|
|
$query4 = "SELECT status FROM domain_status WHERE domain_id = :domain_id";
|
|
$stmt4 = $pdo->prepare($query4);
|
|
$stmt4->bindParam(':domain_id', $f['id'], PDO::PARAM_INT);
|
|
$stmt4->execute();
|
|
|
|
$statusFound = false;
|
|
|
|
while ($f2 = $stmt4->fetch(PDO::FETCH_ASSOC)) {
|
|
$res .= "\nDomain Status: " . $f2['status'] . " https://icann.org/epp#" . $f2['status'];
|
|
$statusFound = true;
|
|
}
|
|
|
|
// Check for additional statuses
|
|
if (!empty($f['rgpstatus'])) {
|
|
$res .= "\nDomain Status: " . $f['rgpstatus'] . " https://icann.org/epp#" . $f['rgpstatus'];
|
|
$statusFound = true;
|
|
}
|
|
|
|
// If no status is found, default to 'ok'
|
|
if (!$statusFound) {
|
|
$res .= "\nDomain Status: ok https://icann.org/epp#ok";
|
|
}
|
|
|
|
$query5 = "SELECT contact.identifier,contact_postalInfo.name,contact_postalInfo.org,contact_postalInfo.street1,contact_postalInfo.street2,contact_postalInfo.street3,contact_postalInfo.city,contact_postalInfo.sp,contact_postalInfo.pc,contact_postalInfo.cc,contact.voice,contact.fax,contact.email
|
|
FROM contact,contact_postalInfo WHERE contact.id=:registrant AND contact_postalInfo.contact_id=contact.id";
|
|
$stmt5 = $pdo->prepare($query5);
|
|
$stmt5->bindParam(':registrant', $f['registrant'], PDO::PARAM_INT);
|
|
$stmt5->execute();
|
|
|
|
$f2 = $stmt5->fetch(PDO::FETCH_ASSOC);
|
|
if ($privacy) {
|
|
$res .= "\nRegistry Registrant ID: REDACTED FOR PRIVACY"
|
|
."\nRegistrant Name: REDACTED FOR PRIVACY"
|
|
."\nRegistrant Organization: REDACTED FOR PRIVACY"
|
|
."\nRegistrant Street: REDACTED FOR PRIVACY"
|
|
."\nRegistrant Street: REDACTED FOR PRIVACY"
|
|
."\nRegistrant Street: REDACTED FOR PRIVACY"
|
|
."\nRegistrant City: REDACTED FOR PRIVACY"
|
|
."\nRegistrant State/Province: REDACTED FOR PRIVACY"
|
|
."\nRegistrant Postal Code: REDACTED FOR PRIVACY"
|
|
."\nRegistrant Country: REDACTED FOR PRIVACY"
|
|
."\nRegistrant Phone: REDACTED FOR PRIVACY"
|
|
."\nRegistrant Fax: REDACTED FOR PRIVACY"
|
|
."\nRegistrant Email: Kindly refer to the RDDS server associated with the identified registrar in this output to obtain contact details for the Registrant, Admin, or Tech associated with the queried domain name.";
|
|
} else {
|
|
$res .= "\nRegistry Registrant ID: C".$f2['identifier']."-".$c['roid']
|
|
."\nRegistrant Name: ".$f2['name']
|
|
."\nRegistrant Organization: ".$f2['org']
|
|
."\nRegistrant Street: ".$f2['street1']
|
|
."\nRegistrant Street: ".$f2['street2']
|
|
."\nRegistrant Street: ".$f2['street3']
|
|
."\nRegistrant City: ".$f2['city']
|
|
."\nRegistrant State/Province: ".$f2['sp']
|
|
."\nRegistrant Postal Code: ".$f2['pc']
|
|
."\nRegistrant Country: ".strtoupper($f2['cc'])
|
|
."\nRegistrant Phone: ".$f2['voice']
|
|
."\nRegistrant Fax: ".$f2['fax']
|
|
."\nRegistrant Email: ".$f2['email'];
|
|
}
|
|
|
|
$query6 = "SELECT contact.identifier,contact_postalInfo.name,contact_postalInfo.org,contact_postalInfo.street1,contact_postalInfo.street2,contact_postalInfo.street3,contact_postalInfo.city,contact_postalInfo.sp,contact_postalInfo.pc,contact_postalInfo.cc,contact.voice,contact.fax,contact.email
|
|
FROM domain_contact_map,contact,contact_postalInfo WHERE domain_contact_map.domain_id=:domain_id AND domain_contact_map.type='admin' AND domain_contact_map.contact_id=contact.id AND domain_contact_map.contact_id=contact_postalInfo.contact_id";
|
|
$stmt6 = $pdo->prepare($query6);
|
|
$stmt6->bindParam(':domain_id', $f['id'], PDO::PARAM_INT);
|
|
$stmt6->execute();
|
|
|
|
$f2 = $stmt6->fetch(PDO::FETCH_ASSOC);
|
|
if ($privacy) {
|
|
$res .= "\nRegistry Admin ID: REDACTED FOR PRIVACY"
|
|
."\nAdmin Name: REDACTED FOR PRIVACY"
|
|
."\nAdmin Organization: REDACTED FOR PRIVACY"
|
|
."\nAdmin Street: REDACTED FOR PRIVACY"
|
|
."\nAdmin Street: REDACTED FOR PRIVACY"
|
|
."\nAdmin Street: REDACTED FOR PRIVACY"
|
|
."\nAdmin City: REDACTED FOR PRIVACY"
|
|
."\nAdmin State/Province: REDACTED FOR PRIVACY"
|
|
."\nAdmin Postal Code: REDACTED FOR PRIVACY"
|
|
."\nAdmin Country: REDACTED FOR PRIVACY"
|
|
."\nAdmin Phone: REDACTED FOR PRIVACY"
|
|
."\nAdmin Fax: REDACTED FOR PRIVACY"
|
|
."\nAdmin Email: Kindly refer to the RDDS server associated with the identified registrar in this output to obtain contact details for the Registrant, Admin, or Tech associated with the queried domain name.";
|
|
} else {
|
|
if (!empty($f2['identifier'])) {
|
|
$res .= "\nRegistry Admin ID: C" . $f2['identifier'] . "-" . $c['roid'];
|
|
} else {
|
|
$res .= "\nRegistry Admin ID:";
|
|
}
|
|
$res .= "\nAdmin Name: ".$f2['name']
|
|
."\nAdmin Organization: ".$f2['org']
|
|
."\nAdmin Street: ".$f2['street1']
|
|
."\nAdmin Street: ".$f2['street2']
|
|
."\nAdmin Street: ".$f2['street3']
|
|
."\nAdmin City: ".$f2['city']
|
|
."\nAdmin State/Province: ".$f2['sp']
|
|
."\nAdmin Postal Code: ".$f2['pc']
|
|
."\nAdmin Country: ".strtoupper($f2['cc'])
|
|
."\nAdmin Phone: ".$f2['voice']
|
|
."\nAdmin Fax: ".$f2['fax']
|
|
."\nAdmin Email: ".$f2['email'];
|
|
}
|
|
|
|
$query7 = "SELECT contact.identifier,contact_postalInfo.name,contact_postalInfo.org,contact_postalInfo.street1,contact_postalInfo.street2,contact_postalInfo.street3,contact_postalInfo.city,contact_postalInfo.sp,contact_postalInfo.pc,contact_postalInfo.cc,contact.voice,contact.fax,contact.email
|
|
FROM domain_contact_map,contact,contact_postalInfo WHERE domain_contact_map.domain_id=:domain_id AND domain_contact_map.type='billing' AND domain_contact_map.contact_id=contact.id AND domain_contact_map.contact_id=contact_postalInfo.contact_id";
|
|
$stmt7 = $pdo->prepare($query7);
|
|
$stmt7->bindParam(':domain_id', $f['id'], PDO::PARAM_INT);
|
|
$stmt7->execute();
|
|
|
|
$f2 = $stmt7->fetch(PDO::FETCH_ASSOC);
|
|
if ($privacy) {
|
|
$res .= "\nRegistry Billing ID: REDACTED FOR PRIVACY"
|
|
."\nBilling Name: REDACTED FOR PRIVACY"
|
|
."\nBilling Organization: REDACTED FOR PRIVACY"
|
|
."\nBilling Street: REDACTED FOR PRIVACY"
|
|
."\nBilling Street: REDACTED FOR PRIVACY"
|
|
."\nBilling Street: REDACTED FOR PRIVACY"
|
|
."\nBilling City: REDACTED FOR PRIVACY"
|
|
."\nBilling State/Province: REDACTED FOR PRIVACY"
|
|
."\nBilling Postal Code: REDACTED FOR PRIVACY"
|
|
."\nBilling Country: REDACTED FOR PRIVACY"
|
|
."\nBilling Phone: REDACTED FOR PRIVACY"
|
|
."\nBilling Fax: REDACTED FOR PRIVACY"
|
|
."\nBilling Email: Kindly refer to the RDDS server associated with the identified registrar in this output to obtain contact details for the Registrant, Admin, or Tech associated with the queried domain name.";
|
|
} else {
|
|
if (!empty($f2['identifier'])) {
|
|
$res .= "\nRegistry Billing ID: C" . $f2['identifier'] . "-" . $c['roid'];
|
|
} else {
|
|
$res .= "\nRegistry Billing ID:";
|
|
}
|
|
$res .= "\nBilling Name: ".$f2['name']
|
|
."\nBilling Organization: ".$f2['org']
|
|
."\nBilling Street: ".$f2['street1']
|
|
."\nBilling Street: ".$f2['street2']
|
|
."\nBilling Street: ".$f2['street3']
|
|
."\nBilling City: ".$f2['city']
|
|
."\nBilling State/Province: ".$f2['sp']
|
|
."\nBilling Postal Code: ".$f2['pc']
|
|
."\nBilling Country: ".strtoupper($f2['cc'])
|
|
."\nBilling Phone: ".$f2['voice']
|
|
."\nBilling Fax: ".$f2['fax']
|
|
."\nBilling Email: ".$f2['email'];
|
|
}
|
|
|
|
$query8 = "SELECT contact.identifier,contact_postalInfo.name,contact_postalInfo.org,contact_postalInfo.street1,contact_postalInfo.street2,contact_postalInfo.street3,contact_postalInfo.city,contact_postalInfo.sp,contact_postalInfo.pc,contact_postalInfo.cc,contact.voice,contact.fax,contact.email
|
|
FROM domain_contact_map,contact,contact_postalInfo WHERE domain_contact_map.domain_id=:domain_id AND domain_contact_map.type='tech' AND domain_contact_map.contact_id=contact.id AND domain_contact_map.contact_id=contact_postalInfo.contact_id";
|
|
$stmt8 = $pdo->prepare($query8);
|
|
$stmt8->bindParam(':domain_id', $f['id'], PDO::PARAM_INT);
|
|
$stmt8->execute();
|
|
|
|
$f2 = $stmt8->fetch(PDO::FETCH_ASSOC);
|
|
if ($privacy) {
|
|
$res .= "\nRegistry Tech ID: REDACTED FOR PRIVACY"
|
|
."\nTech Name: REDACTED FOR PRIVACY"
|
|
."\nTech Organization: REDACTED FOR PRIVACY"
|
|
."\nTech Street: REDACTED FOR PRIVACY"
|
|
."\nTech Street: REDACTED FOR PRIVACY"
|
|
."\nTech Street: REDACTED FOR PRIVACY"
|
|
."\nTech City: REDACTED FOR PRIVACY"
|
|
."\nTech State/Province: REDACTED FOR PRIVACY"
|
|
."\nTech Postal Code: REDACTED FOR PRIVACY"
|
|
."\nTech Country: REDACTED FOR PRIVACY"
|
|
."\nTech Phone: REDACTED FOR PRIVACY"
|
|
."\nTech Fax: REDACTED FOR PRIVACY"
|
|
."\nTech Email: Kindly refer to the RDDS server associated with the identified registrar in this output to obtain contact details for the Registrant, Admin, or Tech associated with the queried domain name.";
|
|
} else {
|
|
if (!empty($f2['identifier'])) {
|
|
$res .= "\nRegistry Tech ID: C" . $f2['identifier'] . "-" . $c['roid'];
|
|
} else {
|
|
$res .= "\nRegistry Tech ID:";
|
|
}
|
|
$res .= "\nTech Name: ".$f2['name']
|
|
."\nTech Organization: ".$f2['org']
|
|
."\nTech Street: ".$f2['street1']
|
|
."\nTech Street: ".$f2['street2']
|
|
."\nTech Street: ".$f2['street3']
|
|
."\nTech City: ".$f2['city']
|
|
."\nTech State/Province: ".$f2['sp']
|
|
."\nTech Postal Code: ".$f2['pc']
|
|
."\nTech Country: ".strtoupper($f2['cc'])
|
|
."\nTech Phone: ".$f2['voice']
|
|
."\nTech Fax: ".$f2['fax']
|
|
."\nTech Email: ".$f2['email'];
|
|
}
|
|
|
|
$query9 = "SELECT name FROM domain_host_map,host WHERE domain_host_map.domain_id = :domain_id AND domain_host_map.host_id = host.id";
|
|
$stmt9 = $pdo->prepare($query9);
|
|
$stmt9->bindParam(':domain_id', $f['id'], PDO::PARAM_INT);
|
|
$stmt9->execute();
|
|
|
|
$counter = 0;
|
|
while ($counter < 13) {
|
|
$f2 = $stmt9->fetch(PDO::FETCH_ASSOC);
|
|
if ($f2 === false) break; // Break if there are no more rows
|
|
$res .= "\nName Server: ".$f2['name'];
|
|
$counter++;
|
|
}
|
|
|
|
$query_dnssec = "SELECT EXISTS(SELECT 1 FROM secdns WHERE domain_id = :domain_id)";
|
|
$stmt_dnssec = $pdo->prepare($query_dnssec);
|
|
$stmt_dnssec->bindParam(':domain_id', $f['id'], PDO::PARAM_INT);
|
|
$stmt_dnssec->execute();
|
|
|
|
$dnssec_exists = $stmt_dnssec->fetchColumn();
|
|
|
|
if ($dnssec_exists) {
|
|
$res .= "\nDNSSEC: signedDelegation";
|
|
} else {
|
|
$res .= "\nDNSSEC: unsigned";
|
|
}
|
|
$res .= "\nURL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/";
|
|
$currentDateTime = new DateTime();
|
|
$currentTimestamp = $currentDateTime->format("Y-m-d\TH:i:s.v\Z");
|
|
$res .= "\n>>> Last update of WHOIS database: {$currentTimestamp} <<<";
|
|
$res .= "\n";
|
|
$res .= "\nFor more information on Whois status codes, please visit https://icann.org/epp";
|
|
$res .= "\n\n";
|
|
$res .= "Access to {$tld['tld']} WHOIS information is provided to assist persons in"
|
|
."\ndetermining the contents of a domain name registration record in the"
|
|
."\nDomain Name Registry registry database. The data in this record is provided by"
|
|
."\nDomain Name Registry for informational purposes only, and Domain Name Registry does not"
|
|
."\nguarantee its accuracy. This service is intended only for query-based"
|
|
."\naccess. You agree that you will use this data only for lawful purposes"
|
|
."\nand that, under no circumstances will you use this data to: (a) allow,"
|
|
."\nenable, or otherwise support the transmission by e-mail, telephone, or"
|
|
."\nfacsimile of mass unsolicited, commercial advertising or solicitations"
|
|
."\nto entities other than the data recipient's own existing customers; or"
|
|
."\n(b) enable high volume, automated, electronic processes that send"
|
|
."\nqueries or data to the systems of Registry Operator, a Registrar, or"
|
|
."\nNIC except as reasonably necessary to register domain names or"
|
|
."\nmodify existing registrations. All rights reserved. Domain Name Registry reserves"
|
|
."\nthe right to modify these terms at any time. By submitting this query,"
|
|
."\nyou agree to abide by this policy."
|
|
."\n";
|
|
$server->send($fd, $res . "");
|
|
|
|
$clientInfo = $server->getClientInfo($fd);
|
|
$remoteAddr = $clientInfo['remote_ip'];
|
|
$log->notice('new request from ' . $remoteAddr . ' | ' . $domain . ' | FOUND');
|
|
|
|
$stmt = $pdo->prepare("UPDATE settings SET value = value + 1 WHERE name = :name");
|
|
$settingName = 'whois-43-queries';
|
|
$stmt->bindParam(':name', $settingName);
|
|
$stmt->execute();
|
|
} else {
|
|
//NOT FOUND or No match for;
|
|
$server->send($fd, "NOT FOUND");
|
|
|
|
$clientInfo = $server->getClientInfo($fd);
|
|
$remoteAddr = $clientInfo['remote_ip'];
|
|
$log->notice('new request from ' . $remoteAddr . ' | ' . $domain . ' | NOT FOUND');
|
|
|
|
$stmt = $pdo->prepare("UPDATE settings SET value = value + 1 WHERE name = :name");
|
|
$settingName = 'whois-43-queries';
|
|
$stmt->bindParam(':name', $settingName);
|
|
$stmt->execute();
|
|
}
|
|
break;
|
|
case 'nameserver':
|
|
// Handle nameserver query
|
|
$nameserver = $queryData;
|
|
|
|
if (!$nameserver) {
|
|
$server->send($fd, "please enter a nameserver");
|
|
$server->close($fd);
|
|
}
|
|
if (strlen($nameserver) > 63) {
|
|
$server->send($fd, "nameserver is too long");
|
|
$server->close($fd);
|
|
}
|
|
|
|
// Convert to Punycode if the host is not in ASCII
|
|
if (!mb_detect_encoding($nameserver, 'ASCII', true)) {
|
|
$convertedDomain = idn_to_ascii($nameserver, IDNA_NONTRANSITIONAL_TO_ASCII, INTL_IDNA_VARIANT_UTS46);
|
|
if ($convertedDomain === false) {
|
|
$server->send($fd, "Host conversion to Punycode failed.");
|
|
$server->close($fd);
|
|
} else {
|
|
$nameserver = $convertedDomain;
|
|
}
|
|
}
|
|
|
|
if (!preg_match('/^((xn--[a-zA-Z0-9-]{1,63}|[a-zA-Z0-9-]{1,63})\.){2,}(xn--[a-zA-Z0-9-]{2,63}|[a-zA-Z]{2,63})$/', $nameserver)) {
|
|
$server->send($fd, "Nameserver contains invalid characters or is not in the correct format.");
|
|
$server->close($fd);
|
|
}
|
|
|
|
$query = "SELECT name,clid FROM host WHERE name = :nameserver";
|
|
$stmt = $pdo->prepare($query);
|
|
$stmt->bindParam(':nameserver', $nameserver, PDO::PARAM_STR);
|
|
$stmt->execute();
|
|
|
|
if ($f = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
|
$res = "Server Name: ".$f['name'];
|
|
|
|
// Fetch the registrar details for this registrar using the id
|
|
$regQuery = "SELECT id,name,iana_id,whois_server,url,abuse_email,abuse_phone FROM registrar WHERE id = :clid";
|
|
$regStmt = $pdo->prepare($regQuery);
|
|
$regStmt->bindParam(':clid', $f['clid'], PDO::PARAM_INT);
|
|
$regStmt->execute();
|
|
|
|
if ($registrar = $regStmt->fetch(PDO::FETCH_ASSOC)) {
|
|
// Append the registrar details to the response
|
|
$res .= "\nRegistrar Name: ".$registrar['name'];
|
|
$res .= "\nRegistrar WHOIS Server: ".$registrar['whois_server'];
|
|
$res .= "\nRegistrar URL: ".$registrar['url'];
|
|
$res .= "\nRegistrar IANA ID: ".$registrar['iana_id'];
|
|
$res .= "\nRegistrar Abuse Contact Email: ".$registrar['abuse_email'];
|
|
$res .= "\nRegistrar Abuse Contact Phone: ".$registrar['abuse_phone'];
|
|
}
|
|
|
|
$res .= "\nURL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/";
|
|
$currentDateTime = new DateTime();
|
|
$currentTimestamp = $currentDateTime->format("Y-m-d\TH:i:s.v\Z");
|
|
$res .= "\n>>> Last update of WHOIS database: {$currentTimestamp} <<<";
|
|
$res .= "\n";
|
|
$res .= "\nFor more information on Whois status codes, please visit https://icann.org/epp";
|
|
$res .= "\n\n";
|
|
$res .= "Access to WHOIS information is provided to assist persons in"
|
|
."\ndetermining the contents of a domain name registration record in the"
|
|
."\nDomain Name Registry registry database. The data in this record is provided by"
|
|
."\nDomain Name Registry for informational purposes only, and Domain Name Registry does not"
|
|
."\nguarantee its accuracy. This service is intended only for query-based"
|
|
."\naccess. You agree that you will use this data only for lawful purposes"
|
|
."\nand that, under no circumstances will you use this data to: (a) allow,"
|
|
."\nenable, or otherwise support the transmission by e-mail, telephone, or"
|
|
."\nfacsimile of mass unsolicited, commercial advertising or solicitations"
|
|
."\nto entities other than the data recipient's own existing customers; or"
|
|
."\n(b) enable high volume, automated, electronic processes that send"
|
|
."\nqueries or data to the systems of Registry Operator, a Registrar, or"
|
|
."\nNIC except as reasonably necessary to register domain names or"
|
|
."\nmodify existing registrations. All rights reserved. Domain Name Registry reserves"
|
|
."\nthe right to modify these terms at any time. By submitting this query,"
|
|
."\nyou agree to abide by this policy."
|
|
."\n";
|
|
$server->send($fd, $res . "");
|
|
|
|
$clientInfo = $server->getClientInfo($fd);
|
|
$remoteAddr = $clientInfo['remote_ip'];
|
|
$log->notice('new request from ' . $remoteAddr . ' | ' . $nameserver . ' | FOUND');
|
|
|
|
$stmt = $pdo->prepare("UPDATE settings SET value = value + 1 WHERE name = :name");
|
|
$settingName = 'whois-43-queries';
|
|
$stmt->bindParam(':name', $settingName);
|
|
$stmt->execute();
|
|
} else {
|
|
//NOT FOUND or No match for;
|
|
$server->send($fd, "NOT FOUND");
|
|
|
|
$clientInfo = $server->getClientInfo($fd);
|
|
$remoteAddr = $clientInfo['remote_ip'];
|
|
$log->notice('new request from ' . $remoteAddr . ' | ' . $nameserver . ' | NOT FOUND');
|
|
|
|
$stmt = $pdo->prepare("UPDATE settings SET value = value + 1 WHERE name = :name");
|
|
$settingName = 'whois-43-queries';
|
|
$stmt->bindParam(':name', $settingName);
|
|
$stmt->execute();
|
|
}
|
|
break;
|
|
case 'registrar':
|
|
// Handle registrar query
|
|
$registrar = $queryData;
|
|
|
|
if (!$registrar) {
|
|
$server->send($fd, "please enter a registrar name");
|
|
$server->close($fd);
|
|
}
|
|
if (strlen($registrar) > 50) {
|
|
$server->send($fd, "registrar name is too long");
|
|
$server->close($fd);
|
|
}
|
|
|
|
if (!preg_match('/^[a-zA-Z0-9\s\-]+$/', $registrar)) {
|
|
$server->send($fd, "Registrar name contains invalid characters.");
|
|
$server->close($fd);
|
|
}
|
|
|
|
$query = "SELECT id,name,iana_id,whois_server,url,abuse_email,abuse_phone FROM registrar WHERE name = :registrar";
|
|
$stmt = $pdo->prepare($query);
|
|
$stmt->bindParam(':registrar', $registrar, PDO::PARAM_STR);
|
|
$stmt->execute();
|
|
|
|
if ($f = $stmt->fetch(PDO::FETCH_ASSOC)) {
|
|
$res = "Registrar: ".$f['name']
|
|
."\nRegistrar WHOIS Server: ".$f['whois_server']
|
|
."\nRegistrar URL: ".$f['url']
|
|
."\nRegistrar IANA ID: ".$f['iana_id']
|
|
."\nRegistrar Abuse Contact Email: ".$f['abuse_email']
|
|
."\nRegistrar Abuse Contact Phone: ".$f['abuse_phone'];
|
|
|
|
// Fetch the contact details for this registrar using the id
|
|
$contactQuery = "SELECT * FROM registrar_contact WHERE id = :registrar_id";
|
|
$contactStmt = $pdo->prepare($contactQuery);
|
|
$contactStmt->bindParam(':registrar_id', $f['id'], PDO::PARAM_INT);
|
|
$contactStmt->execute();
|
|
|
|
if ($contact = $contactStmt->fetch(PDO::FETCH_ASSOC)) {
|
|
// Append the contact details to the response
|
|
$res .= "\nStreet: " . $contact['street1'];
|
|
$res .= "\nCity: " . $contact['city'];
|
|
$res .= "\nPostal Code: " . $contact['pc'];
|
|
$res .= "\nCountry: " . $contact['cc'];
|
|
$res .= "\nPhone: " . $contact['voice'];
|
|
$res .= "\nFax: " . $contact['fax'];
|
|
$res .= "\nPublic Email: " . $contact['email'];
|
|
}
|
|
|
|
$res .= "\nURL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/";
|
|
$currentDateTime = new DateTime();
|
|
$currentTimestamp = $currentDateTime->format("Y-m-d\TH:i:s.v\Z");
|
|
$res .= "\n>>> Last update of WHOIS database: {$currentTimestamp} <<<";
|
|
$res .= "\n";
|
|
$res .= "\nFor more information on Whois status codes, please visit https://icann.org/epp";
|
|
$res .= "\n\n";
|
|
$res .= "Access to WHOIS information is provided to assist persons in"
|
|
."\ndetermining the contents of a domain name registration record in the"
|
|
."\nDomain Name Registry registry database. The data in this record is provided by"
|
|
."\nDomain Name Registry for informational purposes only, and Domain Name Registry does not"
|
|
."\nguarantee its accuracy. This service is intended only for query-based"
|
|
."\naccess. You agree that you will use this data only for lawful purposes"
|
|
."\nand that, under no circumstances will you use this data to: (a) allow,"
|
|
."\nenable, or otherwise support the transmission by e-mail, telephone, or"
|
|
."\nfacsimile of mass unsolicited, commercial advertising or solicitations"
|
|
."\nto entities other than the data recipient's own existing customers; or"
|
|
."\n(b) enable high volume, automated, electronic processes that send"
|
|
."\nqueries or data to the systems of Registry Operator, a Registrar, or"
|
|
."\nNIC except as reasonably necessary to register domain names or"
|
|
."\nmodify existing registrations. All rights reserved. Domain Name Registry reserves"
|
|
."\nthe right to modify these terms at any time. By submitting this query,"
|
|
."\nyou agree to abide by this policy."
|
|
."\n";
|
|
$server->send($fd, $res . "");
|
|
|
|
$clientInfo = $server->getClientInfo($fd);
|
|
$remoteAddr = $clientInfo['remote_ip'];
|
|
$log->notice('new request from ' . $remoteAddr . ' | ' . $registrar . ' | FOUND');
|
|
|
|
$stmt = $pdo->prepare("UPDATE settings SET value = value + 1 WHERE name = :name");
|
|
$settingName = 'whois-43-queries';
|
|
$stmt->bindParam(':name', $settingName);
|
|
$stmt->execute();
|
|
} else {
|
|
//NOT FOUND or No match for;
|
|
$server->send($fd, "NOT FOUND");
|
|
|
|
$clientInfo = $server->getClientInfo($fd);
|
|
$remoteAddr = $clientInfo['remote_ip'];
|
|
$log->notice('new request from ' . $remoteAddr . ' | ' . $registrar . ' | NOT FOUND');
|
|
|
|
$stmt = $pdo->prepare("UPDATE settings SET value = value + 1 WHERE name = :name");
|
|
$settingName = 'whois-43-queries';
|
|
$stmt->bindParam(':name', $settingName);
|
|
$stmt->execute();
|
|
}
|
|
break;
|
|
default:
|
|
// Handle unknown query type
|
|
$log->error('Error');
|
|
$server->send($fd, "Error");
|
|
}
|
|
} catch (PDOException $e) {
|
|
// Handle database exceptions
|
|
$log->error('Database error: ' . $e->getMessage());
|
|
$server->send($fd, "Error connecting to the whois database");
|
|
$server->close($fd);
|
|
} catch (Throwable $e) {
|
|
// Catch any other exceptions or errors
|
|
$log->error('Error: ' . $e->getMessage());
|
|
$server->send($fd, "Error");
|
|
$server->close($fd);
|
|
} finally {
|
|
// Return the connection to the pool
|
|
$pool->put($pdo);
|
|
$server->close($fd);
|
|
}
|
|
});
|
|
|
|
// Register a callback to handle client disconnections
|
|
$server->on('close', function ($server, $fd) use ($log) {
|
|
$log->info('client ' . $fd . ' connected.');
|
|
});
|
|
|
|
// Start the server
|
|
$server->start(); |