PDO::ERRMODE_EXCEPTION]);
}
return $pdo;
}
function ensureTables() {
$pdo = getDB();
// FreeDNS Accounts (multi-comptes)
$pdo->exec("CREATE TABLE IF NOT EXISTS admin.freedns_accounts (
id SERIAL PRIMARY KEY,
username VARCHAR(100) NOT NULL,
password VARCHAR(255) NOT NULL,
cookie TEXT,
domains_count INTEGER DEFAULT 0,
max_domains INTEGER DEFAULT 5,
status VARCHAR(50) DEFAULT 'active',
last_login TIMESTAMP,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)");
// FreeDNS Domains
$pdo->exec("CREATE TABLE IF NOT EXISTS admin.freedns_domains (
id SERIAL PRIMARY KEY,
account_id INTEGER REFERENCES admin.freedns_accounts(id),
domain VARCHAR(255) NOT NULL,
freedns_id VARCHAR(100),
domain_type VARCHAR(50) DEFAULT 'subdomain',
base_domain VARCHAR(255),
status VARCHAR(50) DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)");
// FreeDNS Records
$pdo->exec("CREATE TABLE IF NOT EXISTS admin.freedns_records (
id SERIAL PRIMARY KEY,
domain_id INTEGER REFERENCES admin.freedns_domains(id),
record_type VARCHAR(10) NOT NULL,
name VARCHAR(255),
value TEXT,
ttl INTEGER DEFAULT 3600,
freedns_id VARCHAR(100),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)");
// Cloudflare Accounts
$pdo->exec("CREATE TABLE IF NOT EXISTS admin.cloudflare_accounts (
id SERIAL PRIMARY KEY,
email VARCHAR(255) NOT NULL,
api_key VARCHAR(255),
api_token VARCHAR(255),
account_id VARCHAR(100),
status VARCHAR(50) DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)");
// Cloudflare Zones
$pdo->exec("CREATE TABLE IF NOT EXISTS admin.cloudflare_zones (
id SERIAL PRIMARY KEY,
account_id INTEGER REFERENCES admin.cloudflare_accounts(id),
zone_id VARCHAR(100) NOT NULL,
domain VARCHAR(255) NOT NULL,
status VARCHAR(50),
name_servers TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)");
// Cloudflare DNS Records
$pdo->exec("CREATE TABLE IF NOT EXISTS admin.cloudflare_records (
id SERIAL PRIMARY KEY,
zone_id INTEGER REFERENCES admin.cloudflare_zones(id),
record_id VARCHAR(100),
record_type VARCHAR(10),
name VARCHAR(255),
content TEXT,
ttl INTEGER DEFAULT 1,
proxied BOOLEAN DEFAULT false,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)");
}
// FreeDNS API Class
class FreeDNSAPI {
private $account;
private $cookie;
private $baseUrl = 'https://freedns.afraid.org';
public function __construct($accountId = null) {
if ($accountId) {
$pdo = getDB();
$stmt = $pdo->prepare("SELECT * FROM admin.freedns_accounts WHERE id = ?");
$stmt->execute([$accountId]);
$this->account = $stmt->fetch(PDO::FETCH_ASSOC);
$this->cookie = $this->account['cookie'] ?? '';
}
}
public function login($username, $password) {
$ch = curl_init($this->baseUrl . '/zc.php?action=auth');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_POSTFIELDS => http_build_query([
'username' => $username,
'password' => $password,
'submit' => 'Login',
'action' => 'auth'
]),
CURLOPT_HEADER => true,
CURLOPT_FOLLOWLOCATION => true,
CURLOPT_USERAGENT => 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
]);
$response = curl_exec($ch);
curl_close($ch);
// Extract cookie
preg_match_all('/Set-Cookie:\s*([^;]+)/', $response, $matches);
$cookies = implode('; ', $matches[1] ?? []);
if (strpos($response, 'dns_cookie') !== false || strpos($cookies, 'dns_cookie') !== false) {
$this->cookie = $cookies;
return ['success' => true, 'cookie' => $cookies];
}
return ['success' => false, 'error' => 'Login failed'];
}
public function getDomains() {
$ch = curl_init($this->baseUrl . '/subdomain/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_COOKIE => $this->cookie,
CURLOPT_USERAGENT => 'Mozilla/5.0'
]);
$html = curl_exec($ch);
curl_close($ch);
$domains = [];
// Parse domains from HTML
preg_match_all('/edit\.php\?data_id=(\d+).*?
]*>([^<]+)<\/td>/s', $html, $matches, PREG_SET_ORDER);
foreach ($matches as $m) {
$domains[] = [
'freedns_id' => $m[1],
'domain' => trim($m[2])
];
}
return $domains;
}
public function addSubdomain($subdomain, $baseDomain, $type = 'A', $destination) {
// First get available base domains
$ch = curl_init($this->baseUrl . '/subdomain/edit.php');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_COOKIE => $this->cookie,
CURLOPT_USERAGENT => 'Mozilla/5.0'
]);
$html = curl_exec($ch);
curl_close($ch);
// Find domain_id for base domain
preg_match('/option value="(\d+)"[^>]*>' . preg_quote($baseDomain) . '/i', $html, $m);
$domainId = $m[1] ?? null;
if (!$domainId) {
return ['success' => false, 'error' => 'Base domain not found'];
}
// Create subdomain
$ch = curl_init($this->baseUrl . '/subdomain/save.php?step=2');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_COOKIE => $this->cookie,
CURLOPT_POSTFIELDS => http_build_query([
'type' => $type,
'subdomain' => $subdomain,
'domain_id' => $domainId,
'address' => $destination,
'send' => 'Save!'
]),
CURLOPT_USERAGENT => 'Mozilla/5.0',
CURLOPT_FOLLOWLOCATION => true
]);
$response = curl_exec($ch);
$httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
curl_close($ch);
if (strpos($response, 'ERROR') !== false) {
preg_match('/ERROR[^<]*/', $response, $err);
return ['success' => false, 'error' => $err[0] ?? 'Unknown error'];
}
return ['success' => true, 'domain' => "$subdomain.$baseDomain"];
}
public function deleteSubdomain($freednsId) {
$ch = curl_init($this->baseUrl . "/subdomain/delete2.php?data_id[]=$freednsId&submit=delete");
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_COOKIE => $this->cookie,
CURLOPT_USERAGENT => 'Mozilla/5.0',
CURLOPT_FOLLOWLOCATION => true
]);
$response = curl_exec($ch);
curl_close($ch);
return ['success' => true];
}
public function getAvailableBaseDomains() {
$ch = curl_init($this->baseUrl . '/domain/registry/');
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_COOKIE => $this->cookie,
CURLOPT_USERAGENT => 'Mozilla/5.0'
]);
$html = curl_exec($ch);
curl_close($ch);
$domains = [];
preg_match_all('/ | ]*>([a-z0-9.-]+\.[a-z]{2,})<\/td>/i', $html, $matches);
return array_unique($matches[1] ?? []);
}
}
// Cloudflare API Class
class CloudflareAPI {
private $email;
private $apiKey;
private $apiToken;
private $baseUrl = 'https://api.cloudflare.com/client/v4';
public function __construct($accountId = null) {
if ($accountId) {
$pdo = getDB();
$stmt = $pdo->prepare("SELECT * FROM admin.cloudflare_accounts WHERE id = ?");
$stmt->execute([$accountId]);
$account = $stmt->fetch(PDO::FETCH_ASSOC);
$this->email = $account['email'];
$this->apiKey = $account['api_key'];
$this->apiToken = $account['api_token'];
}
}
public function setCredentials($email, $apiKey, $apiToken = null) {
$this->email = $email;
$this->apiKey = $apiKey;
$this->apiToken = $apiToken;
}
private function request($endpoint, $method = 'GET', $data = null) {
$ch = curl_init($this->baseUrl . $endpoint);
$headers = ['Content-Type: application/json'];
if ($this->apiToken) {
$headers[] = 'Authorization: Bearer ' . $this->apiToken;
} else {
$headers[] = 'X-Auth-Email: ' . $this->email;
$headers[] = 'X-Auth-Key: ' . $this->apiKey;
}
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_HTTPHEADER => $headers,
CURLOPT_CUSTOMREQUEST => $method
]);
if ($data && in_array($method, ['POST', 'PUT', 'PATCH'])) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data));
}
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
public function verifyToken() {
return $this->request('/user/tokens/verify');
}
public function listZones() {
return $this->request('/zones?per_page=50');
}
public function getZone($zoneId) {
return $this->request("/zones/$zoneId");
}
public function createZone($domain, $accountId = null) {
$data = ['name' => $domain, 'jump_start' => true];
if ($accountId) $data['account'] = ['id' => $accountId];
return $this->request('/zones', 'POST', $data);
}
public function deleteZone($zoneId) {
return $this->request("/zones/$zoneId", 'DELETE');
}
public function listDNSRecords($zoneId) {
return $this->request("/zones/$zoneId/dns_records?per_page=100");
}
public function createDNSRecord($zoneId, $type, $name, $content, $ttl = 1, $proxied = false) {
return $this->request("/zones/$zoneId/dns_records", 'POST', [
'type' => $type,
'name' => $name,
'content' => $content,
'ttl' => $ttl,
'proxied' => $proxied
]);
}
public function updateDNSRecord($zoneId, $recordId, $type, $name, $content, $ttl = 1, $proxied = false) {
return $this->request("/zones/$zoneId/dns_records/$recordId", 'PUT', [
'type' => $type,
'name' => $name,
'content' => $content,
'ttl' => $ttl,
'proxied' => $proxied
]);
}
public function deleteDNSRecord($zoneId, $recordId) {
return $this->request("/zones/$zoneId/dns_records/$recordId", 'DELETE');
}
// Bulk operations
public function bulkCreateRecords($zoneId, $records) {
$results = [];
foreach ($records as $record) {
$results[] = $this->createDNSRecord(
$zoneId,
$record['type'],
$record['name'],
$record['content'],
$record['ttl'] ?? 1,
$record['proxied'] ?? false
);
}
return $results;
}
// Email routing setup
public function setupEmailRouting($zoneId, $mxRecords, $spfRecord, $dkimRecord = null, $dmarcRecord = null) {
$results = [];
// MX Records
foreach ($mxRecords as $priority => $server) {
$results[] = $this->createDNSRecord($zoneId, 'MX', '@', $server, 1, false);
}
// SPF
if ($spfRecord) {
$results[] = $this->createDNSRecord($zoneId, 'TXT', '@', $spfRecord, 1, false);
}
// DKIM
if ($dkimRecord) {
$results[] = $this->createDNSRecord($zoneId, 'TXT', 'default._domainkey', $dkimRecord, 1, false);
}
// DMARC
if ($dmarcRecord) {
$results[] = $this->createDNSRecord($zoneId, 'TXT', '_dmarc', $dmarcRecord, 1, false);
}
return $results;
}
}
// API Handler
if (isset($_GET['action']) || isset($_POST['action'])) {
header('Content-Type: application/json');
ensureTables();
$action = $_GET['action'] ?? $_POST['action'];
$pdo = getDB();
try {
switch ($action) {
// Stats
case 'stats':
echo json_encode(['success' => true, 'stats' => [
'freedns_accounts' => $pdo->query("SELECT COUNT(*) FROM admin.freedns_accounts")->fetchColumn(),
'freedns_domains' => $pdo->query("SELECT COUNT(*) FROM admin.freedns_domains")->fetchColumn(),
'cloudflare_accounts' => $pdo->query("SELECT COUNT(*) FROM admin.cloudflare_accounts")->fetchColumn(),
'cloudflare_zones' => $pdo->query("SELECT COUNT(*) FROM admin.cloudflare_zones")->fetchColumn(),
]]);
break;
// ============ FreeDNS ============
case 'freedns_add_account':
$username = $_POST['username'] ?? '';
$password = $_POST['password'] ?? '';
$api = new FreeDNSAPI();
$login = $api->login($username, $password);
if ($login['success']) {
$stmt = $pdo->prepare("INSERT INTO admin.freedns_accounts (username, password, cookie, last_login) VALUES (?, ?, ?, NOW()) RETURNING id");
$stmt->execute([$username, $password, $login['cookie']]);
$id = $stmt->fetchColumn();
echo json_encode(['success' => true, 'id' => $id]);
} else {
echo json_encode($login);
}
break;
case 'freedns_list_accounts':
$accounts = $pdo->query("SELECT id, username, domains_count, max_domains, status, last_login, created_at FROM admin.freedns_accounts ORDER BY id")->fetchAll(PDO::FETCH_ASSOC);
echo json_encode(['success' => true, 'accounts' => $accounts]);
break;
case 'freedns_refresh_account':
$accountId = $_POST['account_id'] ?? 0;
$api = new FreeDNSAPI($accountId);
// Re-login
$stmt = $pdo->prepare("SELECT username, password FROM admin.freedns_accounts WHERE id = ?");
$stmt->execute([$accountId]);
$acc = $stmt->fetch(PDO::FETCH_ASSOC);
$login = $api->login($acc['username'], $acc['password']);
if ($login['success']) {
$pdo->exec("UPDATE admin.freedns_accounts SET cookie = " . $pdo->quote($login['cookie']) . ", last_login = NOW() WHERE id = $accountId");
// Get domains
$api = new FreeDNSAPI($accountId);
$domains = $api->getDomains();
$pdo->exec("UPDATE admin.freedns_accounts SET domains_count = " . count($domains) . " WHERE id = $accountId");
echo json_encode(['success' => true, 'domains_count' => count($domains)]);
} else {
echo json_encode($login);
}
break;
case 'freedns_get_domains':
$accountId = $_GET['account_id'] ?? 0;
$api = new FreeDNSAPI($accountId);
$domains = $api->getDomains();
echo json_encode(['success' => true, 'domains' => $domains]);
break;
case 'freedns_add_subdomain':
$accountId = $_POST['account_id'] ?? 0;
$subdomain = $_POST['subdomain'] ?? '';
$baseDomain = $_POST['base_domain'] ?? '';
$type = $_POST['type'] ?? 'A';
$destination = $_POST['destination'] ?? '';
// Find account with space
if (!$accountId) {
$stmt = $pdo->query("SELECT id FROM admin.freedns_accounts WHERE domains_count < max_domains AND status = 'active' ORDER BY domains_count ASC LIMIT 1");
$accountId = $stmt->fetchColumn();
}
if (!$accountId) {
echo json_encode(['success' => false, 'error' => 'No available account (all at max domains)']);
break;
}
$api = new FreeDNSAPI($accountId);
$result = $api->addSubdomain($subdomain, $baseDomain, $type, $destination);
if ($result['success']) {
$stmt = $pdo->prepare("INSERT INTO admin.freedns_domains (account_id, domain, base_domain, domain_type) VALUES (?, ?, ?, 'subdomain')");
$stmt->execute([$accountId, $result['domain'], $baseDomain]);
$pdo->exec("UPDATE admin.freedns_accounts SET domains_count = domains_count + 1 WHERE id = $accountId");
}
echo json_encode($result);
break;
case 'freedns_delete_subdomain':
$domainId = $_POST['domain_id'] ?? 0;
$freednsId = $_POST['freedns_id'] ?? '';
$stmt = $pdo->prepare("SELECT account_id FROM admin.freedns_domains WHERE id = ?");
$stmt->execute([$domainId]);
$accountId = $stmt->fetchColumn();
$api = new FreeDNSAPI($accountId);
$result = $api->deleteSubdomain($freednsId);
if ($result['success']) {
$pdo->exec("DELETE FROM admin.freedns_domains WHERE id = $domainId");
$pdo->exec("UPDATE admin.freedns_accounts SET domains_count = domains_count - 1 WHERE id = $accountId");
}
echo json_encode($result);
break;
case 'freedns_base_domains':
$accountId = $_GET['account_id'] ?? 0;
$api = new FreeDNSAPI($accountId);
$domains = $api->getAvailableBaseDomains();
echo json_encode(['success' => true, 'domains' => $domains]);
break;
case 'freedns_bulk_create':
$subdomains = json_decode($_POST['subdomains'] ?? '[]', true);
$baseDomain = $_POST['base_domain'] ?? '';
$type = $_POST['type'] ?? 'A';
$destination = $_POST['destination'] ?? '';
$results = ['success' => 0, 'failed' => 0, 'errors' => []];
foreach ($subdomains as $sub) {
// Find account with space
$stmt = $pdo->query("SELECT id FROM admin.freedns_accounts WHERE domains_count < max_domains AND status = 'active' ORDER BY domains_count ASC LIMIT 1");
$accountId = $stmt->fetchColumn();
if (!$accountId) {
$results['failed']++;
$results['errors'][] = "No available account for $sub";
continue;
}
$api = new FreeDNSAPI($accountId);
$result = $api->addSubdomain($sub, $baseDomain, $type, $destination);
if ($result['success']) {
$stmt = $pdo->prepare("INSERT INTO admin.freedns_domains (account_id, domain, base_domain, domain_type) VALUES (?, ?, ?, 'subdomain')");
$stmt->execute([$accountId, $result['domain'], $baseDomain]);
$pdo->exec("UPDATE admin.freedns_accounts SET domains_count = domains_count + 1 WHERE id = $accountId");
$results['success']++;
} else {
$results['failed']++;
$results['errors'][] = $result['error'] ?? 'Unknown error';
}
usleep(500000); // 0.5s delay
}
echo json_encode(['success' => true, 'results' => $results]);
break;
// ============ Cloudflare ============
case 'cf_add_account':
$email = $_POST['email'] ?? '';
$apiKey = $_POST['api_key'] ?? '';
$apiToken = $_POST['api_token'] ?? '';
$api = new CloudflareAPI();
$api->setCredentials($email, $apiKey, $apiToken);
$verify = $api->verifyToken();
if ($verify['success'] ?? false) {
$stmt = $pdo->prepare("INSERT INTO admin.cloudflare_accounts (email, api_key, api_token) VALUES (?, ?, ?) RETURNING id");
$stmt->execute([$email, $apiKey, $apiToken]);
$id = $stmt->fetchColumn();
echo json_encode(['success' => true, 'id' => $id]);
} else {
echo json_encode(['success' => false, 'error' => $verify['errors'][0]['message'] ?? 'Invalid credentials']);
}
break;
case 'cf_list_accounts':
$accounts = $pdo->query("SELECT id, email, status, created_at FROM admin.cloudflare_accounts ORDER BY id")->fetchAll(PDO::FETCH_ASSOC);
echo json_encode(['success' => true, 'accounts' => $accounts]);
break;
case 'cf_list_zones':
$accountId = $_GET['account_id'] ?? 0;
$api = new CloudflareAPI($accountId);
$result = $api->listZones();
if ($result['success'] ?? false) {
// Sync to DB
foreach ($result['result'] as $zone) {
$stmt = $pdo->prepare("INSERT INTO admin.cloudflare_zones (account_id, zone_id, domain, status, name_servers)
VALUES (?, ?, ?, ?, ?) ON CONFLICT (zone_id) DO UPDATE SET status = ?, name_servers = ?");
$ns = implode(',', $zone['name_servers'] ?? []);
$stmt->execute([$accountId, $zone['id'], $zone['name'], $zone['status'], $ns, $zone['status'], $ns]);
}
}
echo json_encode($result);
break;
case 'cf_add_zone':
$accountId = $_POST['account_id'] ?? 0;
$domain = $_POST['domain'] ?? '';
$api = new CloudflareAPI($accountId);
$result = $api->createZone($domain);
if ($result['success'] ?? false) {
$zone = $result['result'];
$stmt = $pdo->prepare("INSERT INTO admin.cloudflare_zones (account_id, zone_id, domain, status, name_servers) VALUES (?, ?, ?, ?, ?)");
$stmt->execute([$accountId, $zone['id'], $zone['name'], $zone['status'], implode(',', $zone['name_servers'] ?? [])]);
}
echo json_encode($result);
break;
case 'cf_delete_zone':
$accountId = $_POST['account_id'] ?? 0;
$zoneId = $_POST['zone_id'] ?? '';
$api = new CloudflareAPI($accountId);
$result = $api->deleteZone($zoneId);
if ($result['success'] ?? false) {
$pdo->exec("DELETE FROM admin.cloudflare_zones WHERE zone_id = " . $pdo->quote($zoneId));
}
echo json_encode($result);
break;
case 'cf_list_records':
$accountId = $_GET['account_id'] ?? 0;
$zoneId = $_GET['zone_id'] ?? '';
$api = new CloudflareAPI($accountId);
echo json_encode($api->listDNSRecords($zoneId));
break;
case 'cf_add_record':
$accountId = $_POST['account_id'] ?? 0;
$zoneId = $_POST['zone_id'] ?? '';
$type = $_POST['type'] ?? 'A';
$name = $_POST['name'] ?? '@';
$content = $_POST['content'] ?? '';
$ttl = intval($_POST['ttl'] ?? 1);
$proxied = ($_POST['proxied'] ?? '0') === '1';
$api = new CloudflareAPI($accountId);
echo json_encode($api->createDNSRecord($zoneId, $type, $name, $content, $ttl, $proxied));
break;
case 'cf_delete_record':
$accountId = $_POST['account_id'] ?? 0;
$zoneId = $_POST['zone_id'] ?? '';
$recordId = $_POST['record_id'] ?? '';
$api = new CloudflareAPI($accountId);
echo json_encode($api->deleteDNSRecord($zoneId, $recordId));
break;
case 'cf_setup_email':
$accountId = $_POST['account_id'] ?? 0;
$zoneId = $_POST['zone_id'] ?? '';
$ip = $_POST['ip'] ?? '';
$domain = $_POST['domain'] ?? '';
$api = new CloudflareAPI($accountId);
// Standard email records
$results = [];
// A record
$results[] = $api->createDNSRecord($zoneId, 'A', '@', $ip, 1, false);
$results[] = $api->createDNSRecord($zoneId, 'A', 'mail', $ip, 1, false);
// MX
$results[] = $api->createDNSRecord($zoneId, 'MX', '@', "mail.$domain", 1, false);
// SPF
$results[] = $api->createDNSRecord($zoneId, 'TXT', '@', "v=spf1 ip4:$ip ~all", 1, false);
// DMARC
$results[] = $api->createDNSRecord($zoneId, 'TXT', '_dmarc', 'v=DMARC1; p=none; rua=mailto:dmarc@'.$domain, 1, false);
echo json_encode(['success' => true, 'results' => $results]);
break;
case 'cf_bulk_add_records':
$accountId = $_POST['account_id'] ?? 0;
$zoneId = $_POST['zone_id'] ?? '';
$records = json_decode($_POST['records'] ?? '[]', true);
$api = new CloudflareAPI($accountId);
$results = $api->bulkCreateRecords($zoneId, $records);
echo json_encode(['success' => true, 'results' => $results]);
break;
default:
echo json_encode(['success' => false, 'error' => 'Unknown action']);
}
} catch (Exception $e) {
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
}
exit;
}
ensureTables();
?>
DNS Manager - FreeDNS & Cloudflare
Add FreeDNS Account
FreeDNS limite à 5 domaines par compte. Créez plusieurs comptes pour plus de domaines.
FreeDNS Accounts
| ID | Username | Domains | Capacity | Status | Last Login | Actions |
Create Subdomain
My Subdomains
| Domain | Base | Account | Status | Actions |
Cloudflare Accounts
| ID | Email | Status | Created | Actions |
Zones
Select an account to view zones
DNS Records -
| Type | Name | Content | Proxied | TTL | Actions |
|