commit 52dff0567315f0f18530de5a9d018c38e4060ff6 Author: deepend Date: Wed Jan 10 13:12:05 2024 -0700 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a646221 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +includes/initdb.php diff --git a/README.md b/README.md new file mode 100644 index 0000000..e69de29 diff --git a/css/styles.css b/css/styles.css new file mode 100644 index 0000000..d52a9f3 --- /dev/null +++ b/css/styles.css @@ -0,0 +1,130 @@ +body { + font-family: 'Courier New', monospace; + background-color: #000; + margin: 0; + padding: 20px; + color: #0f0; /* Green text, typical of classic terminals */ +} + +h1, h2 { + color: #0f0; + border-bottom: 1px solid #0f0; + padding-bottom: 10px; +} +.content { + background-color: #222; /* Darker background for content */ + padding: 20px; + margin-top: 20px; + border-radius: 8px; +} + +.info-section, .server-list { + margin-bottom: 20px; +} + +form { + background: #000; /* Black background */ + padding: 20px; + margin-bottom: 20px; + border: 1px solid #0f0; /* Green border */ + box-shadow: none; +} + +input[type="text"], +input[type="password"] { + padding: 10px; + margin: 10px 0; + background: #222; /* Dark gray background */ + border: 1px solid #0f0; /* Green border */ + color: #0f0; /* Green text */ + border-radius: 0; /* Square corners */ + box-sizing: border-box; + width: 100%; +} + +input[type="submit"], +input[type="button"] { + padding: 10px 20px; + margin: 10px 0; + background-color: #222; /* Dark gray background */ + color: #0f0; /* Green text */ + border: 1px solid #0f0; /* Green border */ + cursor: pointer; + display: inline-block; + width: auto; + border-radius: 0; /* Square corners */ +} + +input[type="submit"]:hover, +input[type="button"]:hover { + background-color: #333; /* Slightly lighter gray */ +} + +ul { + list-style-type: none; + padding: 0; + margin-top: 10px; +} + +li { + background: #000; /* Black background */ + margin-bottom: 10px; + padding: 20px; + border: 1px solid #0f0; /* Green border */ + box-shadow: none; + border-radius: 0; /* Square corners */ +} + +a { + color: #4af; + text-decoration: none; +} + +a:hover { + text-decoration: underline; + color: #7cf; +} + + .status { + font-weight: bold; + } + .online { + color: green; + } + .offline { + color: red; + } + +/* Centering form buttons */ +form { + text-align: center; +} + +/* Aligning form inputs to the left */ +form input[type="text"], +form input[type="password"] { + margin-left: auto; + margin-right: auto; + display: block; +} + .domain-input-container { + display: flex; + justify-content: center; + align-items: center; + margin: 10px 0; + } + + .tilde-extension { + padding: 10px; + border: 1px solid #ddd; + border-radius: 0 4px 4px 0; /* Rounded right corners */ + } + + .result { + margin-top: 20px; + } + .register-link { + color: #337ab7; + text-decoration: none; + font-weight: bold; + } diff --git a/dns_cron.php b/dns_cron.php new file mode 100644 index 0000000..c489af8 --- /dev/null +++ b/dns_cron.php @@ -0,0 +1,123 @@ +query("SELECT domain_name FROM domains"); + return $stmt->fetchAll(PDO::FETCH_COLUMN, 0); +} + +// Function to fetch all domains +function getAllDomains($pdo) { + $stmt = $pdo->query("SELECT domain_name, ip_address FROM domains"); + return $stmt->fetchAll(PDO::FETCH_ASSOC); +} + +// Function to generate BIND DNS file content +function generateDnsFileContent($domain, $ipAddress) { + $content = "; BIND data file for $domain\n"; + $content .= "\$TTL 604800\n"; + $content .= "@ IN SOA ns1.master.tilde. root.$domain. (\n"; + $content .= " " . date('Ymd') . "01 ; Serial\n"; // Date-based serial + $content .= " 604800 ; Refresh\n"; + $content .= " 86400 ; Retry\n"; + $content .= " 2419200 ; Expire\n"; + $content .= " 604800 ) ; Negative Cache TTL\n"; + $content .= ";\n"; + $content .= "@ IN NS ns1.master.tilde.\n"; + $content .= "@ IN NS ns2.master.tilde.\n"; + $content .= "www IN CNAME $domain\n"; + $content .= "@ IN A $ipAddress\n"; + $content .= "* IN A $ipAddress\n"; // Wildcard A record + // Add more DNS records as needed + return $content; +} + +// Change to the Git repository directory +chdir('/home/retrodig/dottilde'); + +// Perform a git pull to ensure the repository is up to date + exec('git pull'); + +// Fetch domain names from the database +$databaseDomains = getAllDomainNames($pdo); + +// Fetch domains and generate/update DNS files +$domains = getAllDomains($pdo); +$currentFiles = glob('db.*'); // Get all current db files +$changes = false; + +foreach ($domains as $domain) { + $filename = "db." . $domain['domain_name']; + $content = generateDnsFileContent($domain['domain_name'], $domain['ip_address']); + + if (!file_exists($filename) || $content !== file_get_contents($filename)) { + file_put_contents($filename, $content); + $changes = true; + writeToLog("Updated or created DNS file: $filename", $logFile); + } + + // Remove filename from the list of current files if it's in the database + if (($key = array_search($filename, $currentFiles)) !== false) { + unset($currentFiles[$key]); + } +} + + +// Function to update named.conf.local file +function updateNamedConfLocal($domains, $namedConfPath, $logFile) { + $confContent = "// Dynamic BIND configuration\n\n"; + + foreach ($domains as $domain) { + $zoneEntry = "zone \"" . $domain['domain_name'] . "\" {\n"; + $zoneEntry .= "\ttype master;\n"; + $zoneEntry .= "\tfile \"/etc/bind/db." . $domain['domain_name'] . "\";\n"; + $zoneEntry .= "};\n\n"; + $confContent .= $zoneEntry; + } + + // Write the new configuration to the file + file_put_contents($namedConfPath, $confContent); + writeToLog("Updated named.conf.local", $logFile); +} + +// Define the path to named.conf.local +$namedConfPath = '/home/retrodig/dottilde/named.conf.local'; + +// Update named.conf.local with current domains +updateNamedConfLocal($domains, $namedConfPath, $logFile); + +// List of DNS files that should never be deleted +$protectedFiles = ['db.master.tilde', 'db.tilde.tilde', 'db.nic.tilde']; // Add your protected filenames here + +// Delete any remaining files that are no longer in the database +foreach ($currentFiles as $file) { + $domainName = substr($file, 3); // Extract domain name from filename + if (!in_array($domainName, $databaseDomains) && !in_array($file, $protectedFiles)) { + unlink($file); + $changes = true; + writeToLog("Deleted orphaned DNS file: $file", $logFile); + } +} + +// Close the log file +fclose($logFile); + +// Git commit and push if there are changes +if ($changes) { + exec('git add .'); + exec('git commit -m "Updated DNS files"'); + exec('git push origin master'); +} + diff --git a/includes/dns_cron.php b/includes/dns_cron.php new file mode 100644 index 0000000..7186452 --- /dev/null +++ b/includes/dns_cron.php @@ -0,0 +1,87 @@ +query("SELECT domain_name, ip_address FROM domains"); + return $stmt->fetchAll(PDO::FETCH_ASSOC); +} + +// Function to generate BIND DNS file content +function generateDnsFileContent($domain, $ipAddress) { + $content = "; BIND data file for $domain\n"; + $content .= "\$TTL 604800\n"; + $content .= "@ IN SOA ns1.master.tilde. root.$domain. (\n"; + $content .= " " . date('Ymd') . "01 ; Serial\n"; // Date-based serial + $content .= " 604800 ; Refresh\n"; + $content .= " 86400 ; Retry\n"; + $content .= " 2419200 ; Expire\n"; + $content .= " 604800 ) ; Negative Cache TTL\n"; + $content .= ";\n"; + $content .= "@ IN NS ns1.master.tilde.\n"; + $content .= "@ IN NS ns2.master.tilde.\n"; + $content .= "www IN CNAME $domain\n"; + $content .= "@ IN A $ipAddress\n"; + $content .= "* IN A $ipAddress\n"; // Wildcard A record + // Add more DNS records as needed + return $content; +} + +// Change to the Git repository directory +chdir('../dottilde'); + +// Perform a git pull to ensure the repository is up to date +exec('git pull'); + +// Fetch domains and generate DNS files +$domains = getAllDomains($pdo); +$changes = false; +$currentFiles = glob('db.*'); // Get all current db files + +writeToLog("Current files before processing: " . implode(', ', $currentFiles), $logFile); + +foreach ($domains as $domain) { + $filename = "db." . $domain['domain_name']; + $content = generateDnsFileContent($domain['domain_name'], $domain['ip_address']); + + // Check if file content is different from existing file + if (!file_exists($filename) || $content !== file_get_contents($filename)) { + file_put_contents($filename, $content); + $changes = true; + } + + // Remove filename from the list of current files + if (($key = array_search($filename, $currentFiles)) !== false) { + unset($currentFiles[$key]); + } +} + +writeToLog("Files to be deleted: " . implode(', ', $currentFiles), $logFile); + +// Delete any remaining files that are no longer in the database +foreach ($currentFiles as $file) { + writeToLog("Deleting file: $file", $logFile); + unlink($file); + $changes = true; +} + +// Close the log file +fclose($logFile); + +// Git commit and push if there are changes +if ($changes) { +// exec('git add .'); +// exec('git commit -m "Updated DNS files"'); +// exec('git push origin master'); +} \ No newline at end of file diff --git a/includes/domain_register.php b/includes/domain_register.php new file mode 100644 index 0000000..6686b0c --- /dev/null +++ b/includes/domain_register.php @@ -0,0 +1,94 @@ +prepare("INSERT INTO domains (user_id, domain_name) VALUES (?, ?)"); + $stmt->execute([$userId, $domain]); + return "Domain registered successfully: " . htmlspecialchars($domain); + } catch (PDOException $e) { + if ($e->getCode() == 23000) { + return "Error: The domain '$domain' is already registered."; + } else { + return "Error: An error occurred while registering the domain."; + } + } +} + +// Function to get user ID +function getUserId($username, $pdo) { + $stmt = $pdo->prepare("SELECT id FROM users WHERE username = ?"); + $stmt->execute([$username]); + return $stmt->fetchColumn(); +} + +// Handle domain registration +$message = ''; +if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_POST['registerdomain'])) { + $domain = $_POST['registerdomain'] . '.tilde'; + $userId = getUserId($_SESSION['username'], $pdo); + + $message = registerDomain($domain, $userId, $pdo, $restrictedDomains); +} +?> + + + + + + Register Domain + + + + +
+ +
+

Register Domain

+
+
+ + + .tilde +
+ +
+ +

+ + + \ No newline at end of file diff --git a/includes/initdb-template.php b/includes/initdb-template.php new file mode 100644 index 0000000..4ab54bf --- /dev/null +++ b/includes/initdb-template.php @@ -0,0 +1,47 @@ + PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false, +]; + +try { + // Create a PDO instance (connect to the database) + $pdo = new PDO($dsn, $user, $pass, $options); + + // SQL for creating tables + // Users table + $pdo->exec("CREATE TABLE IF NOT EXISTS users ( + id INT AUTO_INCREMENT PRIMARY KEY, + username VARCHAR(255) NOT NULL UNIQUE, + password VARCHAR(255) NOT NULL, + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP + ) ENGINE=InnoDB;"); + + // Domains table with added ip_address column + $pdo->exec("CREATE TABLE IF NOT EXISTS domains ( + id INT AUTO_INCREMENT PRIMARY KEY, + user_id INT NOT NULL, + domain_name VARCHAR(255) NOT NULL UNIQUE, + dns_records TEXT, + ip_address VARCHAR(15), -- Added column for IP address + created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP, + FOREIGN KEY (user_id) REFERENCES users(id) + ) ENGINE=InnoDB;"); + +} catch (\PDOException $e) { + throw new \PDOException($e->getMessage(), (int)$e->getCode()); +} diff --git a/includes/login.php b/includes/login.php new file mode 100644 index 0000000..26aad04 --- /dev/null +++ b/includes/login.php @@ -0,0 +1,53 @@ +prepare("SELECT password FROM users WHERE username = ?"); + $stmt->execute([$username]); + $user = $stmt->fetch(); + return $user && password_verify($password, $user['password']); +} + +// Handle login +if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['login'])) { + $username = $_POST['username']; + $password = $_POST['password']; + + if (checkCredentials($username, $password, $pdo)) { + $_SESSION['username'] = $username; + header("Location: /?page=user_domains"); + exit; + } else { + $error = "Invalid username or password."; + } +} +?> + + + + + + Login + + + +

Login

+
+ + +
+ + +
+ + + +
+ +

+ + + diff --git a/includes/main.php b/includes/main.php new file mode 100644 index 0000000..bb32836 --- /dev/null +++ b/includes/main.php @@ -0,0 +1,126 @@ + $nsName, 'ipv4' => $ipv4, 'ipv6' => $ipv6]; + } + } + + return $servers; +} + +$dnsServers = getDnsServersInfo(); + +// Function to check server status +function checkServerStatus($server) { + // Ping command varies depending on the operating system + // This is an example for a Unix-like system + $output = []; + $status = null; + exec("ping -c 1 " . escapeshellarg($server), $output, $status); + + return $status === 0 ? "Online" : "Offline"; +} + +?> + + + + + + |--===TildeNIC ===--| Bringing .tilde to the Tildeverse! + + + +
+ +
+ +
+

