Удалить DNS Resolver Pro

This commit is contained in:
2026-01-12 12:54:07 +00:00
parent be5d41b468
commit fe9e67ee8e

View File

@@ -1,345 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>DNS Resolver Pro</title>
<link rel="icon" href="https://rockblack.pro/images/favicon.ico" type="image/x-icon">
<style>
body {
font-family: 'Helvetica Neue', 'Segoe UI', Arial, sans-serif;
margin: 0 auto;
padding: 30px;
max-width: 800px;
background: #0f0f0f;
color: #fff;
line-height: 1.6;
}
body.light-mode {
background: #f8f9fa;
color: #333;
}
h2 {
text-align: center;
font-size: 2.2em;
margin-bottom: 30px;
color: #4CAF50;
}
.input-group {
margin: 20px 0;
}
textarea {
width: 100%;
height: 150px;
padding: 15px;
border-radius: 8px;
border: 2px solid #2d2d2d;
background: #1a1a1a;
color: #fff;
font-family: 'Courier New', monospace;
}
body.light-mode textarea {
background: #fff;
border-color: #ddd;
color: #333;
}
.controls {
display: flex;
gap: 15px;
flex-wrap: wrap;
margin: 25px 0;
justify-content: center;
}
select, button {
padding: 12px 20px;
border-radius: 8px;
border: none;
font-weight: 600;
cursor: pointer;
}
select {
background: #1a1a1a;
color: #fff;
border: 2px solid #4CAF50;
}
body.light-mode select {
background: #fff;
border-color: #2196F3;
color: #333;
}
button {
background: linear-gradient(135deg, #4CAF50, #45a049);
color: white;
}
.theme-toggle {
background: linear-gradient(135deg, #673AB7, #512DA8);
}
pre {
background: #1a1a1a;
padding: 20px;
border-radius: 8px;
white-space: pre-wrap;
border: 2px solid #2d2d2d;
font-family: 'Courier New', monospace;
}
body.light-mode pre {
background: #fff;
border-color: #ddd;
}
.progress-container {
width: 100%;
height: 20px;
background-color: #1a1a1a;
border-radius: 10px;
margin: 20px 0;
overflow: hidden;
display: none;
}
.progress-bar {
height: 100%;
background: linear-gradient(90deg, #4CAF50, #45a049);
width: 0%;
transition: width 0.3s ease;
text-align: center;
color: white;
font-size: 12px;
line-height: 20px;
}
body.light-mode .progress-container {
background-color: #eee;
}
body.light-mode .progress-bar {
background: linear-gradient(90deg, #2196F3, #1976D2);
}
</style>
</head>
<body>
<h2>🔍 DNS Resolver Pro</h2>
<div class="input-group">
<textarea id="domains" placeholder="Введите домены каждый с новой строки"></textarea>
</div>
<div class="progress-container">
<div class="progress-bar" id="progressBar">0%</div>
</div>
<div class="controls">
<select id="format">
<option value="standard">IPv4</option>
<option value="keenetic">Keenetic</option>
<option value="keenetic_clear">Keenetic route</option>
<option value="keenetic_ip_min">Keenetic route Min</option>
</select>
<button onclick="resolveDomains()">🚀 Найти IP</button>
<button onclick="saveToTxt()">💾 Сохранить в TXT</button>
<button class="theme-toggle" onclick="toggleTheme()">🌓 Сменить тему</button>
</div>
<pre id="result">Результаты появятся здесь...</pre>
<script>
function normalizeDomain(input) {
// Обработка URL (https://example.com)
if (input.includes('://')) {
try {
const url = new URL(input);
return url.hostname;
} catch (e) {
return input;
}
}
// Обработка формата: 0: "example.com"
const matchIndex = input.match(/^\s*\d+\s*:\s*"([^"]+)"\s*$/);
if (matchIndex && matchIndex[1]) {
return matchIndex[1];
}
// Обработка формата: "example.com",
const matchQuotes = input.match(/^\s*"([^"]+)"\s*,?\s*$/);
if (matchQuotes && matchQuotes[1]) {
return matchQuotes[1];
}
return input.trim();
}
async function fetchDNSFromResolver(resolverName, url) {
try {
const options = (resolverName === 'Cloudflare')
? { headers: { "accept": "application/dns-json" } }
: {};
const response = await fetch(url, options);
const data = await response.json();
return { resolver: resolverName, data };
} catch (error) {
return { resolver: resolverName, error: error.message };
}
}
async function resolveDomainWithResolvers(domain) {
const resolvers = [
{ name: "Google", url: `https://dns.google/resolve?name=${domain}&type=A` },
{ name: "Cloudflare", url: `https://cloudflare-dns.com/dns-query?name=${domain}&type=A` }
];
const promises = resolvers.map(r => fetchDNSFromResolver(r.name, r.url));
return await Promise.all(promises);
}
async function resolveDomains() {
const domainsText = document.getElementById("domains").value;
const rawLines = domainsText.split('\n').filter(line => line.trim() !== "");
const domains = rawLines.map(normalizeDomain).filter(domain => domain !== "");
const format = document.getElementById("format").value;
const progressContainer = document.querySelector('.progress-container');
const progressBar = document.getElementById('progressBar');
progressContainer.style.display = 'block';
progressBar.style.width = '0%';
progressBar.textContent = '0%';
let output = "";
if (domains.length === 0) {
document.getElementById("result").textContent = "Пожалуйста, введите хотя бы один домен.";
progressContainer.style.display = 'none';
return;
}
const totalDomains = domains.length;
let processed = 0;
const updateProgress = () => {
const percent = Math.round((processed / totalDomains) * 100);
progressBar.style.width = `${percent}%`;
progressBar.textContent = `${percent}%`;
if (percent === 100) {
setTimeout(() => {
progressContainer.style.display = 'none';
}, 500);
}
};
if (format === "keenetic_clear") {
const uniqueIPs = new Set();
for (let domain of domains) {
try {
const results = await resolveDomainWithResolvers(domain);
results.forEach(result => {
if (result.data?.Answer) {
result.data.Answer
.filter(ans => ans.type === 1)
.forEach(ans => uniqueIPs.add(ans.data));
}
});
} catch (error) {}
processed++;
updateProgress();
}
output = Array.from(uniqueIPs)
.map(ip => `route add ${ip} mask 255.255.255.255 0.0.0.0`)
.join('\n');
} else if (format === "keenetic_ip_min") {
const uniqueIPs = new Set();
for (let domain of domains) {
try {
const results = await resolveDomainWithResolvers(domain);
results.forEach(result => {
if (result.data?.Answer) {
result.data.Answer
.filter(ans => ans.type === 1)
.forEach(ans => uniqueIPs.add(ans.data));
}
});
} catch (error) {}
processed++;
updateProgress();
}
// Группировка IP в подсети /24
const cidrMap = new Map();
uniqueIPs.forEach(ip => {
if (ip === "0.0.0.0" || ip === "255.255.255.255") return;
const octets = ip.split('.').map(Number);
const network = `${octets[0]}.${octets[1]}.${octets[2]}.0/24`;
cidrMap.set(network, true);
});
// Сортировка подсетей
const sortedCidrs = Array.from(cidrMap.keys()).sort((a, b) => {
const aParts = a.split('.').map(Number);
const bParts = b.split('.').map(Number);
for (let i = 0; i < 3; i++) {
if (aParts[i] !== bParts[i]) {
return aParts[i] - bParts[i];
}
}
return 0;
});
output = sortedCidrs
.map(cidr => `route add ${cidr.split('/')[0]} mask 255.255.255.0 0.0.0.0`)
.join('\n');
} else {
for (let domain of domains) {
output += `Домен: ${domain}\n`;
try {
const results = await resolveDomainWithResolvers(domain);
results.forEach(result => {
output += ` [${result.resolver}]\n`;
if (result.error) {
output += ` Ошибка: ${result.error}\n`;
} else if (result.data?.Answer) {
const aRecords = result.data.Answer.filter(ans => ans.type === 1);
if (aRecords.length > 0) {
aRecords.forEach(ans => {
const ip = ans.data;
if (format === "keenetic") {
output += ` route add ${ip} mask 255.255.255.255 0.0.0.0\n`;
} else {
output += ` ${ip}\n`;
}
});
} else {
output += ` Нет A записей.\n`;
}
} else {
output += ` Нет ответа.\n`;
}
});
} catch (error) {
output += ` Ошибка: ${error.message}\n`;
}
processed++;
updateProgress();
output += "\n";
}
}
document.getElementById("result").textContent = output.trim() || "Не удалось получить IP-адреса.";
updateProgress();
}
function toggleTheme() {
document.body.classList.toggle('light-mode');
}
function saveToTxt() {
const content = document.getElementById("result").textContent;
if (!content || content.trim() === "Результаты появятся здесь...") {
alert("Нет данных для сохранения.");
return;
}
const blob = new Blob([content], { type: "text/plain;charset=utf-8" });
const link = document.createElement("a");
link.href = URL.createObjectURL(blob);
link.download = "dns_result.txt";
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
}
</script>
</body>
</html>