feat: initial commit of Ghaymah internal DNS, TCP and security testing suite and report

This commit is contained in:
2026-10-12 23:43:09 +03:00
commit bdcd2d44f5
57 changed files with 6499 additions and 0 deletions
+262
View File
@@ -0,0 +1,262 @@
// Phase 3 & 4: Complete DNS, TCP, Security, and Isolation Tests on Ghaymah
// This runs AFTER apps are deployed and accessible
const APP_A_ID = 'af1b9e91-9bec-4d6a-b76c-92d7273b82ce';
const APP_B_ID = 'fcbd895c-2370-46db-bd6a-057f6d887b0f';
const PROJECT_ID = '3f55ceef-78ae-40c8-a41b-0505db8c59ee';
const fs = require('fs');
let report = [];
function log(phase, msg, data) {
const ts = new Date().toISOString();
const line = `[${ts}] [${phase}] ${msg}`;
console.log(line);
if (data) console.log(JSON.stringify(data, null, 2));
report.push({ ts, phase, msg, data });
}
async function auth() {
const res = await fetch('https://auth.ghaymah.systems/signin/email-password', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ email: 'ziadalex2003@gmail.com', password: '2062003Mz*' })
});
const data = await res.json();
return { token: data.session.accessToken, userId: data.session.user.id };
}
async function gql(token, query, variables = {}) {
const res = await fetch('https://graphql.ghaymah.systems/v1/graphql', {
method: 'POST',
headers: { 'Authorization': 'Bearer ' + token, 'Content-Type': 'application/json' },
body: JSON.stringify({ query, variables })
});
return res.json();
}
async function appRequest(domain, path, timeout = 8000) {
try {
const res = await fetch(`https://${domain}${path}`, { signal: AbortSignal.timeout(timeout) });
return await res.json();
} catch (e) {
return { _error: e.message };
}
}
async function main() {
const { token, userId } = await auth();
log('AUTH', 'Authenticated', { userId });
// Step 1: Get app domains and status
log('RECON', 'Fetching app resources...');
const resData = await gql(token, `query GetResources($userId: uuid) {
ghaymah_cloud_resources(where: { user_id: { _eq: $userId }, deleted: { _eq: false }, chart_name: { _eq: "ghaymah-app" } }) {
id chart_name status values message
}
}`, { userId });
const apps = resData.data?.ghaymah_cloud_resources || [];
const appA = apps.find(a => a.values?.name === 'tcp-echo-server');
const appB = apps.find(a => a.values?.name === 'tcp-test-client');
const authDeploy = apps.find(a => a.values?.name === 'auth-deploy');
const domainA = appA?.values?.publicAccess?.domain;
const domainB = appB?.values?.publicAccess?.domain;
const domainAuth = authDeploy?.values?.publicAccess?.domain;
log('RECON', 'App A (tcp-echo-server)', { status: appA?.status, domain: domainA, project: appA?.values?.projectId });
log('RECON', 'App B (tcp-test-client)', { status: appB?.status, domain: domainB, project: appB?.values?.projectId });
log('RECON', 'App auth-deploy (different project)', { status: authDeploy?.status, domain: domainAuth, project: authDeploy?.values?.projectId });
if (!domainA || !domainB) {
log('ERROR', 'Missing domains! Cannot proceed with tests.');
// Try ListApps mutation to get hostnames
const listApps = await gql(token, `mutation ListApps {
listApps {
id name status alias
ports { name number hostname }
}
}`);
log('RECON', 'ListApps result', listApps.data?.listApps);
// Save partial report and exit
fs.writeFileSync('D:/cumin/ghaymah_dns_net_sec_tests/logs/06_test_results.json', JSON.stringify(report, null, 2));
return;
}
// ═══════════════════════════════════════════════
// PHASE 3: FUNCTIONALITY & QA TESTING
// ═══════════════════════════════════════════════
log('PHASE3', '═══ PHASE 3: FUNCTIONALITY & QA TESTING ═══');
// 3.1: Health checks
log('PHASE3', 'Testing App A health...');
const healthA = await appRequest(domainA, '/health');
log('PHASE3', 'App A health response', healthA);
log('PHASE3', 'Testing App B health...');
const healthB = await appRequest(domainB, '/health');
log('PHASE3', 'App B health response', healthB);
// 3.2: DNS Infrastructure
log('PHASE3-DNS', '--- Internal DNS Verification ---');
// Get resolv.conf from both apps
const resolvA = await appRequest(domainA, '/resolv-conf');
log('PHASE3-DNS', 'App A resolv.conf', resolvA);
const resolvB = await appRequest(domainB, '/resolv-conf');
log('PHASE3-DNS', 'App B resolv.conf', resolvB);
// Get IP addresses from both apps
const ipA = await appRequest(domainA, '/ip-addr');
log('PHASE3-DNS', 'App A network interfaces', ipA);
const ipB = await appRequest(domainB, '/ip-addr');
log('PHASE3-DNS', 'App B network interfaces', ipB);
// DNS Lookup tests from App B -> App A
const dnsPatterns = [
'tcp-echo-server',
'tcp-echo-server.mesh',
'tcp-echo-server.dns-tcp-test.mesh',
'tcp-echo-server.local',
'tcp-echo-server.dns-tcp-test',
'tcp-echo-server.internal',
'tcp-echo-server.svc.cluster.local',
];
log('PHASE3-DNS', 'Testing DNS resolution patterns from App B -> App A...');
for (const pattern of dnsPatterns) {
const dnsResult = await appRequest(domainB, `/dns-lookup?name=${encodeURIComponent(pattern)}`);
log('PHASE3-DNS', `DNS lookup: ${pattern}`, dnsResult);
}
// DNS Lookup tests from App A -> App B
const dnsPatternsB = [
'tcp-test-client',
'tcp-test-client.mesh',
'tcp-test-client.dns-tcp-test.mesh',
'tcp-test-client.local',
'tcp-test-client.dns-tcp-test',
];
log('PHASE3-DNS', 'Testing DNS resolution patterns from App A -> App B...');
for (const pattern of dnsPatternsB) {
const dnsResult = await appRequest(domainA, `/dns-lookup?name=${encodeURIComponent(pattern)}`);
log('PHASE3-DNS', `DNS lookup: ${pattern}`, dnsResult);
}
// 3.3: TCP Connection Tests
log('PHASE3-TCP', '--- TCP Connection Tests ---');
// Extract WireGuard/mesh IPs from App A
let appAPrivateIp = null;
if (ipA?.interfaces) {
for (const [name, addrs] of Object.entries(ipA.interfaces)) {
if (name === 'wg0' || name.startsWith('wg')) {
const v4 = addrs.find(a => a.family === 'IPv4');
if (v4) appAPrivateIp = v4.address;
}
}
if (!appAPrivateIp) {
// Try eth0
for (const [name, addrs] of Object.entries(ipA.interfaces)) {
if (name === 'eth0') {
const v4 = addrs.find(a => a.family === 'IPv4');
if (v4) appAPrivateIp = v4.address;
}
}
}
}
log('PHASE3-TCP', `App A private IP: ${appAPrivateIp}`);
// TCP connect from App B to App A on port 9000 using IP
if (appAPrivateIp) {
const tcpByIp = await appRequest(domainB, `/tcp-connect?host=${appAPrivateIp}&port=9000`);
log('PHASE3-TCP', `TCP via IP (${appAPrivateIp}:9000)`, tcpByIp);
}
// TCP connect from App B to App A via DNS name
for (const dnsName of ['tcp-echo-server', 'tcp-echo-server.mesh']) {
const tcpByDns = await appRequest(domainB, `/tcp-connect?host=${dnsName}&port=9000`);
log('PHASE3-TCP', `TCP via DNS (${dnsName}:9000)`, tcpByDns);
}
// HTTP connectivity test (App B -> App A port 8080)
if (appAPrivateIp) {
const httpByIp = await appRequest(domainB, `/tcp-connect?host=${appAPrivateIp}&port=8080`);
log('PHASE3-TCP', `HTTP port via IP (${appAPrivateIp}:8080)`, httpByIp);
}
// ═══════════════════════════════════════════════
// PHASE 4: SECURITY & SCOPING
// ═══════════════════════════════════════════════
log('PHASE4', '═══ PHASE 4: SECURITY & SCOPING ═══');
// 4.1: Isolation & Lateral Movement
log('PHASE4-ISO', '--- Isolation & Lateral Movement Tests ---');
// Try to reach auth-deploy (DIFFERENT project)
if (domainAuth) {
// DNS lookup for cross-project app
const crossProjectPatterns = [
'auth-deploy',
'auth-deploy.mesh',
'auth-deploy.auth-deploy.mesh',
];
for (const pattern of crossProjectPatterns) {
const crossDns = await appRequest(domainB, `/dns-lookup?name=${encodeURIComponent(pattern)}`);
log('PHASE4-ISO', `Cross-project DNS: ${pattern}`, crossDns);
}
}
// Try to reach scanner-clean (DIFFERENT project, in backoff)
const crossPatterns2 = [
'scanner-clean',
'scanner-clean.mesh',
];
for (const pattern of crossPatterns2) {
const crossDns = await appRequest(domainB, `/dns-lookup?name=${encodeURIComponent(pattern)}`);
log('PHASE4-ISO', `Cross-project DNS (scanner-clean): ${pattern}`, crossDns);
}
// 4.2: Network Enumeration (Port Scan)
log('PHASE4-SCAN', '--- Network Enumeration ---');
if (appAPrivateIp) {
const scanA = await appRequest(domainB, `/port-scan?host=${appAPrivateIp}&ports=22,53,80,443,3000,4000,5432,6379,8080,9000`, 15000);
log('PHASE4-SCAN', `Port scan App A (${appAPrivateIp})`, scanA);
}
// Scan common internal gateway IPs
const internalIps = ['10.100.0.1', '10.100.0.2', '172.26.64.1', '127.0.0.1'];
for (const ip of internalIps) {
const scanGw = await appRequest(domainB, `/port-scan?host=${ip}&ports=22,53,80,443,8080,9090`, 12000);
log('PHASE4-SCAN', `Port scan ${ip}`, scanGw);
}
// 4.3: External Internet Access & DNS Leak
log('PHASE4-LEAK', '--- Dual Routing & DNS Leaks ---');
const extA = await appRequest(domainA, '/external-test');
log('PHASE4-LEAK', 'App A external internet access', extA);
const extB = await appRequest(domainB, '/external-test');
log('PHASE4-LEAK', 'App B external internet access', extB);
// DNS leak test: resolve external domains
const externalDns = ['google.com', 'github.com', 'cloudflare.com'];
for (const name of externalDns) {
const dnsExt = await appRequest(domainB, `/dns-lookup?name=${encodeURIComponent(name)}`);
log('PHASE4-LEAK', `External DNS resolution: ${name}`, dnsExt);
}
// Save full results
fs.writeFileSync('D:/cumin/ghaymah_dns_net_sec_tests/logs/06_test_results.json', JSON.stringify(report, null, 2));
log('DONE', 'All tests completed. Results saved.');
}
main().catch(e => { console.error('FATAL:', e); process.exit(1); });