Welcome to TildeNIC

+
+

TildeNIC is where you can request your .tilde top level domain. To do so, you need to first change your DNS over to one of the resolvers we offer, or you can self-host one.

+ +

NOTE! None of the servers currently listed are functional. They are old IP addresses. New servers will be online very soon!

+

+ OpenNIC Information +

+

+ Domains offered by OpenNIC are also able to be resolved using our servers, Such as: +

    +
  • .geek
  • +
  • .bbs
  • +
  • .gopher and more.
  • +
+ Will all resolve using our dns servers. For more information about OpenNIC you can visit http://opennic.org +

+
+ +
+

TildeNIC Available DNS Servers

+
    + + +
  • + - + IPv4: , + IPv6: - + + + +
  • + +
+
+
+ + \ No newline at end of file diff --git a/includes/register.php b/includes/register.php new file mode 100644 index 0000000..c6ab1b3 --- /dev/null +++ b/includes/register.php @@ -0,0 +1,58 @@ +prepare("INSERT INTO users (username, password) VALUES (?, ?)"); + $stmt->execute([$username, $hash]); +} + +// Function to check if username exists +function doesUserExist($username, $pdo) { + $stmt = $pdo->prepare("SELECT COUNT(*) FROM users WHERE username = ?"); + $stmt->execute([$username]); + return $stmt->fetchColumn() > 0; +} + +// Handle registration +if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['register'])) { + $username = $_POST['username']; + $password = $_POST['password']; + + if (!doesUserExist($username, $pdo)) { + registerUser($username, $password, $pdo); + $_SESSION['username'] = $username; + header("Location: https://tildenic.org/?page=domain_register"); + exit; + } else { + $error = "Username already exists."; + } +} +?> + + + + + + Register + + + +

