Files
explorer-monorepo/scripts/trace-dns-to-vm.sh

353 lines
14 KiB
Bash
Executable File

#!/bin/bash
# Trace DNS to VM Service - Complete Path Analysis
# Reviews all hops and configurations from DNS to VMID 5000
set -uo pipefail
DOMAIN="explorer.d-bis.org"
VM_IP="192.168.11.140"
VMID=5000
NODE="r630-02"
NPMPLUS_IP="192.168.11.166"
NPMPLUS_VMID="10233"
# Colors
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
CYAN='\033[0;36m'
NC='\033[0m'
echo "=========================================="
echo "DNS to VM Service Path Analysis"
echo "=========================================="
echo "Domain: $DOMAIN"
echo "Target VM: VMID $VMID ($VM_IP) on $NODE"
echo "=========================================="
echo ""
# ============================================
# 1. DNS Resolution
# ============================================
echo -e "${CYAN}=== 1. DNS Resolution ===${NC}"
# Check DNS A record
DNS_IP=$(dig +short $DOMAIN A 2>/dev/null | head -1 || echo "")
if [ -n "$DNS_IP" ]; then
echo -e "${GREEN}✅ DNS A Record:${NC} $DOMAIN$DNS_IP"
# Check if it's Cloudflare IP
if echo "$DNS_IP" | grep -qE "^104\.|^172\.|^198\.|^141\.|^188\."; then
echo -e "${GREEN} → Cloudflare IP detected${NC}"
CLOUDFLARE_IP="$DNS_IP"
else
echo -e "${YELLOW} → Not a Cloudflare IP${NC}"
fi
else
echo -e "${RED}❌ DNS A Record: Not found${NC}"
fi
# Check DNS AAAA record (IPv6)
DNS_IPV6=$(dig +short $DOMAIN AAAA 2>/dev/null | head -1 || echo "")
if [ -n "$DNS_IPV6" ]; then
echo -e "${GREEN}✅ DNS AAAA Record:${NC} $DOMAIN$DNS_IPV6"
fi
# Check DNS CNAME
DNS_CNAME=$(dig +short $DOMAIN CNAME 2>/dev/null | head -1 || echo "")
if [ -n "$DNS_CNAME" ]; then
echo -e "${GREEN}✅ DNS CNAME:${NC} $DOMAIN$DNS_CNAME"
fi
echo ""
# ============================================
# 2. Cloudflare Configuration
# ============================================
echo -e "${CYAN}=== 2. Cloudflare Configuration ===${NC}"
# Check if Cloudflare tunnel is configured
if [ -n "${CLOUDFLARE_IP:-}" ]; then
echo -e "${GREEN}✅ Domain appears to use Cloudflare${NC}"
echo " IP: $CLOUDFLARE_IP"
# Check Cloudflare tunnel status (if accessible)
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@r630-01 'pct exec 102 -- systemctl is-active cloudflared 2>/dev/null'" 2>/dev/null | grep -q "active"; then
echo -e "${GREEN}✅ Cloudflare tunnel service is running${NC}"
else
echo -e "${YELLOW}⚠️ Cloudflare tunnel service status unknown${NC}"
fi
else
echo -e "${YELLOW}⚠️ Cloudflare IP not detected in DNS${NC}"
fi
echo ""
# ============================================
# 3. NPMplus Configuration
# ============================================
echo -e "${CYAN}=== 3. NPMplus Configuration ===${NC}"
# Check NPMplus service status
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@r630-01 'pct exec $NPMPLUS_VMID -- docker ps | grep -q npmplus'" 2>/dev/null; then
echo -e "${GREEN}✅ NPMplus container is running${NC}"
else
echo -e "${RED}❌ NPMplus container not running${NC}"
fi
# Get NPMplus configuration from database
echo "Checking NPMplus proxy host configuration..."
NPMPLUS_CONFIG=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@r630-01 'pct exec $NPMPLUS_VMID -- docker exec npmplus node -e \"
const Database = require('better-sqlite3');
const db = new Database('/data/npmplus/database.sqlite', { readonly: true });
const host = db.prepare('SELECT id, domain_names, forward_scheme, forward_host, forward_port, ssl_forced FROM proxy_host WHERE domain_names LIKE \\\"%$DOMAIN%\\\"').get();
console.log(JSON.stringify(host || {}));
db.close();
\" 2>&1'" 2>/dev/null || echo "{}")
if echo "$NPMPLUS_CONFIG" | jq -e '.forward_host' >/dev/null 2>&1; then
FORWARD_HOST=$(echo "$NPMPLUS_CONFIG" | jq -r '.forward_host // "unknown"')
FORWARD_PORT=$(echo "$NPMPLUS_CONFIG" | jq -r '.forward_port // "unknown"')
FORWARD_SCHEME=$(echo "$NPMPLUS_CONFIG" | jq -r '.forward_scheme // "unknown"')
SSL_FORCED=$(echo "$NPMPLUS_CONFIG" | jq -r '.ssl_forced // false')
echo -e "${GREEN}✅ NPMplus Proxy Host Configuration:${NC}"
echo " Domain: $DOMAIN"
echo " Forward Scheme: $FORWARD_SCHEME"
echo " Forward Host: $FORWARD_HOST"
echo " Forward Port: $FORWARD_PORT"
echo " SSL Forced: $SSL_FORCED"
# Verify target matches expected
if [ "$FORWARD_HOST" = "$VM_IP" ] && [ "$FORWARD_PORT" = "80" ]; then
echo -e "${GREEN} → Configuration matches expected target${NC}"
else
echo -e "${RED} → Configuration mismatch! Expected: $VM_IP:80${NC}"
fi
else
echo -e "${RED}❌ NPMplus proxy host not found for $DOMAIN${NC}"
fi
# Check NPMplus port 80/443 listening
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@r630-01 'pct exec $NPMPLUS_VMID -- ss -tlnp | grep -qE \":80 |:443 \"'" 2>/dev/null; then
echo -e "${GREEN}✅ NPMplus listening on ports 80/443${NC}"
else
echo -e "${RED}❌ NPMplus not listening on ports 80/443${NC}"
fi
echo ""
# ============================================
# 4. Network Routing
# ============================================
echo -e "${CYAN}=== 4. Network Routing ===${NC}"
# Test connectivity from NPMplus to target VM
echo "Testing connectivity from NPMplus to target VM..."
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@r630-01 'pct exec $NPMPLUS_VMID -- curl -s -o /dev/null -w \"%{http_code}\" --connect-timeout 5 http://$VM_IP:80/ 2>/dev/null'" 2>/dev/null | grep -q "200"; then
echo -e "${GREEN}✅ NPMplus can reach target VM (HTTP 200)${NC}"
else
HTTP_CODE=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@r630-01 'pct exec $NPMPLUS_VMID -- curl -s -o /dev/null -w \"%{http_code}\" --connect-timeout 5 http://$VM_IP:80/ 2>/dev/null'" 2>/dev/null || echo "000")
echo -e "${RED}❌ NPMplus cannot reach target VM (HTTP $HTTP_CODE)${NC}"
fi
# Check firewall rules (basic check)
echo "Checking network connectivity..."
if ping -c 1 -W 2 "$VM_IP" >/dev/null 2>&1; then
echo -e "${GREEN}✅ Target VM is reachable via ping${NC}"
else
echo -e "${YELLOW}⚠️ Target VM not reachable via ping (may be firewall)${NC}"
fi
echo ""
# ============================================
# 5. Target VM (VMID 5000) Configuration
# ============================================
echo -e "${CYAN}=== 5. Target VM (VMID 5000) Configuration ===${NC}"
# Check container status
CONTAINER_STATUS=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@$NODE 'pct status $VMID 2>/dev/null | awk \"{print \\\$2}\"'" 2>/dev/null || echo "unknown")
if [ "$CONTAINER_STATUS" = "running" ]; then
echo -e "${GREEN}✅ Container VMID $VMID is running${NC}"
else
echo -e "${RED}❌ Container VMID $VMID is not running (status: $CONTAINER_STATUS)${NC}"
fi
# Check nginx service
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@$NODE 'pct exec $VMID -- systemctl is-active nginx 2>/dev/null'" 2>/dev/null | grep -q "active"; then
echo -e "${GREEN}✅ Nginx service is running${NC}"
else
echo -e "${RED}❌ Nginx service is not running${NC}"
fi
# Check nginx listening ports
NGINX_PORTS=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@$NODE 'pct exec $VMID -- ss -tlnp | grep nginx | grep -oE \":[0-9]+\" | sort -u'" 2>/dev/null || echo "")
if [ -n "$NGINX_PORTS" ]; then
echo -e "${GREEN}✅ Nginx listening on ports:${NC} $NGINX_PORTS"
if echo "$NGINX_PORTS" | grep -q ":80"; then
echo -e "${GREEN} → Port 80 confirmed${NC}"
else
echo -e "${RED} → Port 80 NOT listening!${NC}"
fi
else
echo -e "${RED}❌ Nginx not listening on any ports${NC}"
fi
# Check nginx configuration
echo "Checking nginx configuration..."
NGINX_CONFIG=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@$NODE 'pct exec $VMID -- cat /etc/nginx/sites-available/blockscout 2>/dev/null | head -50'" 2>/dev/null || echo "")
if [ -n "$NGINX_CONFIG" ]; then
echo -e "${GREEN}✅ Nginx configuration file exists${NC}"
# Check server_name
if echo "$NGINX_CONFIG" | grep -q "server_name.*$DOMAIN"; then
echo -e "${GREEN} → server_name includes $DOMAIN${NC}"
else
echo -e "${YELLOW} → server_name may not include $DOMAIN${NC}"
fi
# Check listen directives
if echo "$NGINX_CONFIG" | grep -q "listen.*80"; then
echo -e "${GREEN} → Listening on port 80${NC}"
else
echo -e "${RED} → Not listening on port 80!${NC}"
fi
# Check root location
if echo "$NGINX_CONFIG" | grep -q "location.*/.*root.*html"; then
echo -e "${GREEN} → Root location configured${NC}"
else
echo -e "${YELLOW} → Root location may not be configured${NC}"
fi
else
echo -e "${RED}❌ Nginx configuration file not found${NC}"
fi
# Test nginx config validity
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@$NODE 'pct exec $VMID -- nginx -t 2>&1'" 2>/dev/null | grep -q "test is successful"; then
echo -e "${GREEN}✅ Nginx configuration is valid${NC}"
else
echo -e "${RED}❌ Nginx configuration has errors${NC}"
ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@$NODE 'pct exec $VMID -- nginx -t 2>&1'" 2>/dev/null | head -5
fi
echo ""
# ============================================
# 6. Frontend File Check
# ============================================
echo -e "${CYAN}=== 6. Frontend File Check ===${NC}"
if ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@$NODE 'pct exec $VMID -- test -f /var/www/html/index.html'" 2>/dev/null; then
echo -e "${GREEN}✅ Frontend file exists${NC}"
FILE_SIZE=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@$NODE 'pct exec $VMID -- stat -c%s /var/www/html/index.html 2>/dev/null'" 2>/dev/null || echo "0")
echo " File size: $FILE_SIZE bytes"
FILE_PERMS=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@$NODE 'pct exec $VMID -- ls -l /var/www/html/index.html 2>/dev/null'" 2>/dev/null || echo "")
if [ -n "$FILE_PERMS" ]; then
echo " Permissions: $FILE_PERMS"
fi
else
echo -e "${RED}❌ Frontend file not found${NC}"
fi
echo ""
# ============================================
# 7. End-to-End Test
# ============================================
echo -e "${CYAN}=== 7. End-to-End Connectivity Test ===${NC}"
# Test from local to target
echo "Testing direct access to target VM..."
LOCAL_TEST=$(curl -s -o /dev/null -w '%{http_code}' --connect-timeout 5 "http://$VM_IP:80/" 2>/dev/null || echo "000")
if [ "$LOCAL_TEST" = "200" ]; then
echo -e "${GREEN}✅ Direct access to target VM: HTTP $LOCAL_TEST${NC}"
else
echo -e "${RED}❌ Direct access to target VM: HTTP $LOCAL_TEST${NC}"
fi
# Test from NPMplus to target
echo "Testing from NPMplus to target VM..."
NPMPLUS_TEST=$(ssh -o ConnectTimeout=5 -o StrictHostKeyChecking=no root@192.168.11.10 "ssh -o ConnectTimeout=5 root@r630-01 'pct exec $NPMPLUS_VMID -- curl -s -o /dev/null -w \"%{http_code}\" --connect-timeout 5 http://$VM_IP:80/ 2>/dev/null'" 2>/dev/null || echo "000")
if [ "$NPMPLUS_TEST" = "200" ]; then
echo -e "${GREEN}✅ NPMplus to target VM: HTTP $NPMPLUS_TEST${NC}"
else
echo -e "${RED}❌ NPMplus to target VM: HTTP $NPMPLUS_TEST${NC}"
fi
# Test external domain (if accessible)
echo "Testing external domain access..."
EXTERNAL_TEST=$(curl -s -o /dev/null -w '%{http_code}' --connect-timeout 5 --max-time 10 "https://$DOMAIN" 2>/dev/null || echo "000")
if [ "$EXTERNAL_TEST" = "200" ] || [ "$EXTERNAL_TEST" = "301" ] || [ "$EXTERNAL_TEST" = "302" ]; then
echo -e "${GREEN}✅ External domain access: HTTP $EXTERNAL_TEST${NC}"
elif [ "$EXTERNAL_TEST" = "000" ]; then
echo -e "${YELLOW}⚠️ External domain access: Timeout/Connection failed${NC}"
else
echo -e "${YELLOW}⚠️ External domain access: HTTP $EXTERNAL_TEST${NC}"
fi
echo ""
# ============================================
# Summary & Recommendations
# ============================================
echo "=========================================="
echo "Summary & Recommendations"
echo "=========================================="
echo ""
# Check each hop
ISSUES=0
if [ -z "$DNS_IP" ]; then
echo -e "${RED}❌ DNS: No A record found${NC}"
((ISSUES++))
else
echo -e "${GREEN}✅ DNS: Resolves to $DNS_IP${NC}"
fi
if [ -n "${FORWARD_HOST:-}" ] && [ -n "${FORWARD_PORT:-}" ]; then
if [ "$FORWARD_HOST" != "$VM_IP" ] || [ "$FORWARD_PORT" != "80" ]; then
echo -e "${RED}❌ NPMplus: Configuration mismatch${NC}"
((ISSUES++))
else
echo -e "${GREEN}✅ NPMplus: Correctly configured${NC}"
fi
else
echo -e "${RED}❌ NPMplus: Configuration not found${NC}"
fi
if [ "$CONTAINER_STATUS" != "running" ]; then
echo -e "${RED}❌ VM: Container not running${NC}"
((ISSUES++))
else
echo -e "${GREEN}✅ VM: Container running${NC}"
fi
if [ "$LOCAL_TEST" != "200" ]; then
echo -e "${RED}❌ Service: Not responding on port 80${NC}"
((ISSUES++))
else
echo -e "${GREEN}✅ Service: Responding correctly${NC}"
fi
echo ""
if [ $ISSUES -eq 0 ]; then
echo -e "${GREEN}✅ All hops are configured correctly!${NC}"
echo ""
echo "If external access is still not working, check:"
echo " 1. Cloudflare proxy status (if using Cloudflare)"
echo " 2. Firewall rules between NPMplus and target VM"
echo " 3. NPMplus SSL certificate configuration"
else
echo -e "${RED}❌ Found $ISSUES issue(s) that need to be fixed${NC}"
fi
echo ""