diff --git a/debian/set_mac_wifi.sh b/debian/set_mac_wifi.sh index 32e3acb..2636d70 100644 --- a/debian/set_mac_wifi.sh +++ b/debian/set_mac_wifi.sh @@ -1,40 +1,29 @@ #!/bin/bash # Script Dinâmico de Configuração de Rede para Raspberry Pi # Localização: /usr/local/bin/configure_network.sh +# Descrição: Configura MAC address persistente para interface eth0 e monitoriza estado da rede # --- Configurações --- LOG_FILE="/var/log/network_config.log" UDEV_RULES_FILE="/etc/udev/rules.d/81-mac-spoof.rules" +IFACE="eth0" +WLAN_IFACE="wlan0" # --- Funções Auxiliares --- # Função de Log log() { - echo "$(date '+%Y-%m-%d %H:%M:%S'): $1" | tee -a "$LOG_FILE" + local timestamp=$(date '+%Y-%m-%d %H:%M:%S') + echo "$timestamp: $1" | tee -a "$LOG_FILE" } -# Function to disable Wi-Fi -disable_wifi() { - # Create log directory if it doesn't exist - mkdir -p /var/log - - # Wait for 1 minute (60 seconds) before disabling Wi-Fi - echo "$(date): Waiting 60 seconds before checking eth0 IP and disabling Wi-Fi..." | tee -a /var/log/set_mac.log - sleep 60 - - # Check if eth0 has an IP address before disabling Wi-Fi - if has_ip_address "eth0"; then - if ip link show "wlan0" &> /dev/null; then - if ip link set "wlan0" down; then - echo "$(date): Wi-Fi (wlan0) disabled successfully (eth0 has IP)" | tee -a /var/log/set_mac.log - else - echo "$(date): Failed to disable Wi-Fi (wlan0)" | tee -a /var/log/set_mac.log - fi - else - echo "$(date): wlan0 interface not found (Wi-Fi already disabled?)" | tee -a /var/log/set_mac.log - fi +# Função para verificar se a interface tem IP +has_ip_address() { + local iface="$1" + if ip addr show "$iface" | grep -q "inet "; then + return 0 else - echo "$(date): eth0 does not have an IP address. Wi-Fi remains active." | tee -a /var/log/set_mac.log + return 1 fi } @@ -42,19 +31,16 @@ disable_wifi() { ask_confirmation() { local message="$1" local default="$2" # "y" or "n" - while true; do if [ "$default" = "y" ]; then read -p "$message [Y/n]: " choice < /dev/tty else read -p "$message [y/N]: " choice < /dev/tty fi - # Default choice if user just presses Enter if [ -z "$choice" ]; then choice="$default" fi - case "$choice" in y|Y|yes|Yes|YES) return 0 @@ -75,7 +61,13 @@ generate_unique_mac() { serial=$(awk '/Serial/ {print $3}' /proc/cpuinfo | tr -d ' ') if [ -z "$serial" ]; then - printf '%02X:%02X:%02X:%02X:%02X:%02X' $((0x02 | (RANDOM % 256) & 0xFE)) $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) + # Fallback: generate random MAC if serial not available + printf '%02X:%02X:%02X:%02X:%02X:%02X' $((0x02 | (RANDOM % 256) & 0xFE)) \ + $((RANDOM % 256)) \ + $((RANDOM % 256)) \ + $((RANDOM % 256)) \ + $((RANDOM % 256)) \ + $((RANDOM % 256)) else local hash hash=$(echo -n "$serial-dm9601" | md5sum | cut -c1-10) @@ -83,6 +75,12 @@ generate_unique_mac() { fi } +# Função para obter o MAC atual da interface +get_current_mac() { + local interface="$1" + ip link show "$interface" | awk '/ether/ {print $2}' | tr '[:upper:]' '[:lower:]' +} + # Função para definir MAC imediatamente set_mac() { local interface="$1" @@ -94,6 +92,7 @@ set_mac() { fi log "A definir MAC $mac em $interface..." + if ip link set "$interface" down && \ ip link set dev "$interface" address "$mac" && \ ip link set "$interface" up; then @@ -105,13 +104,14 @@ set_mac() { fi } -# Função para criar regra Udev +# Função para criar/atualizar regra Udev setup_udev_persistence() { local interface="$1" local target_mac="$2" - local original_mac - original_mac=$(ip link show "$interface" | awk '/ether/ {print $2}' | tr '[:upper:]' '[:lower:]') + local rule_content + + original_mac=$(get_current_mac "$interface") target_mac=$(echo "$target_mac" | tr '[:upper:]' '[:lower:]') if [ -z "$original_mac" ]; then @@ -120,44 +120,77 @@ setup_udev_persistence() { fi # Cria o conteúdo da regra - local rule_content="ACTION==\"add\", SUBSYSTEM==\"net\", ATTR{address}==\"$original_mac\", RUN+=\"/usr/bin/ip link set dev \$name address $target_mac\"" + rule_content="ACTION==\"add\", SUBSYSTEM==\"net\", ATTR{address}==\"$original_mac\", RUN+=\"/usr/bin/ip link set dev \$name address $target_mac\"" + + # Cria diretório se não existir + mkdir -p "$(dirname "$UDEV_RULES_FILE")" # Escreve no ficheiro de regras echo "$rule_content" > "$UDEV_RULES_FILE" # Verifica se o ficheiro foi criado com sucesso if [ -f "$UDEV_RULES_FILE" ]; then - log "Sucesso: Ficheiro de regras Udev criado em $UDEV_RULES_FILE." + log "Sucesso: Ficheiro de regras Udev criado/atualizado em $UDEV_RULES_FILE." log "Conteúdo da regra: $rule_content" else - log "Erro: Falha ao criar o ficheiro de regras Udev em $UDEV_RULES_FILE." + log "Erro: Falha ao criar/atualizar o ficheiro de regras Udev em $UDEV_RULES_FILE." return 1 fi # Recarrega as regras do udev - if udevadm control --reload-rules; then - log "Regras Udev recarregadas com sucesso." + if udevadm control --reload-rules && udevadm trigger; then + log "Regras Udev recarregadas e aplicadas com sucesso." + return 0 else - log "Erro: Falha ao recarregar regras Udev." + log "Erro: Falha ao recarregar/aplicar regras Udev." + return 1 + fi +} + +# Função para verificar se a persistência está configurada corretamente +is_persistence_configured() { + local current_mac + local udev_mac + + if [ ! -f "$UDEV_RULES_FILE" ] || [ ! -s "$UDEV_RULES_FILE" ]; then + log "Ficheiro de persistência não encontrado ou vazio." return 1 fi - return 0 + current_mac=$(get_current_mac "$IFACE") + udev_mac=$(grep -oP 'address \K([0-9a-f]{2}:){5}[0-9a-f]{2}' "$UDEV_RULES_FILE") + + if [ "$current_mac" = "$udev_mac" ]; then + log "Persistência verificada: MAC atual ($current_mac) coincide com regra Udev." + return 0 + else + log "Persistência desatualizada: MAC atual ($current_mac) não coincide com regra Udev ($udev_mac)." + return 1 + fi } -# Função robusta para verificar persistência -is_persistence_configured() { - if [ -f "$UDEV_RULES_FILE" ]; then - if [ -s "$UDEV_RULES_FILE" ]; then - log "Ficheiro de persistência encontrado: $UDEV_RULES_FILE" - return 0 +# Função para desativar Wi-Fi +disable_wifi() { + # Cria diretório de log se não existir + mkdir -p /var/log + + # Aguarda 60 segundos antes de verificar IP e desativar Wi-Fi + log "A aguardar 60 segundos antes de verificar IP de $IFACE e desativar Wi-Fi..." + sleep 60 + + # Verifica se eth0 tem IP antes de desativar Wi-Fi + if has_ip_address "$IFACE"; then + if ip link show "$WLAN_IFACE" &> /dev/null; then + if ip link set "$WLAN_IFACE" down; then + log "Wi-Fi ($WLAN_IFACE) desativado com sucesso ($IFACE tem IP)" + else + log "Falha ao desativar Wi-Fi ($WLAN_IFACE)" + fi else - log "Ficheiro de persistência existe mas está vazio. Invalidando." - return 1 + log "Interface $WLAN_IFACE não encontrada (Wi-Fi já desativado?)" fi else - log "Ficheiro de persistência NÃO encontrado." - return 1 + log "$IFACE não tem endereço IP. Wi-Fi permanece ativo." fi } @@ -166,24 +199,54 @@ monitor_network_task() { log "Monitor: A iniciar verificação de rede (aguardando 60s)..." sleep 60 - local interface="eth0" - local wlan="wlan0" - - if ip link show "$interface" &> /dev/null; then - if ip link show "$interface" | grep -q "NO-CARRIER"; then - log "Monitor: Interface $interface sem cabo (NO-CARRIER). A ativar Wi-Fi..." - if ip link show "$wlan" &> /dev/null; then - ip link set "$wlan" up - log "Monitor: Wi-Fi ($wlan) ativado." + if ip link show "$IFACE" &> /dev/null; then + if ip link show "$IFACE" | grep -q "NO-CARRIER"; then + log "Monitor: Interface $IFACE sem cabo (NO-CARRIER). A ativar Wi-Fi..." + if ip link show "$WLAN_IFACE" &> /dev/null; then + ip link set "$WLAN_IFACE" up + log "Monitor: Wi-Fi ($WLAN_IFACE) ativado." fi else - log "Monitor: Interface $interface ativa. Nenhuma ação necessária." + log "Monitor: Interface $IFACE ativa. Nenhuma ação necessária." + fi + fi +} + +# Função principal para configurar MAC +configure_mac() { + local target_mac="$1" + + # Validação do MAC + if [[ ! "$target_mac" =~ ^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$ ]]; then + log "MAC Address inválido: $target_mac" + return 1 + fi + + log "A configurar sistema com MAC: $target_mac" + + # Aplica o MAC na sessão atual + if set_mac "$IFACE" "$target_mac"; then + # Atualiza a regra Udev independentemente do estado anterior + if setup_udev_persistence "$IFACE" "$target_mac"; then + log "Configuração de MAC e persistência concluída com sucesso." + return 0 + else + log "Aviso: MAC definido mas persistência falhou." + return 1 + fi + else + log "Aviso: Falha ao definir MAC em tempo real, mas a tentar criar persistência..." + if setup_udev_persistence "$IFACE" "$target_mac"; then + log "Persistência criada, mas MAC não foi aplicado na sessão atual." + return 1 + else + log "Erro: Falha completa na configuração de MAC." + return 1 fi fi } # --- Execução Principal --- - if [ "$(id -u)" -ne 0 ]; then echo "Este script deve ser executado como root." >&2 exit 1 @@ -191,50 +254,31 @@ fi mkdir -p "$(dirname "$LOG_FILE")" -# 1. Verificar Persistência Existente -if is_persistence_configured; then - log "Configuração já persistida no sistema. A saltar configuração de MAC." +# 1. Verificar se a interface existe +if ! ip link show "$IFACE" &> /dev/null; then + log "Erro: Interface $IFACE não disponível. A sair." + exit 1 +fi - # Função auxiliar para verificar se a interface tem IP - has_ip_address() { - local iface="$1" - if ip addr show "$iface" | grep -q "inet "; then - return 0 - else - return 1 - fi - } +# 2. Verificar se já existe configuração de persistência +if is_persistence_configured; then + log "Configuração de persistência verificada. A saltar configuração inicial." # Verifica se eth0 tem IP antes de desativar Wi-Fi - if has_ip_address "eth0"; then + if has_ip_address "$IFACE"; then if ! pgrep -f "disable_wifi" > /dev/null; then disable_wifi & else log "disable_wifi já está em execução." fi else - log "eth0 não tem endereço IP. Wi-Fi permanece ativo." + log "$IFACE não tem endereço IP. Wi-Fi permanece ativo." fi monitor_network_task & exit 0 fi -# 2. Esperar pela Interface de Rede (Importante para boot/curl) -IFACE="eth0" -log "A aguardar pela interface $IFACE..." -for i in {1..30}; do - if ip link show "$IFACE" &> /dev/null; then - break - fi - sleep 1 -done - -if ! ip link show "$IFACE" &> /dev/null; then - log "Erro: Interface $IFACE não disponível após 30 segundos. A sair." - exit 1 -fi - # 3. Determinar o MAC Address TARGET_MAC="" @@ -246,33 +290,21 @@ else # Verificar se é boot (não interativo e sem /dev/tty disponível) if [ ! -t 0 ] && [ ! -e /dev/tty ]; then # Modo boot: Não fazer nada, assumindo que já foi configurado - log "${YELLOW}Modo boot: A saltar configuração de MAC (assumindo que já foi configurado)${NC}" + log "Modo boot: A saltar configuração de MAC (assumindo que já foi configurado)" - # Função auxiliar para verificar se a interface tem IP - has_ip_address() { - local iface="$1" - if ip addr show "$iface" | grep -q "inet "; then - return 0 - else - return 1 - fi - } - - # Verifica se eth0 tem IP antes de desativar Wi-Fi - if has_ip_address "eth0"; then + if has_ip_address "$IFACE"; then if ! pgrep -f "disable_wifi" > /dev/null; then disable_wifi & else log "disable_wifi já está em execução." fi else - log "eth0 não tem endereço IP. Wi-Fi permanece ativo." + log "$IFACE não tem endereço IP. Wi-Fi permanece ativo." fi - exit 0 else - # Modo interativo ou via curl: Perguntar ao utilizador o que fazer - if ask_confirmation "Deseja configurar um novo MAC para a interface eth0?" "y"; then + # Modo interativo: Perguntar ao utilizador o que fazer + if ask_confirmation "Deseja configurar um novo MAC para a interface $IFACE?" "y"; then if ask_confirmation "Deseja gerar um novo MAC único automaticamente?" "y"; then TARGET_MAC=$(generate_unique_mac) log "MAC gerado automaticamente: $TARGET_MAC" @@ -288,29 +320,20 @@ else done fi else - log "${YELLOW}Configuração de MAC cancelada pelo utilizador${NC}" + log "Configuração de MAC cancelada pelo utilizador" exit 0 fi fi fi -# Validação simples do MAC -if [[ ! "$TARGET_MAC" =~ ^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$ ]]; then - log "MAC Address inválido ou vazio: $TARGET_MAC" - exit 1 -fi - -# 4. Aplicar Configuração -log "A configurar sistema com MAC: $TARGET_MAC" - -if set_mac "$IFACE" "$TARGET_MAC"; then - setup_udev_persistence "$IFACE" "$TARGET_MAC" +# 4. Configurar MAC e persistência +if configure_mac "$TARGET_MAC"; then + log "Configuração concluída com sucesso." else - log "Aviso: Falha ao definir MAC em tempo real, mas a tentar criar persistência..." - setup_udev_persistence "$IFACE" "$TARGET_MAC" + log "Aviso: Configuração concluída com alguns erros." fi -# 5. Lançar Monitor de Rede +# 5. Lançar monitor de rede monitor_network_task & exit 0 \ No newline at end of file