'nginx',443=>'nginx-ssl',2024=>'DeerFlow',2026=>'DeerFlow-UI',3088=>'Kuma',3100=>'Langfuse',3200=>'Paperclip',3900=>'GPT-Runner',5001=>'MiroFish',5432=>'PostgreSQL',5678=>'n8n',6333=>'Qdrant',8000=>'Plausible',8065=>'Mattermost',8080=>'SearXNG',8222=>'Vaultwarden',11434=>'Ollama']; $SACRED=[80,443,5432,11434,49222]; $NGINX=['paperclip.weval-consulting.com'=>3200,'langfuse.weval-consulting.com'=>3100]; $pass=$fail=0;$conflicts=[];$checks=[]; foreach($PORT_MAP as $port=>$svc){ $up=!empty(trim(shell_exec("ss -tlnp sport = :$port 2>/dev/null|grep LISTEN"))); if($up){$pass++;$checks[]=['port'=>$port,'svc'=>$svc,'s'=>'UP'];} else{ if(in_array($port,$SACRED)){$fail++;$conflicts[]="SACRED :$port ($svc) DOWN";} $checks[]=['port'=>$port,'svc'=>$svc,'s'=>'DOWN']; } } foreach($NGINX as $dom=>$exp){ $cf="/etc/nginx/sites-enabled/$dom"; if(file_exists($cf)){ $c=file_get_contents($cf); if(preg_match('/proxy_pass\s+https?:\/\/.*?:(\d+)\s*;/',$c,$m)){ $act=(int)$m[1]; if($act!==$exp){$fail++;$conflicts[]="NGINX $dom -> :$act should be :$exp";} else{$pass++;} } } } if(count($conflicts)>0){ $msg="PORT PROTECTION: ".implode(", ",$conflicts); @file_get_contents("https://api.telegram.org/bot8544624912/sendMessage?chat_id=7605775322&text=".urlencode($msg)); } $total=$pass+$fail; echo json_encode(['score'=>$total>0?round($pass/$total*100,1):0,'pass'=>$pass,'fail'=>$fail,'ports'=>count($PORT_MAP),'conflicts'=>$conflicts,'checks'=>$checks,'elapsed_ms'=>round((microtime(true)-$start)*1000),'rule'=>'EACH APP = 1 PORT. NEVER REUSE.'],JSON_PRETTY_PRINT);