Register

+
+ + +
+ + +
+ +
+ +

+ + + diff --git a/includes/user_domains.php b/includes/user_domains.php new file mode 100644 index 0000000..7feca33 --- /dev/null +++ b/includes/user_domains.php @@ -0,0 +1,118 @@ +prepare("SELECT id FROM users WHERE username = ?"); + $stmt->execute([$username]); + return $stmt->fetchColumn(); +} + +// Function to get user's domains +function getUserDomains($userId, $pdo) { + $stmt = $pdo->prepare("SELECT id, domain_name, ip_address FROM domains WHERE user_id = ?"); // Fetching ip_address + $stmt->execute([$userId]); + return $stmt->fetchAll(); +} + +// Function to remove a domain +function removeDomain($domainId, $pdo) { + $stmt = $pdo->prepare("DELETE FROM domains WHERE id = ?"); + $stmt->execute([$domainId]); +} + +// Function to update domain's IP address +function updateDomainIP($domainId, $ipAddress, $pdo) { + $stmt = $pdo->prepare("UPDATE domains SET ip_address = ? WHERE id = ?"); // Updating ip_address + $stmt->execute([$ipAddress, $domainId]); +} + +// Handle domain removal +if (isset($_GET['remove'])) { + removeDomain($_GET['remove'], $pdo); + header("Location: https://tildenic.org/?page=user_domains"); + exit; +} + +// Handle IP address update +if ($_SERVER["REQUEST_METHOD"] == "POST" && isset($_POST['update_ip'])) { + $domainId = $_POST['domain_id']; + $ipAddress = $_POST['ip_address']; + updateDomainIP($domainId, $ipAddress, $pdo); + header("Location: https://tildenic.org/?page=user_domains"); + exit; +} +// Handle logout +if (isset($_POST['logout'])) { + session_destroy(); + header("Location: https://tildenic.org/?page=login"); + exit; +} +// Handle form submission +if ($_SERVER["REQUEST_METHOD"] == "POST") { + $domainId = $_POST['domain_id']; + + if (isset($_POST['update_ip'])) { + // Update IP address + $ipAddress = $_POST['ip_address']; + updateDomainIP($domainId, $ipAddress, $pdo); + } elseif (isset($_POST['remove_domain'])) { + // Remove domain + removeDomain($domainId, $pdo); + } + + header("Location: https://tildenic.org/?page=user_domains"); + exit; +} + +$userId = getUserId($_SESSION['username'], $pdo); +$domains = getUserDomains($userId, $pdo); +?> + + + + + + My Account + + + +
+ +
+

Your Domains

+ + + diff --git a/index.php b/index.php new file mode 100644 index 0000000..77eb7ab --- /dev/null +++ b/index.php @@ -0,0 +1,22 @@ +