| const TURNSTILE_SOLVER_URL = 'https://herzaj-turnstile-solver.hf.space'; | |
| async function getTurnstileToken() { | |
| try { | |
| const params = new URLSearchParams({ | |
| url: 'https://www.subdomainfinder.in', | |
| sitekey: '0x4AAAAAAAj7jyMV3Zv9ZMN-' | |
| }); | |
| const submitResponse = await fetch(`${TURNSTILE_SOLVER_URL}/turnstile?${params}`, { | |
| method: 'GET' | |
| }); | |
| if (!submitResponse.ok) { | |
| throw new Error(`Failed to submit task: ${submitResponse.status}`); | |
| } | |
| const taskData = await submitResponse.json(); | |
| const taskId = taskData.task_id; | |
| await new Promise(resolve => setTimeout(resolve, 5000)); | |
| const resultResponse = await fetch(`${TURNSTILE_SOLVER_URL}/result?id=${taskId}`); | |
| if (!resultResponse.ok) { | |
| throw new Error(`Failed to get result: ${resultResponse.status}`); | |
| } | |
| const resultData = await resultResponse.json(); | |
| return resultData.value; | |
| } catch (error) { | |
| throw new Error("Gagal mendapatkan Turnstile token: " + error.message); | |
| } | |
| } | |
| async function findSubdomains(domain, token) { | |
| const response = await fetch(`https://api.subdomainfinder.in/?domain=${domain}`, { | |
| method: 'GET', | |
| headers: { | |
| 'X-Secure-Token': token, | |
| 'X-Referer': 'https://www.google.com/', | |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' | |
| } | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`); | |
| } | |
| return await response.json(); | |
| } | |
| async function resolveDNS(subdomain) { | |
| const response = await fetch(`https://lookup.subdomainfinder.in/resolve?name=${subdomain}&rd=1`, { | |
| method: 'GET', | |
| headers: { | |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' | |
| } | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`); | |
| } | |
| return await response.json(); | |
| } | |
| async function getIPInfo(ip) { | |
| const response = await fetch(`https://ipresolver.subdomainfinder.in/${ip}`, { | |
| method: 'GET', | |
| headers: { | |
| 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36' | |
| } | |
| }); | |
| if (!response.ok) { | |
| throw new Error(`HTTP error! status: ${response.status}`); | |
| } | |
| return await response.json(); | |
| } | |
| function extractIPFromDNS(dnsData) { | |
| if (!dnsData || !dnsData.Answer) return null; | |
| for (const answer of dnsData.Answer) { | |
| if (answer.type === 1 && answer.data) { | |
| return answer.data; | |
| } | |
| } | |
| return null; | |
| } | |
| async function subdo(domain) { | |
| const token = await getTurnstileToken(); | |
| const subdomainData = await findSubdomains(domain, token); | |
| const results = []; | |
| for (const sub of subdomainData.data) { | |
| try { | |
| const dnsData = await resolveDNS(sub.subdomain); | |
| const ip = extractIPFromDNS(dnsData); | |
| let result = { | |
| subdomain: sub.subdomain, | |
| ip: ip || 'N/A', | |
| cloudflare: sub.cloudflare, | |
| dnsStatus: dnsData.Status | |
| }; | |
| if (ip) { | |
| try { | |
| const ipInfo = await getIPInfo(ip); | |
| if (ipInfo.success && ipInfo.result && ipInfo.result.ip) { | |
| result.ipInfo = { | |
| location: ipInfo.result.ip.locationName, | |
| asn: ipInfo.result.ip.asnName, | |
| country: ipInfo.result.ip.location, | |
| flag: ipInfo.result.ip.flag | |
| }; | |
| } | |
| } catch (e) { | |
| result.ipInfo = null; | |
| } | |
| } | |
| results.push(result); | |
| } catch (error) { | |
| results.push({ | |
| subdomain: sub.subdomain, | |
| error: error.message | |
| }); | |
| } | |
| } | |
| return { | |
| domain: domain, | |
| count: subdomainData.count, | |
| data: results | |
| }; | |
| } | |
| const handler = async (req, res) => { | |
| try { | |
| const { domain } = req.query; | |
| if (!domain) { | |
| return res.status(400).json({ | |
| success: false, | |
| error: 'Missing required parameter: domain' | |
| }); | |
| } | |
| const domainRegex = /^[a-zA-Z0-9][a-zA-Z0-9-]{0,61}[a-zA-Z0-9]?\.([a-zA-Z]{2,}\.?)+$/; | |
| if (!domainRegex.test(domain)) { | |
| return res.status(400).json({ | |
| success: false, | |
| error: 'Invalid domain format' | |
| }); | |
| } | |
| const result = await subdo(domain); | |
| res.json({ | |
| success: true, | |
| data: { | |
| domain: result.domain, | |
| total_subdomains: result.count, | |
| subdomains: result.data | |
| } | |
| }); | |
| } catch (error) { | |
| res.status(500).json({ | |
| success: false, | |
| error: error.message | |
| }); | |
| } | |
| }; | |
| module.exports = { | |
| name: 'Subdomain Finder', | |
| description: 'Find subdomains with IP addresses and location information', | |
| type: 'GET', | |
| routes: ['api/tools/subdofinder'], | |
| tags: ['security', 'subdomain', 'dns', 'recon'], | |
| parameters: ['domain', 'key'], | |
| enabled: true, | |
| main: ['tools', 'Search'], | |
| handler | |
| }; |