@@ -270,6 +270,15 @@ fn is_genesis_bootstrap_node() -> bool {
270270 match bootstrap_id. as_str ( ) {
271271 "001" | "002" | "003" | "004" | "005" => {
272272 println ! ( "🚀 Genesis bootstrap node #{} detected" , bootstrap_id) ;
273+
274+ // SECURITY: Verify IP authorization for Genesis nodes
275+ if !verify_genesis_node_ip_authorization ( & bootstrap_id) {
276+ println ! ( "🚨 SECURITY: Unauthorized IP attempting to run Genesis node {}" , bootstrap_id) ;
277+ println ! ( "🔒 BLOCKED: This Genesis node can only run from authorized IP addresses" ) ;
278+ return false ;
279+ }
280+
281+ println ! ( "✅ SECURITY: Genesis node {} authorized from this IP" , bootstrap_id) ;
273282 return true ;
274283 }
275284 _ => {
@@ -1317,6 +1326,126 @@ fn get_genesis_node_ips_dynamic() -> Vec<String> {
13171326 default_nodes
13181327}
13191328
1329+ // SECURITY: Verify that Genesis node is running from authorized IP address
1330+ fn verify_genesis_node_ip_authorization ( bootstrap_id : & str ) -> bool {
1331+ println ! ( "[SECURITY] 🔐 Verifying IP authorization for Genesis node {}" , bootstrap_id) ;
1332+
1333+ // Get current server IP address
1334+ let current_ip = get_current_server_ip ( ) ;
1335+ println ! ( "[SECURITY] 📍 Current server IP: {}" , current_ip) ;
1336+
1337+ // Get list of authorized Genesis IPs
1338+ let authorized_genesis_ips = get_genesis_node_ips_dynamic ( ) ;
1339+ println ! ( "[SECURITY] 📋 Authorized Genesis IPs: {:?}" , authorized_genesis_ips) ;
1340+
1341+ // Check if current IP is in authorized list
1342+ let is_authorized = authorized_genesis_ips. contains ( & current_ip) ;
1343+
1344+ if is_authorized {
1345+ println ! ( "[SECURITY] ✅ IP {} is authorized for Genesis nodes" , current_ip) ;
1346+
1347+ // Additional check: Ensure this specific Genesis node ID can run from this IP
1348+ if let Some ( expected_position) = get_expected_genesis_position ( & current_ip, & authorized_genesis_ips) {
1349+ let expected_id = format ! ( "{:03}" , expected_position) ;
1350+ if bootstrap_id == expected_id {
1351+ println ! ( "[SECURITY] ✅ Genesis node {} matches expected position {} for IP {}" ,
1352+ bootstrap_id, expected_position, current_ip) ;
1353+ return true ;
1354+ } else {
1355+ println ! ( "[SECURITY] ⚠️ Genesis node {} does not match expected position {} for IP {}" ,
1356+ bootstrap_id, expected_position, current_ip) ;
1357+ println ! ( "[SECURITY] 💡 Allowing anyway - IP is authorized (flexible during setup)" ) ;
1358+ return true ; // Allow any Genesis ID from authorized IP during setup
1359+ }
1360+ }
1361+
1362+ return true ;
1363+ } else {
1364+ println ! ( "[SECURITY] ❌ IP {} is NOT authorized for Genesis nodes" , current_ip) ;
1365+ println ! ( "[SECURITY] 🔒 Only authorized IPs can run Genesis nodes" ) ;
1366+ return false ;
1367+ }
1368+ }
1369+
1370+ // Get current server IP address using multiple methods
1371+ fn get_current_server_ip ( ) -> String {
1372+ // Method 1: Check environment variable (for manual override)
1373+ if let Ok ( manual_ip) = std:: env:: var ( "QNET_MANUAL_IP" ) {
1374+ if validate_ip_address_security ( & manual_ip) {
1375+ println ! ( "[IP] 🎯 Using manual IP from QNET_MANUAL_IP: {}" , manual_ip) ;
1376+ return manual_ip;
1377+ }
1378+ }
1379+
1380+ // Method 2: Try to detect public IP via external service
1381+ if let Ok ( detected_ip) = detect_public_ip ( ) {
1382+ println ! ( "[IP] 🌐 Detected public IP: {}" , detected_ip) ;
1383+ return detected_ip;
1384+ }
1385+
1386+ // Method 3: Try to get local network IP
1387+ if let Ok ( local_ip) = get_local_network_ip ( ) {
1388+ println ! ( "[IP] 🏠 Using local network IP: {}" , local_ip) ;
1389+ return local_ip;
1390+ }
1391+
1392+ // Fallback: Return localhost (will be rejected by security check)
1393+ println ! ( "[IP] ⚠️ Could not detect IP address - using localhost (will be rejected)" ) ;
1394+ "127.0.0.1" . to_string ( )
1395+ }
1396+
1397+ // Detect public IP address
1398+ fn detect_public_ip ( ) -> Result < String , String > {
1399+ // Try multiple IP detection services
1400+ let ip_services = [
1401+ "https://api.ipify.org" ,
1402+ "https://ifconfig.me/ip" ,
1403+ "https://icanhazip.com"
1404+ ] ;
1405+
1406+ for service in ip_services. iter ( ) {
1407+ if let Ok ( ip) = query_ip_service ( service) {
1408+ if validate_ip_address_security ( & ip) {
1409+ return Ok ( ip) ;
1410+ }
1411+ }
1412+ }
1413+
1414+ Err ( "Could not detect public IP from any service" . to_string ( ) )
1415+ }
1416+
1417+ // Query IP detection service
1418+ fn query_ip_service ( url : & str ) -> Result < String , String > {
1419+ // In production, this would use a proper HTTP client
1420+ // For now, return error to fallback to local IP detection
1421+ Err ( "External IP detection not implemented in this version" . to_string ( ) )
1422+ }
1423+
1424+ // Get local network IP address
1425+ fn get_local_network_ip ( ) -> Result < String , String > {
1426+ use std:: net:: { TcpStream , SocketAddr } ;
1427+
1428+ // Try to connect to a remote address to determine local IP
1429+ match TcpStream :: connect ( "8.8.8.8:80" ) {
1430+ Ok ( stream) => {
1431+ if let Ok ( local_addr) = stream. local_addr ( ) {
1432+ let ip = local_addr. ip ( ) . to_string ( ) ;
1433+ if validate_ip_address_security ( & ip) {
1434+ return Ok ( ip) ;
1435+ }
1436+ }
1437+ }
1438+ Err ( _) => { }
1439+ }
1440+
1441+ Err ( "Could not determine local network IP" . to_string ( ) )
1442+ }
1443+
1444+ // Get expected Genesis position for IP in the list
1445+ fn get_expected_genesis_position ( ip : & str , genesis_ips : & [ String ] ) -> Option < usize > {
1446+ genesis_ips. iter ( ) . position ( |genesis_ip| genesis_ip == ip) . map ( |pos| pos + 1 )
1447+ }
1448+
13201449// SECURITY: Validate IP address format and security
13211450fn validate_ip_address_security ( ip : & str ) -> bool {
13221451 use std:: net:: Ipv4Addr ;
0 commit comments