#!/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 ""