diff --git a/debian/set_mac_wifi.sh b/debian/set_mac_wifi.sh index 3a5e0d7..ffaf70a 100644 --- a/debian/set_mac_wifi.sh +++ b/debian/set_mac_wifi.sh @@ -1,132 +1,29 @@ #!/bin/bash -# Script to set fixed MAC address and disable Wi-Fi if eth0 configuration succeeds -# Must be run with sudo! -# Update: Agora gera um MAC único automaticamente se nenhum for especificado (resolver problema do DM9601). +# Script Dinâmico de Configuração de Rede para Raspberry Pi +# Localização sugerida: /usr/local/bin/configure_network.sh +# Uso: sudo ./configure_network.sh [MAC_ADDRESS] +# Deve ser executado com privilégios de root. -# --- Configuration --- -ETH0_MAC="00:00:00:00:00:00" # Default MAC - será alterado automaticamente se mantiver este valor -# WLAN0_MAC="XX:XX:XX:XX:XX:XX" # Uncomment and set if needed +# --- Configurações --- +LOG_FILE="/var/log/network_config.log" +UDEV_RULES_FILE="/etc/udev/rules.d/81-mac-spoof.rules" -# Verify root privileges -if [ "$(id -u)" -ne 0 ]; then - echo "This script must be run as root" >&2 - exit 1 -fi +# --- Funções Auxiliares --- -# --- Functions --- -# Function to set MAC and verify success -set_mac() { - local interface="$1" - local mac="$2" - local success=false - local log_file="/var/log/set_mac.log" - - # Verifica se a interface existe - if ! ip link show "$interface" &> /dev/null; then - echo "$(date): Interface $interface não encontrada." | tee -a "$log_file" - return 1 - fi - - # Verifica se macchanger está instalado - if command -v macchanger >/dev/null 2>&1; then - echo "$(date): Usando macchanger para definir MAC de $interface para $mac" | tee -a "$log_file" - # Tenta usar macchanger - if ip link set "$interface" down && \ - macchanger -m "$mac" "$interface" >/dev/null 2>&1 && \ - ip link set "$interface" up; then - echo "$(date): Sucesso ao definir MAC com macchanger para $interface (novo: $mac)" | tee -a "$log_file" - success=true - else - echo "$(date): Falha ao definir MAC com macchanger para $interface. Tentando fallback com ip link..." | tee -a "$log_file" - fi - fi - - # Fallback para ip link (se macchanger não estiver disponível ou falhar) - if [ "$success" = false ]; then - # Tenta com ip link diretamente - if ip link set "$interface" down && \ - ip link set dev "$interface" address "$mac" && \ - ip link set "$interface" up; then - echo "$(date): Sucesso ao definir MAC com 'ip link' para $interface (novo: $mac)" | tee -a "$log_file" - success=true - else - echo "$(date): Falha ao definir MAC para $interface com ambos os métodos." | tee -a "$log_file" - return 1 - fi - fi - - # Retorna sucesso (0) ou falha (1) - return $([ "$success" = true ] && echo 0 || echo 1) +# Função de Log +log() { + echo "$(date '+%Y-%m-%d %H:%M:%S'): $1" | tee -a "$LOG_FILE" } -# Function to configure static IP -configure_static_ip() { - local ip_script="/usr/local/bin/set_static_ip.sh" - - if [ -f "$ip_script" ]; then - # Get current IP configuration - local interface - if interface=$(get_active_interface); then - local current_ip=$(ip -4 addr show "$interface" | grep -oP '(?<=inet\s)\d+(\.\d+){3}') - if [[ "$current_ip" =~ ^169\.254\. ]]; then - # Link-local address, likely no DHCP - log "No valid IP address found for $interface, configuring static IP..." - IP_ADDRESS_ENV="10.10.0.100/24" bash "$ip_script" - fi - fi - fi -} - -# Function to check if interface has IP address -has_ip_address() { - local interface="$1" - # Check if interface is UP and has an IPv4 address - if ip link show "$interface" | grep -q "state UP" && \ - ip -4 addr show "$interface" | grep -q "inet "; then - return 0 - else - return 1 - fi -} - -# 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 - else - echo "$(date): eth0 does not have an IP address. Wi-Fi remains active." | tee -a /var/log/set_mac.log - fi -} - -# --- Novas Funções Complementares (Dinâmicas) --- - -# Função para gerar um MAC único baseado no Serial do Raspberry Pi -# Garante que cada dispositivo fica com um MAC diferente mas consistente +# Função para gerar MAC único baseado no Serial do CPU generate_unique_mac() { local serial serial=$(awk '/Serial/ {print $3}' /proc/cpuinfo | tr -d ' ') if [ -z "$serial" ]; then - # Fallback aleatório caso não encontre serial + # Fallback aleatório printf '%02X:%02X:%02X:%02X:%02X:%02X' $((0x02 | (RANDOM % 256) & 0xFE)) $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) $((RANDOM % 256)) else - # Gera hash do serial para criar os octetos local hash hash=$(echo -n "$serial-dm9601" | md5sum | cut -c1-10) # 02 define como Local Admin Address @@ -134,60 +31,170 @@ generate_unique_mac() { fi } -# Função para criar regra Udev persistente (Best Practice) -# Isto faz com que o MAC seja aplicado no boot, evitando erros de "Device Busy" +# Função para definir MAC imediatamente (usada apenas na configuração inicial) +set_mac() { + local interface="$1" + local mac="$2" + + if ! ip link show "$interface" &> /dev/null; then + log "Interface $interface não encontrada." + return 1 + fi + + log "A definir MAC $mac em $interface imediatamente..." + if ip link set "$interface" down && \ + ip link set dev "$interface" address "$mac" && \ + ip link set "$interface" up; then + log "MAC alterado com sucesso na sessão atual." + return 0 + else + log "Falha ao alterar MAC na sessão atual." + return 1 + fi +} + +# Função para criar regra Udev (Persistência) setup_udev_persistence() { local interface="$1" local target_mac="$2" - local log_file="/var/log/set_mac.log" - + # Obtém o MAC original (físico) do adaptador local original_mac original_mac=$(ip link show "$interface" | awk '/ether/ {print $2}' | tr '[:upper:]' '[:lower:]') target_mac=$(echo "$target_mac" | tr '[:upper:]' '[:lower:]') - if [ -z "$original_mac" ]; then return 1; fi - - local rules_file="/etc/udev/rules.d/81-mac-spoof.rules" - - # Se a regra já existe para este MAC original, não faz nada - if grep -q "$original_mac" "$rules_file" 2>/dev/null; then - return 0 + if [ -z "$original_mac" ]; then + log "Não foi possível obter o MAC original para criar regra udev." + return 1 fi - echo "$(date): Criando regra udev persistente para $interface" | tee -a "$log_file" - echo "ACTION==\"add\", SUBSYSTEM==\"net\", ATTR{address}==\"$original_mac\", RUN+=\"/usr/bin/ip link set dev \$name address $target_mac\"" >> "$rules_file" + # Cria a regra: Ao adicionar o dispositivo com o MAC original, define o novo MAC + echo "ACTION==\"add\", SUBSYSTEM==\"net\", ATTR{address}==\"$original_mac\", RUN+=\"/usr/bin/ip link set dev \$name address $target_mac\"" > "$UDEV_RULES_FILE" + udevadm control --reload-rules + log "Regra Udev criada em $UDEV_RULES_FILE para persistência." + return 0 +} + +# Função para verificar se a persistência já está configurada +is_persistence_configured() { + if [ -f "$UDEV_RULES_FILE" ]; then + return 0 + else + return 1 + fi +} + +# Tarefa em Background para monitorizar Ethernet e ativar Wi-Fi +monitor_network_task() { + log "Iniciando tarefa de monitorização de rede (Background)..." + + # Espera inicial para o sistema estabilizar + sleep 60 + + local interface="eth0" + local wlan="wlan0" + + # Loop infinito para verificação periódica (opcional, ou apenas uma vez) + # Aqui verificamos uma vez após o boot, conforme lógica original do disable_wifi + + if ip link show "$interface" &> /dev/null; then + # Verifica 'NO-CARRIER' (cabo desligado) ou estado DOWN + if ip link show "$interface" | grep -q "NO-CARRIER" || ! ip link show "$interface" | grep -q "state UP"; then + log "Interface $interface sem ligação (cabo desligado?). A ativar Wi-Fi..." + + if ip link show "$wlan" &> /dev/null; then + ip link set "$wlan" up + # Opcional: Pode-se adicionar lógica para reiniciar o wpa_supplicant ou dhclient + # systemctl restart wpa_supplicant + log "Wi-Fi ($wlan) ativado." + fi + else + log "Interface $interface está ativa com ligação. Wi-Fi mantido inalterado." + fi + else + log "Interface $interface não encontrada para monitorização." + fi } # --- Execução Principal --- -# LÓGICA COMPLEMENTAR: -# Se ETH0_MAC for o valor padrão (00:00...) ou vazio, gera um novo automaticamente. -if [ -z "$ETH0_MAC" ] || [ "$ETH0_MAC" == "00:00:00:00:00:00" ]; then - echo "$(date): Nenhum MAC específico definido. Gerando MAC único automático..." | tee -a /var/log/set_mac.log - ETH0_MAC=$(generate_unique_mac) - echo "$(date): Novo MAC gerado: $ETH0_MAC" | tee -a /var/log/set_mac.log +# Verificar root +if [ "$(id -u)" -ne 0 ]; then + echo "Este script deve ser executado como root." >&2 + exit 1 fi -# Executa a lógica original com o MAC definido (seja o do config ou o gerado) -if set_mac "eth0" "$ETH0_MAC"; then - # Se definiu o MAC com sucesso, tenta criar persistência via Udev - # Isto resolve o problema do adapter mantendo o MAC em futuros boots - setup_udev_persistence "eth0" "$ETH0_MAC" +# Criar diretório de log se não existir +mkdir -p "$(dirname "$LOG_FILE")" - # Check if disable_wifi is already running - if ! pgrep -f "disable_wifi" > /dev/null; then - #configure_static_ip - disable_wifi & - else - echo "$(date): disable_wifi is already running" | tee -a /var/log/set_mac.log - fi +# 1. Verificar se a persistência já está feita +if is_persistence_configured; then + log "Persistência Udev já configurada. Ignorando configuração de MAC." + # Apenas lança a tarefa de monitorização de rede + monitor_network_task & + exit 0 +fi + +# 2. Determinar o MAC Address a utilizar +TARGET_MAC="" + +# 2.1. Verificar argumento passado ao script +if [ -n "$1" ]; then + TARGET_MAC="$1" + log "MAC definido via argumento: $TARGET_MAC" else - echo "$(date): Could not set MAC for eth0. Wi-Fi remains active" | tee -a /var/log/set_mac.log + # 2.2. Verificar se é uma execução interativa (terminal) + if [ -t 0 ]; then + echo "Nenhum MAC definido. Deseja:" + echo "1) Gerar um novo MAC único automático" + echo "2) Introduzir um MAC manualmente" + read -p "Opção [1/2]: " choice + + case "$choice" in + 1) + TARGET_MAC=$(generate_unique_mac) + log "MAC gerado automaticamente: $TARGET_MAC" + ;; + 2) + read -p "Introduza o MAC (formato XX:XX:XX:XX:XX:XX): " TARGET_MAC + if [[ ! "$TARGET_MAC" =~ ^([0-9A-Fa-f]{2}:){5}[0-9A-Fa-f]{2}$ ]]; then + log "Formato de MAC inválido." + exit 1 + fi + ;; + *) + log "Opção inválida. A sair." + exit 1 + ;; + esac + else + # 2.3. Execução não interativa (ex: boot) sem argumentos -> Gerar automático + log "Execução não interativa sem argumentos. A gerar MAC único..." + TARGET_MAC=$(generate_unique_mac) + log "MAC gerado: $TARGET_MAC" + fi fi -# Uncomment if you want to set MAC for wlan0 (optional) -# if [[ -n "$WLAN0_MAC" ]]; then -# set_mac "wlan0" "$WLAN0_MAC" -# fi \ No newline at end of file +# 3. Aplicar Configuração (Imediata e Persistente) +# Detectar interface (assumindo eth0 ou primeira USB) +IFACE="eth0" +if ! ip link show "$IFACE" &> /dev/null; then + # Tenta encontrar interface USB alternativa + IFACE=$(ip -o link show | grep -v "wlan0" | grep -v "lo" | awk '{print $2}' | sed 's/://' | head -n 1) + [ -z "$IFACE" ] && { log "Nenhuma interface Ethernet encontrada."; exit 1; } +fi + +log "Interface detetada: $IFACE" + +# Aplicar agora (para a sessão atual) e criar regra para o futuro (udev) +if set_mac "$IFACE" "$TARGET_MAC"; then + setup_udev_persistence "$IFACE" "$TARGET_MAC" +else + log "Erro ao aplicar configuração MAC." +fi + +# 4. Lançar tarefa de monitorização em Background +monitor_network_task & + +exit 0 \ No newline at end of file