Update network_menu.sh

This commit is contained in:
MacRimi 2025-07-08 22:42:12 +02:00
parent d0bbfa82d1
commit 77c950bc1e

View File

@ -6,17 +6,13 @@
# Copyright : (c) 2024 MacRimi # Copyright : (c) 2024 MacRimi
# License : MIT (https://raw.githubusercontent.com/MacRimi/ProxMenux/main/LICENSE) # License : MIT (https://raw.githubusercontent.com/MacRimi/ProxMenux/main/LICENSE)
# Version : 1.1 # Version : 1.1
# Last Updated: 06/07/2025 # Last Updated: 08/07/2025
# ========================================================== # ==========================================================
# Description: # Description:
# ProxMenu is an advanced yet user-friendly network management tool for Proxmox VE. # Advanced network management and troubleshooting tool for Proxmox VE.
# Core features: # Features include interface detection, bridge management, connectivity testing,
# - View and analyze network interfaces, bridges, and routing table # network diagnostics, configuration backup/restore, and automated repairs.
# - Test Internet and LAN connectivity
# - Diagnose and repair basic network issues
# - Backup, restore, and clean network configuration
# - Safely restart the network service
# Configuration ============================================ # Configuration ============================================
REPO_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main" REPO_URL="https://raw.githubusercontent.com/MacRimi/ProxMenux/main"
@ -33,22 +29,24 @@ load_language
initialize_cache initialize_cache
# ========================================================== # ==========================================================
# Utility Functions
create_backup_dir() { create_backup_dir() {
[ ! -d "$BACKUP_DIR" ] && mkdir -p "$BACKUP_DIR" [ ! -d "$BACKUP_DIR" ] && mkdir -p "$BACKUP_DIR"
} }
backup_network_config() { backup_network_config() {
create_backup_dir create_backup_dir
local timestamp=$(date +"%Y%m%d_%H%M%S") local timestamp=$(date +"%Y-%m-%d_%H-%M-%S")
cp /etc/network/interfaces "$BACKUP_DIR/interfaces_backup_$timestamp" local backup_file="$BACKUP_DIR/interfaces_backup_$timestamp"
cp /etc/network/interfaces "$backup_file"
msg_ok "$(translate "Network configuration backed up")" msg_ok "$(translate "Network configuration backed up")"
echo "$backup_file"
} }
# ========================================================== # ==========================================================
# Network Detection Functions
detect_physical_interfaces() { detect_physical_interfaces() {
ip -o link show | awk -F': ' '$2 !~ /^(lo|veth|dummy|bond|tap|tun)/ && $2 !~ /vmbr/ {print $2}' | sort ip -o link show | awk -F': ' '$2 !~ /^(lo|veth|dummy|bond|tap|tun|docker|br-)/ && $2 !~ /vmbr/ {print $2}' | sort
} }
detect_bridge_interfaces() { detect_bridge_interfaces() {
@ -63,15 +61,15 @@ get_interface_info() {
local interface="$1" local interface="$1"
local info="" local info=""
# Get IP address
local ip=$(ip -4 addr show "$interface" 2>/dev/null | grep -oP '(?<=inet\s)\d+(\.\d+){3}/\d+' | head -1) local ip=$(ip -4 addr show "$interface" 2>/dev/null | grep -oP '(?<=inet\s)\d+(\.\d+){3}/\d+' | head -1)
[ -z "$ip" ] && ip="$(translate "No IP")" [ -z "$ip" ] && ip="$(translate "No IP")"
# Get status
local status=$(ip link show "$interface" 2>/dev/null | grep -o "state [A-Z]*" | cut -d' ' -f2) local status=$(ip link show "$interface" 2>/dev/null | grep -o "state [A-Z]*" | cut -d' ' -f2)
[ -z "$status" ] && status="UNKNOWN" [ -z "$status" ] && status="UNKNOWN"
# Get MAC address
local mac=$(ip link show "$interface" 2>/dev/null | grep -o "link/ether [a-f0-9:]*" | cut -d' ' -f2) local mac=$(ip link show "$interface" 2>/dev/null | grep -o "link/ether [a-f0-9:]*" | cut -d' ' -f2)
[ -z "$mac" ] && mac="$(translate "No MAC")" [ -z "$mac" ] && mac="$(translate "No MAC")"
@ -79,7 +77,7 @@ get_interface_info() {
} }
# ========================================================== # ==========================================================
# Network Information Functions
show_interface_details() { show_interface_details() {
local interfaces=($(detect_all_interfaces)) local interfaces=($(detect_all_interfaces))
local info_text="" local info_text=""
@ -97,7 +95,7 @@ show_interface_details() {
info_text+=" $(translate "MAC Address"): $mac\n\n" info_text+=" $(translate "MAC Address"): $mac\n\n"
done done
dialog --title "$(translate "Interface Details")" \ dialog --backtitle "ProxMenux" --title "$(translate "Interface Details")" \
--msgbox "$info_text" 20 70 --msgbox "$info_text" 20 70
} }
@ -115,7 +113,7 @@ show_bridge_status() {
local details=$(get_interface_info "$bridge") local details=$(get_interface_info "$bridge")
IFS='|' read -r name ip status mac <<< "$details" IFS='|' read -r name ip status mac <<< "$details"
# Get bridge ports
local ports=$(grep -A5 "iface $bridge" /etc/network/interfaces 2>/dev/null | grep "bridge-ports" | cut -d' ' -f2-) local ports=$(grep -A5 "iface $bridge" /etc/network/interfaces 2>/dev/null | grep "bridge-ports" | cut -d' ' -f2-)
[ -z "$ports" ] && ports="$(translate "None")" [ -z "$ports" ] && ports="$(translate "None")"
@ -126,23 +124,54 @@ show_bridge_status() {
done done
fi fi
dialog --title "$(translate "Bridge Status")" \ dialog --backtitle "ProxMenux" --title "$(translate "Bridge Status")" \
--msgbox "$bridge_info" 18 70 --msgbox "$bridge_info" 18 70
} }
show_routing_table() { show_routing_table_() {
local route_info="" local route_info=""
route_info+="$(translate "Routing Table")\n" route_info+="$(translate "Routing Table")\n"
route_info+="$(printf '=%.0s' {1..30})\n\n" route_info+="$(printf '=%.0s' {1..30})\n\n"
route_info+="$(ip route show)\n\n" route_info+="$(ip route show)\n\n"
route_info+="$(translate "Default Gateway"): $(ip route | grep default | awk '{print $3}' | head -1)\n" route_info+="$(translate "Default Gateway"): $(ip route | grep default | awk '{print $3}' | head -1)\n"
dialog --title "$(translate "Routing Information")" \ dialog --backtitle "ProxMenux" --title "$(translate "Routing Information")" \
--msgbox "$route_info" 15 80 --msgbox "$route_info" 15 80
} }
# ==========================================================
show_routing_table() {
local route_info=""
local default_gw=$(ip route | grep default | awk '{print $3}' | head -1)
local routes=$(ip route show)
local route_count=$(echo "$routes" | wc -l)
route_info+="🗺️ $(translate "Routing Table")\n"
route_info+="$(printf '═%.0s' {1..60})\n\n"
if [ -z "$routes" ]; then
route_info+="⚠️ $(translate "No routing information found.")\n\n"
else
route_info+="$(translate "Total routes"): $route_count\n\n"
while read -r line; do
if [[ "$line" == *"default"* ]]; then
route_info+="➡️ $line\n"
else
route_info+="$line\n"
fi
done <<< "$routes"
route_info+="\n"
route_info+="🌍 $(translate "Default Gateway"): ${default_gw:-$(translate "Not found")}\n"
fi
dialog --backtitle "ProxMenux" --title "$(translate "Routing Information")" \
--msgbox "$route_info" 20 85
}
# ==========================================================
# Network Testing Functions
test_connectivity() { test_connectivity() {
local test_results="" local test_results=""
local tests=( local tests=(
@ -166,14 +195,14 @@ test_connectivity() {
fi fi
done done
# DNS Resolution test
if nslookup google.com >/dev/null 2>&1; then if nslookup google.com >/dev/null 2>&1; then
test_results+="$(translate "DNS Resolution"): $(translate "OK")\n" test_results+="$(translate "DNS Resolution"): $(translate "OK")\n"
else else
test_results+="$(translate "DNS Resolution"): $(translate "FAILED")\n" test_results+="$(translate "DNS Resolution"): $(translate "FAILED")\n"
fi fi
cleanup cleanup
dialog --title "$(translate "Connectivity Test")" \ dialog --backtitle "ProxMenux" --title "$(translate "Connectivity Test")" \
--msgbox "$test_results" 15 60 --msgbox "$test_results" 15 60
} }
@ -187,194 +216,294 @@ advanced_network_diagnostics() {
diag_info+="$(translate "Advanced Network Diagnostics")\n" diag_info+="$(translate "Advanced Network Diagnostics")\n"
diag_info+="$(printf '=%.0s' {1..40})\n\n" diag_info+="$(printf '=%.0s' {1..40})\n\n"
# Network statistics
diag_info+="$(translate "Active Connections"): $(ss -tuln | wc -l)\n" diag_info+="$(translate "Active Connections"): $(ss -tuln | wc -l)\n"
diag_info+="$(translate "Listening Ports"): $(ss -tln | grep LISTEN | wc -l)\n" diag_info+="$(translate "Listening Ports"): $(ss -tln | grep LISTEN | wc -l)\n"
diag_info+="$(translate "Network Interfaces"): $(ip link show | grep -c "^[0-9]")\n\n" diag_info+="$(translate "Network Interfaces"): $(ip link show | grep -c "^[0-9]")\n\n"
# Check for common issues
diag_info+="$(translate "Common Issues Check"):\n" diag_info+="$(translate "Common Issues Check"):\n"
# Check if NetworkManager is running (shouldn't be on Proxmox)
if systemctl is-active --quiet NetworkManager 2>/dev/null; then if systemctl is-active --quiet NetworkManager 2>/dev/null; then
diag_info+="$(translate "NetworkManager is running (may cause conflicts)")\n" diag_info+="$(translate "NetworkManager is running (may cause conflicts)")\n"
if dialog --title "$(translate "NetworkManager Detected")" \
--yesno "$(translate "NetworkManager is running, which may conflict with Proxmox.")\n\n$(translate "Do you want to disable and remove it now?")" 10 70; then
dialog --infobox "$(translate "Disabling and removing NetworkManager...")" 6 60
systemctl stop NetworkManager >/dev/null 2>&1
systemctl disable NetworkManager >/dev/null 2>&1
apt-get purge -y network-manager >/dev/null 2>&1
diag_info+="$(translate "NetworkManager has been removed successfully")\n"
else
diag_info+=" $(translate "User chose not to remove NetworkManager")\n"
fi
else else
diag_info+="$(translate "NetworkManager not running")\n" diag_info+="$(translate "NetworkManager not running")\n"
fi fi
# Check for duplicate IPs
local ips=($(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | sort | uniq -d)) local ips=($(ip -4 addr show | grep -oP '(?<=inet\s)\d+(\.\d+){3}' | sort | uniq -d))
if [ ${#ips[@]} -gt 0 ]; then if [ ${#ips[@]} -gt 0 ]; then
diag_info+="$(translate "Duplicate IP addresses found"): ${ips[*]}\n" diag_info+="$(translate "Duplicate IP addresses found"): ${ips[*]}\n"
else else
diag_info+="$(translate "No duplicate IP addresses")\n" diag_info+="$(translate "No duplicate IP addresses")\n"
fi fi
cleanup cleanup
dialog --title "$(translate "Network Diagnostics")" \
dialog --backtitle "ProxMenux" --title "$(translate "Network Diagnostics")" \
--msgbox "$diag_info" 18 70 --msgbox "$diag_info" 18 70
} }
# ==========================================================
# SAFE Network Analysis Functions (NO AUTO-REPAIR)
# ========================================================== # ==========================================================
repair_bridge_configuration() { analyze_bridge_configuration() {
show_proxmenux_logo show_proxmenux_logo
msg_info "$(translate "Analyzing Bridge Configuration")" msg_info "$(translate "Analyzing Bridge Configuration - READ ONLY MODE")"
sleep 1 sleep 1
local physical_interfaces=($(detect_physical_interfaces)) local physical_interfaces=($(detect_physical_interfaces))
local bridges=($(detect_bridge_interfaces)) local bridges=($(detect_bridge_interfaces))
local issues_found="" local analysis_report=""
local proposed_changes="" local issues_found=0
local suggestions=""
analysis_report+="🔍 $(translate "BRIDGE CONFIGURATION ANALYSIS")\n"
analysis_report+="$(printf '=%.0s' {1..50})\n\n"
cleanup
if [ ${#bridges[@]} -eq 0 ]; then
analysis_report+=" $(translate "No bridges found in system")\n"
dialog --backtitle "ProxMenux" --title "$(translate "Bridge Analysis")" --msgbox "$analysis_report" 10 60
return
fi
# Analyze each bridge
for bridge in "${bridges[@]}"; do for bridge in "${bridges[@]}"; do
analysis_report+="🌉 $(translate "Bridge"): $bridge\n"
# Get current configuration
local current_ports=$(grep -A5 "iface $bridge" /etc/network/interfaces 2>/dev/null | grep "bridge-ports" | cut -d' ' -f2-) local current_ports=$(grep -A5 "iface $bridge" /etc/network/interfaces 2>/dev/null | grep "bridge-ports" | cut -d' ' -f2-)
local bridge_ip=$(ip -4 addr show "$bridge" 2>/dev/null | grep -oP '(?<=inet\s)\d+(\.\d+){3}/\d+' | head -1)
local bridge_status=$(ip link show "$bridge" 2>/dev/null | grep -o "state [A-Z]*" | cut -d' ' -f2)
analysis_report+=" 📍 $(translate "Status"): ${bridge_status:-UNKNOWN}\n"
analysis_report+=" 🌐 $(translate "IP"): ${bridge_ip:-$(translate "No IP assigned")}\n"
analysis_report+=" 🔌 $(translate "Configured Ports"): ${current_ports:-$(translate "None")}\n"
if [ -n "$current_ports" ]; then if [ -n "$current_ports" ]; then
local invalid_ports="" local invalid_ports=""
local valid_ports="" local valid_ports=""
# Check each configured port
for port in $current_ports; do for port in $current_ports; do
if ip link show "$port" >/dev/null 2>&1; then if ip link show "$port" >/dev/null 2>&1; then
valid_ports+="$port " valid_ports+="$port "
analysis_report+="$(translate "Port") $port: $(translate "EXISTS")\n"
else else
invalid_ports+="$port " invalid_ports+="$port "
analysis_report+="$(translate "Port") $port: $(translate "NOT FOUND")\n"
((issues_found++))
fi fi
done done
# Generate suggestions for invalid ports
if [ -n "$invalid_ports" ]; then if [ -n "$invalid_ports" ]; then
issues_found+="$(translate "Bridge") $bridge: $(translate "Invalid ports") - $invalid_ports\n" suggestions+="🔧 $(translate "SUGGESTION FOR") $bridge:\n"
if [ -z "$valid_ports" ] && [ ${#physical_interfaces[@]} -gt 0 ]; then if [ ${#physical_interfaces[@]} -gt 0 ]; then
proposed_changes+="$(translate "Assign") ${physical_interfaces[0]} $(translate "to") $bridge\n" suggestions+=" $(translate "Replace invalid port(s)") '$invalid_ports' $(translate "with"): ${physical_interfaces[0]}\n"
suggestions+=" $(translate "Command"): sed -i 's/bridge-ports.*/bridge-ports ${physical_interfaces[0]}/' /etc/network/interfaces\n"
else else
proposed_changes+="$(translate "Remove invalid ports from") $bridge\n" suggestions+=" $(translate "Remove invalid port(s)") '$invalid_ports'\n"
suggestions+=" $(translate "Command"): sed -i 's/bridge-ports.*/bridge-ports none/' /etc/network/interfaces\n"
fi fi
suggestions+="\n"
fi
else
analysis_report+=" ⚠️ $(translate "No ports configured")\n"
if [ ${#physical_interfaces[@]} -gt 0 ]; then
suggestions+="🔧 $(translate "SUGGESTION FOR") $bridge:\n"
suggestions+=" $(translate "Consider adding physical interface"): ${physical_interfaces[0]}\n"
suggestions+=" $(translate "Command"): sed -i '/iface $bridge/a\\ bridge-ports ${physical_interfaces[0]}' /etc/network/interfaces\n\n"
fi fi
fi fi
analysis_report+="\n"
done done
cleanup
if [ -z "$issues_found" ]; then # Summary
dialog --title "$(translate "Bridge Analysis")" \ analysis_report+="📊 $(translate "ANALYSIS SUMMARY")\n"
--msgbox "\n$(translate "No bridge configuration issues found.")" 8 60 analysis_report+="$(printf '=%.0s' {1..25})\n"
return analysis_report+="$(translate "Bridges analyzed"): ${#bridges[@]}\n"
analysis_report+="$(translate "Issues found"): $issues_found\n"
local auto_only=$(grep "^auto" /etc/network/interfaces | awk '{print $2}' | while read i; do
grep -q "^iface $i" /etc/network/interfaces || echo "$i"
done)
if [ -n "$auto_only" ]; then
analysis_report+="⚠️ $(translate "Interfaces defined with 'auto' but no 'iface' block"): $auto_only\n"
((issues_found++))
fi
analysis_report+="$(translate "Physical interfaces available"): ${#physical_interfaces[@]}\n\n"
if [ $issues_found -gt 0 ]; then
analysis_report+="$suggestions"
analysis_report+="⚠️ $(translate "IMPORTANT"): $(translate "No changes have been made to your system")\n"
analysis_report+="$(translate "Use the Guided Repair option to fix issues safely")\n"
else
analysis_report+="$(translate "No bridge configuration issues found")\n"
fi fi
# Show analysis in scrollable dialog
local temp_file=$(mktemp)
echo -e "$analysis_report" > "$temp_file"
dialog --backtitle "ProxMenux" --title "$(translate "Bridge Configuration Analysis")" \
--textbox "$temp_file" 25 80
rm -f "$temp_file"
# Offer guided repair if issues found
if [ $issues_found -gt 0 ]; then
if dialog --backtitle "ProxMenux" --title "$(translate "Guided Repair Available")" \
--yesno "$(translate "Issues were found. Would you like to use the Guided Repair Assistant?")" 8 60; then
guided_bridge_repair
fi
fi
}
local confirmation_text="" guided_bridge_repair() {
confirmation_text+="$(translate "Bridge Configuration Issues Found"):\n\n" local step=1
confirmation_text+="$issues_found\n" local total_steps=5
confirmation_text+="$(translate "Proposed Changes"):\n\n"
confirmation_text+="$proposed_changes\n"
confirmation_text+="$(translate "A backup will be created before making changes.")\n\n" local timestamp=$(date +"%Y%m%d_%H%M%S")
confirmation_text+="$(translate "Do you want to proceed with these repairs?")" local preview_backup_file="$BACKUP_DIR/interfaces_backup_$timestamp"
if ! dialog --title "$(translate "Confirm Bridge Repair")" \
--yesno "$confirmation_text" 18 70; then if ! dialog --backtitle "ProxMenux" --title "$(translate "Step") $step/$total_steps: $(translate "Safety Backup")" \
--yesno "$(translate "Before making any changes, we'll create a safety backup.")\n\n$(translate "Backup location"): $preview_backup_file\n\n$(translate "Continue?")" 12 70; then
return return
fi fi
((step++))
show_proxmenux_logo show_proxmenux_logo
echo -e local backup_file=$(backup_network_config)
backup_network_config
sleep 1 sleep 1
dialog --backtitle "ProxMenux" --title "$(translate "Backup Created")" \
--msgbox "$(translate "Safety backup created"): $backup_file\n\n$(translate "You can restore it anytime with"):\ncp $backup_file /etc/network/interfaces" 10 70
local repair_log="" # Step 2: Show current configuration
repair_log+="$(translate "Bridge Repair Process")\n" if ! dialog --backtitle "ProxMenux" --title "$(translate "Step") $step/$total_steps: $(translate "Current Configuration")" \
repair_log+="$(printf '=%.0s' {1..30})\n\n" --yesno "$(translate "Let's review your current network configuration.")\n\n$(translate "Would you like to see the current") /etc/network/interfaces $(translate "file?")" 10 70; then
return
fi
((step++))
# Show current config
local temp_config=$(mktemp)
cat /etc/network/interfaces > "$temp_config"
dialog --backtitle "ProxMenux" --title "$(translate "Current Network Configuration")" \
--textbox "$temp_config" 20 80
rm -f "$temp_config"
# Step 3: Identify specific changes needed
local physical_interfaces=($(detect_physical_interfaces))
local bridges=($(detect_bridge_interfaces))
local changes_needed=""
for bridge in "${bridges[@]}"; do for bridge in "${bridges[@]}"; do
local current_ports=$(grep -A5 "iface $bridge" /etc/network/interfaces 2>/dev/null | grep "bridge-ports" | cut -d' ' -f2-) local current_ports=$(grep -A5 "iface $bridge" /etc/network/interfaces 2>/dev/null | grep "bridge-ports" | cut -d' ' -f2-)
if [ -n "$current_ports" ]; then if [ -n "$current_ports" ]; then
local valid_ports="" for port in $current_ports; do
if ! ip link show "$port" >/dev/null 2>&1; then
if [ ${#physical_interfaces[@]} -gt 0 ]; then
changes_needed+="$(translate "Bridge") $bridge: $(translate "Replace") '$port' $(translate "with") '${physical_interfaces[0]}'\n"
else
changes_needed+="$(translate "Bridge") $bridge: $(translate "Remove invalid port") '$port'\n"
fi
fi
done
fi
done
if [ -z "$changes_needed" ]; then
dialog --backtitle "ProxMenux" --title "$(translate "No Changes Needed")" \
--msgbox "$(translate "After detailed analysis, no changes are needed.")" 8 50
return
fi
if ! dialog --backtitle "ProxMenux" --title "$(translate "Step") $step/$total_steps: $(translate "Proposed Changes")" \
--yesno "$(translate "These are the changes that will be made"):\n\n$changes_needed\n$(translate "Do you want to proceed?")" 15 70; then
return
fi
((step++))
# Step 4: Apply changes with verification
dialog --backtitle "ProxMenux" --title "$(translate "Step") $step/$total_steps: $(translate "Applying Changes")" \
--infobox "$(translate "Applying changes safely...")\n\n$(translate "This may take a few seconds...")" 8 50
# Apply the changes
for bridge in "${bridges[@]}"; do
local current_ports=$(grep -A5 "iface $bridge" /etc/network/interfaces 2>/dev/null | grep "bridge-ports" | cut -d' ' -f2-)
if [ -n "$current_ports" ]; then
local new_ports=""
for port in $current_ports; do for port in $current_ports; do
if ip link show "$port" >/dev/null 2>&1; then if ip link show "$port" >/dev/null 2>&1; then
valid_ports+="$port " new_ports+="$port "
else
repair_log+="$(translate "Removed invalid port"): $port $(translate "from") $bridge\n"
fi fi
done done
if [ -z "$valid_ports" ] && [ ${#physical_interfaces[@]} -gt 0 ]; then # If no valid ports and we have physical interfaces, use the first one
valid_ports="${physical_interfaces[0]}" if [ -z "$new_ports" ] && [ ${#physical_interfaces[@]} -gt 0 ]; then
repair_log+="$(translate "Assigned port"): ${physical_interfaces[0]} $(translate "to") $bridge\n" new_ports="${physical_interfaces[0]}"
fi fi
if [ "$valid_ports" != "$current_ports" ]; then # Apply the change
sed -i "/iface $bridge/,/bridge-ports/ s/bridge-ports.*/bridge-ports $valid_ports/" /etc/network/interfaces if [ "$new_ports" != "$current_ports" ]; then
repair_log+="$(translate "Updated bridge"): $bridge\n" sed -i "/iface $bridge/,/bridge-ports/ s/bridge-ports.*/bridge-ports $new_ports/" /etc/network/interfaces
else
repair_log+="$(translate "Bridge OK"): $bridge\n"
fi fi
fi fi
done done
((step++))
dialog --title "$(translate "Bridge Repair Complete")" \ # Step 5: Verification
--msgbox "$repair_log" 15 70 local verification_report=""
} verification_report+="$(translate "CHANGES APPLIED SUCCESSFULLY")\n\n"
verification_report+="$(translate "Verification"):\n"
clean_network_configuration() {
show_proxmenux_logo
msg_info "$(translate "Analyzing Network Configuration")"
sleep 1
for bridge in "${bridges[@]}"; do
local configured_interfaces=($(grep "^iface" /etc/network/interfaces | awk '{print $2}' | grep -v "lo")) local new_ports=$(grep -A5 "iface $bridge" /etc/network/interfaces 2>/dev/null | grep "bridge-ports" | cut -d' ' -f2-)
local interfaces_to_remove="" verification_report+="$(translate "Bridge") $bridge: $new_ports\n"
for iface in "${configured_interfaces[@]}"; do # Verify each port exists
if [[ ! $iface =~ ^(vmbr|bond) ]] && ! ip link show "$iface" >/dev/null 2>&1; then for port in $new_ports; do
interfaces_to_remove+="$iface " if ip link show "$port" >/dev/null 2>&1; then
fi verification_report+="$port: $(translate "EXISTS")\n"
done else
cleanup verification_report+="$port: $(translate "NOT FOUND")\n"
if [ -z "$interfaces_to_remove" ]; then fi
dialog --title "$(translate "Configuration Analysis")" \ done
--msgbox "\n$(translate "No invalid interface configurations found.")" 8 60
return
fi
local confirmation_text=""
confirmation_text+="$(translate "Invalid Interface Configurations Found"):\n\n"
confirmation_text+="$(translate "The following interfaces are configured but don't exist"):\n"
confirmation_text+="$interfaces_to_remove\n\n"
confirmation_text+="$(translate "These configurations will be removed from") /etc/network/interfaces\n"
confirmation_text+="$(translate "A backup will be created before making changes.")\n\n"
confirmation_text+="$(translate "Do you want to proceed with cleanup?")"
if ! dialog --title "$(translate "Confirm Configuration Cleanup")" \
--yesno "$confirmation_text" 16 70; then
return
fi
show_proxmenux_logo
echo -e
backup_network_config
sleep 1
local cleanup_log=""
cleanup_log+="$(translate "Network Configuration Cleanup")\n"
cleanup_log+="$(printf '=%.0s' {1..35})\n\n"
for iface in "${configured_interfaces[@]}"; do
if [[ ! $iface =~ ^(vmbr|bond) ]] && ! ip link show "$iface" >/dev/null 2>&1; then
sed -i "/iface $iface/,/^$/d" /etc/network/interfaces
cleanup_log+="$(translate "Removed configuration for"): $iface\n"
fi
done done
cleanup_log+="$(translate "Cleanup completed")\n" verification_report+="\n$(translate "Backup available at"): $backup_file\n"
verification_report+="$(translate "To restore"): cp $backup_file /etc/network/interfaces"
dialog --title "$(translate "Configuration Cleanup Complete")" \ dialog --backtitle "ProxMenux" --title "$(translate "Step") $step/$total_steps: $(translate "Repair Complete")" \
--msgbox "$cleanup_log" 12 60 --msgbox "$verification_report" 18 70
}
# Ask about network restart
restart_network_service() { if dialog --backtitle "ProxMenux" --title "$(translate "Network Restart")" \
if dialog --title "$(translate "Restart Network")" \ --yesno "$(translate "Changes have been applied to the configuration file.")\n\n$(translate "Do you want to restart the network service to apply changes?")\n\n$(translate "WARNING: This may cause a brief disconnection.")" 12 70; then
--yesno "$(translate "This will restart the network service and may cause a brief disconnection. Continue?")" 10 60; then
clear clear
msg_info "$(translate "Restarting network service...")" msg_info "$(translate "Restarting network service...")"
@ -383,6 +512,7 @@ restart_network_service() {
msg_ok "$(translate "Network service restarted successfully")" msg_ok "$(translate "Network service restarted successfully")"
else else
msg_error "$(translate "Failed to restart network service")" msg_error "$(translate "Failed to restart network service")"
msg_warn "$(translate "You can restore the backup with"): cp $backup_file /etc/network/interfaces"
fi fi
msg_success "$(translate "Press ENTER to continue...")" msg_success "$(translate "Press ENTER to continue...")"
@ -390,8 +520,205 @@ restart_network_service() {
fi fi
} }
# ========================================================== analyze_network_configuration() {
show_proxmenux_logo
msg_info "$(translate "Analyzing Network Configuration - READ ONLY MODE")"
sleep 1
local configured_interfaces=($(grep "^iface" /etc/network/interfaces | awk '{print $2}' | grep -v "lo"))
local analysis_report=""
local issues_found=0
local suggestions=""
analysis_report+="🔍 $(translate "NETWORK CONFIGURATION ANALYSIS")\n"
analysis_report+="$(printf '=%.0s' {1..50})\n\n"
cleanup
if [ ${#configured_interfaces[@]} -eq 0 ]; then
analysis_report+=" $(translate "No network interfaces configured (besides loopback)")\n"
dialog --title "$(translate "Configuration Analysis")" --msgbox "$analysis_report" 10 60
return
fi
analysis_report+="📋 $(translate "CONFIGURED INTERFACES")\n"
analysis_report+="$(printf '=%.0s' {1..30})\n"
# Analyze each configured interface
for iface in "${configured_interfaces[@]}"; do
analysis_report+="🔌 $(translate "Interface"): $iface\n"
# Check if interface exists physically
if ip link show "$iface" >/dev/null 2>&1; then
local status=$(ip link show "$iface" 2>/dev/null | grep -o "state [A-Z]*" | cut -d' ' -f2)
local ip=$(ip -4 addr show "$iface" 2>/dev/null | grep -oP '(?<=inet\s)\d+(\.\d+){3}/\d+' | head -1)
analysis_report+="$(translate "Status"): $(translate "EXISTS") ($status)\n"
analysis_report+=" 🌐 $(translate "IP"): ${ip:-$(translate "No IP assigned")}\n"
# Check if it's a bridge or bond (these are virtual, so it's normal they exist)
if [[ $iface =~ ^(vmbr|bond) ]]; then
analysis_report+=" $(translate "Type"): $(translate "Virtual interface (normal)")\n"
else
analysis_report+=" $(translate "Type"): $(translate "Physical interface")\n"
fi
else
analysis_report+="$(translate "Status"): $(translate "NOT FOUND")\n"
analysis_report+=" ⚠️ $(translate "Issue"): $(translate "Configured but doesn't exist")\n"
((issues_found++))
# Only suggest removal for non-virtual interfaces
if [[ ! $iface =~ ^(vmbr|bond) ]]; then
suggestions+="🔧 $(translate "SUGGESTION FOR") $iface:\n"
suggestions+=" $(translate "This interface is configured but doesn't exist physically")\n"
suggestions+=" $(translate "Consider removing its configuration")\n"
suggestions+=" $(translate "Command"): sed -i '/iface $iface/,/^$/d' /etc/network/interfaces\n\n"
fi
fi
analysis_report+="\n"
done
# Summary
analysis_report+="📊 $(translate "ANALYSIS SUMMARY")\n"
analysis_report+="$(printf '=%.0s' {1..25})\n"
analysis_report+="$(translate "Interfaces configured"): ${#configured_interfaces[@]}\n"
analysis_report+="$(translate "Issues found"): $issues_found\n\n"
if [ $issues_found -gt 0 ]; then
analysis_report+="$suggestions"
analysis_report+="⚠️ $(translate "IMPORTANT"): $(translate "No changes have been made to your system")\n"
analysis_report+="$(translate "Use the Guided Cleanup option to fix issues safely")\n"
else
analysis_report+="$(translate "No configuration issues found")\n"
fi
# Show analysis in scrollable dialog
local temp_file=$(mktemp)
echo -e "$analysis_report" > "$temp_file"
dialog --backtitle "ProxMenux" --title "$(translate "Network Configuration Analysis")" \
--textbox "$temp_file" 25 80
rm -f "$temp_file"
# Offer guided cleanup if issues found
if [ $issues_found -gt 0 ]; then
if dialog --backtitle "ProxMenux" --title "$(translate "Guided Cleanup Available")" \
--yesno "$(translate "Issues were found. Would you like to use the Guided Cleanup Assistant?")" 8 60; then
guided_configuration_cleanup
fi
fi
}
guided_configuration_cleanup() {
local step=1
local total_steps=5
local timestamp=$(date +"%Y%m%d_%H%M%S")
local preview_backup_file="$BACKUP_DIR/interfaces_backup_$timestamp"
if ! dialog --backtitle "ProxMenux" --title "$(translate "Step") $step/$total_steps: $(translate "Safety Backup")" \
--yesno "$(translate "Before making any changes, we'll create a safety backup.")\n\n$(translate "Backup location"): $preview_backup_file\n\n$(translate "Continue?")" 12 70; then
return
fi
((step++))
show_proxmenux_logo
local backup_file=$(backup_network_config)
sleep 1
dialog --backtitle "ProxMenux" --title "$(translate "Backup Created")" \
--msgbox "$(translate "Safety backup created"): $backup_file\n\n$(translate "You can restore it anytime with"):\ncp $backup_file /etc/network/interfaces" 10 70
# Step 2: Identify interfaces to remove
local configured_interfaces=($(grep "^iface" /etc/network/interfaces | awk '{print $2}' | grep -v "lo"))
local interfaces_to_remove=""
local removal_list=""
for iface in "${configured_interfaces[@]}"; do
if [[ ! $iface =~ ^(vmbr|bond) ]] && ! ip link show "$iface" >/dev/null 2>&1; then
interfaces_to_remove+="$iface "
removal_list+="$iface: $(translate "Configured but doesn't exist")\n"
fi
done
if [ -z "$interfaces_to_remove" ]; then
dialog --backtitle "ProxMenux" --title "$(translate "No Cleanup Needed")" \
--msgbox "$(translate "After detailed analysis, no cleanup is needed.")" 8 50
return
fi
if ! dialog --backtitle "ProxMenux" --title "$(translate "Step") $step/$total_steps: $(translate "Interfaces to Remove")" \
--yesno "$(translate "These interface configurations will be removed"):\n\n$removal_list\n$(translate "Do you want to proceed?")" 15 70; then
return
fi
((step++))
# Step 3: Show what will be removed
local temp_preview=$(mktemp)
echo "$(translate "Configuration sections that will be REMOVED"):" > "$temp_preview"
echo "=================================================" >> "$temp_preview"
echo "" >> "$temp_preview"
for iface in $interfaces_to_remove; do
echo "# Interface: $iface" >> "$temp_preview"
sed -n "/^iface $iface/,/^$/p" /etc/network/interfaces >> "$temp_preview"
echo "" >> "$temp_preview"
done
if ! dialog --backtitle "ProxMenux" --title "$(translate "Step") $step/$total_steps: $(translate "Preview Changes")" \
--yesno "$(translate "Review what will be removed"):\n\n$(translate "Press OK to see the preview, then confirm")" 10 60; then
rm -f "$temp_preview"
return
fi
dialog --backtitle "ProxMenux" --title "$(translate "Configuration to be Removed")" \
--textbox "$temp_preview" 20 80
rm -f "$temp_preview"
if ! dialog --backtitle "ProxMenux" --title "$(translate "Final Confirmation")" \
--yesno "$(translate "Are you sure you want to remove these configurations?")" 8 60; then
return
fi
((step++))
# Step 4: Apply changes
dialog --backtitle "ProxMenux" --title "$(translate "Step") $step/$total_steps: $(translate "Applying Changes")" \
--infobox "$(translate "Removing invalid configurations...")\n\n$(translate "This may take a few seconds...")" 8 50
for iface in $interfaces_to_remove; do
sed -i "/^iface $iface/,/^$/d" /etc/network/interfaces
done
((step++))
# Step 5: Verification
local verification_report=""
verification_report+="$(translate "CLEANUP COMPLETED SUCCESSFULLY")\n\n"
verification_report+="$(translate "Removed configurations for"):\n"
for iface in $interfaces_to_remove; do
verification_report+="$iface\n"
done
verification_report+="\n$(translate "Verification"): $(translate "Checking remaining interfaces")\n"
local remaining_interfaces=($(grep "^iface" /etc/network/interfaces | awk '{print $2}' | grep -v "lo"))
for iface in "${remaining_interfaces[@]}"; do
if ip link show "$iface" >/dev/null 2>&1; then
verification_report+="$iface: $(translate "OK")\n"
else
verification_report+="⚠️ $iface: $(translate "Still has issues")\n"
fi
done
verification_report+="\n$(translate "Backup available at"): $backup_file\n"
verification_report+="$(translate "To restore"): cp $backup_file /etc/network/interfaces"
dialog --backtitle "ProxMenux" --title "$(translate "Step") $step/$total_steps: $(translate "Cleanup Complete")" \
--msgbox "$verification_report" 18 70
}
# ==========================================================
# Configuration Management
show_network_config() { show_network_config() {
local config_content local config_content
config_content=$(cat /etc/network/interfaces) config_content=$(cat /etc/network/interfaces)
@ -406,63 +733,99 @@ show_network_config() {
read -r read -r
} }
create_network_backup_manual() {
show_proxmenux_logo
echo -e
msg_info "$(translate "Creating backup of network interfaces configuration...")"
sleep 3
backup_network_config
echo -e
msg_success "$(translate "Press Enter to continue...")"
read -r
}
restore_network_backup() { restore_network_backup() {
local backups=($(ls -1 "$BACKUP_DIR"/interfaces_backup_* 2>/dev/null | sort -r)) local backups=($(ls -1 "$BACKUP_DIR"/interfaces_backup_* 2>/dev/null | sort -r))
if [ ${#backups[@]} -eq 0 ]; then if [ ${#backups[@]} -eq 0 ]; then
dialog --title "$(translate "No Backups")" \ dialog --backtitle "ProxMenux" --title "$(translate "No Backups")" \
--msgbox "$(translate "No network configuration backups found.")" 8 50 --msgbox "\n$(translate "No network configuration backups found.")" 14 60
return return
fi fi
local menu_items=() local menu_items=()
local counter=1 local counter=1
for backup in "${backups[@]}"; do for backup in "${backups[@]}"; do
local filename=$(basename "$backup") local filename=$(basename "$backup")
local timestamp=$(echo "$filename" | sed 's/interfaces_backup_//' | sed 's/_/ /') local timestamp=$(basename "$backup" | sed 's/interfaces_backup_//')
menu_items+=("$counter" "$timestamp") menu_items+=("$counter" "$timestamp")
((counter++)) ((counter++))
done done
local selection=$(dialog --title "$(translate "Restore Backup")" \ local selection=$(dialog --backtitle "ProxMenux" --title "$(translate "Restore Backup")" \
--menu "$(translate "Select backup to restore:"):" 15 60 8 \ --menu "$(translate "Select backup to restore:"):" 15 60 8 \
"${menu_items[@]}" 3>&1 1>&2 2>&3) "${menu_items[@]}" 3>&1 1>&2 2>&3)
if [ -n "$selection" ] && [ "$selection" -ge 1 ] && [ "$selection" -le ${#backups[@]} ]; then if [ -n "$selection" ] && [ "$selection" -ge 1 ] && [ "$selection" -le ${#backups[@]} ]; then
local selected_backup="${backups[$((selection-1))]}" local selected_backup="${backups[$((selection-1))]}"
if dialog --title "$(translate "Confirm Restore")" \
--yesno "$(translate "Are you sure you want to restore this backup? Current configuration will be overwritten.")" 10 60; then if dialog --backtitle "ProxMenux" --title "$(translate "Preview Backup")" \
--yesno "\n$(translate "Do you want to view the selected backup before restoring?")" 8 60; then
dialog --backtitle "ProxMenux" --title "$(translate "Backup Preview")" \
--textbox "$selected_backup" 22 80
fi
if dialog --backtitle "ProxMenux" --title "$(translate "Confirm Restore")" \
--yesno "\n$(translate "Are you sure you want to restore this backup?\nCurrent configuration will be overwritten.")\n\n$(translate "For your safety, a backup of the current configuration will be created automatically before restoring.")" 14 70; then
local pre_restore_backup=$(backup_network_config)
cp "$selected_backup" /etc/network/interfaces cp "$selected_backup" /etc/network/interfaces
dialog --title "$(translate "Backup Restored")" \
--msgbox "$(translate "Network configuration has been restored from backup.")" 8 60
dialog --backtitle "ProxMenux" --title "$(translate "Backup Restored")" \
--msgbox "\n$(translate "Network configuration has been restored from backup.")" 8 60
if dialog --backtitle "ProxMenux" --title "$(translate "Restart Network")" \
--yesno "\n$(translate "Do you want to restart the network service now to apply changes?")" 8 60; then
if systemctl restart networking; then
dialog --backtitle "ProxMenux" --title "$(translate "Network Restarted")" \
--msgbox "\n$(translate "Network service restarted successfully.")" 8 50
fi
fi
fi fi
fi fi
} }
# ==========================================================
# ==========================================================
# Main Menu
show_main_menu() { show_main_menu() {
while true; do while true; do
local selection=$(dialog --clear \ local selection=$(dialog --clear \
--backtitle "ProxMenux" \ --backtitle "ProxMenux" \
--title "$(translate "Network Management")" \ --title "$(translate "Network Management - SAFE MODE")" \
--menu "$(translate "Select an option:"):" 20 70 12 \ --menu "$(translate "Select an option:"):" 20 70 12 \
"1" "$(translate "Show Interface Details")" \ "1" "$(translate "Show Interface Details")" \
"2" "$(translate "Show Bridge Status")" \ "2" "$(translate "Show Bridge Status")" \
"3" "$(translate "Show Routing Table")" \ "3" "$(translate "Show Routing Table")" \
"4" "$(translate "Test Connectivity")" \ "4" "$(translate "Test Connectivity")" \
"5" "$(translate "Advanced Diagnostics")" \ "5" "$(translate "Advanced Diagnostics")" \
"6" "$(translate "Analyze Bridge Configuration")" \
"7" "$(translate "Analyze Network Configuration")" \
"8" "$(translate "Restart Network Service")" \ "8" "$(translate "Restart Network Service")" \
"9" "$(translate "Show Network Config File")" \ "9" "$(translate "Show Network Config File")" \
"10" "$(translate "Restore Network Backup")" \ "10" "$(translate "Create Network Backup")" \
"11" "$(translate "Restore Network Backup")" \
"0" "$(translate "Return to Main Menu")" \ "0" "$(translate "Return to Main Menu")" \
3>&1 1>&2 2>&3) 3>&1 1>&2 2>&3)
# "6" "$(translate "Repair Bridge Configuration")" \
# "7" "$(translate "Clean Network Configuration")" \
case $selection in case $selection in
1) show_interface_details ;; 1) show_interface_details ;;
@ -470,15 +833,16 @@ show_main_menu() {
3) show_routing_table ;; 3) show_routing_table ;;
4) test_connectivity ;; 4) test_connectivity ;;
5) advanced_network_diagnostics ;; 5) advanced_network_diagnostics ;;
6) repair_bridge_configuration ;; 6) analyze_bridge_configuration ;;
7) clean_network_configuration ;; 7) analyze_network_configuration ;;
8) restart_network_service ;; 8) restart_network_service ;;
9) show_network_config ;; 9) show_network_config ;;
10) restore_network_backup ;; 10) create_network_backup_manual ;;
11) restore_network_backup ;;
0|"") exec bash <(curl -s "$REPO_URL/scripts/menus/main_menu.sh") ;; 0|"") exec bash <(curl -s "$REPO_URL/scripts/menus/main_menu.sh") ;;
esac esac
done done
} }
# ========================================================== # ==========================================================
show_main_menu show_main_menu