541 lines
18 KiB
Bash
Executable File
541 lines
18 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
# ============================================================================
|
|
# DNSBlock Agent - Script de Instalação e Desinstalação
|
|
# ============================================================================
|
|
# Este script realiza a instalação ou desinstalação completa do DNSBlock Agent
|
|
# Requer privilégios de root para execução
|
|
#
|
|
# Uso:
|
|
# ./install.sh Instalação interativa
|
|
# ./install.sh uninstall Desinstalação
|
|
# ============================================================================
|
|
|
|
set -e
|
|
|
|
# Diretórios e arquivos
|
|
INSTALL_DIR="/opt/dnsblock"
|
|
RPZ_DIR="$INSTALL_DIR/rpz"
|
|
SERVICE_FILE="/etc/systemd/system/dnsblock-agent.service"
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
|
|
# Configurações do Unbound
|
|
UNBOUND_CONF_DIR="/etc/unbound/unbound.conf.d"
|
|
UNBOUND_MAIN_CONF="/etc/unbound/unbound.conf"
|
|
DNSBLOCK_UNBOUND_CONF="$INSTALL_DIR/unbound.conf"
|
|
DNSBLOCK_INCLUDE='include: "/opt/dnsblock/unbound.conf"'
|
|
|
|
# Variáveis globais
|
|
SERIAL=""
|
|
NO_SERIAL=false
|
|
UNBOUND_ERROR=""
|
|
|
|
# ============================================================================
|
|
# FUNÇÕES UTILITÁRIAS
|
|
# ============================================================================
|
|
|
|
# Verificar se está executando como root
|
|
verificar_root() {
|
|
if [ "$(id -u)" -ne 0 ]; then
|
|
whiptail --title "Erro" --msgbox "Este script deve ser executado como root.\n\nExecute novamente com sudo." 10 50
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Verificar dependências
|
|
verificar_dependencias() {
|
|
local deps_faltando=""
|
|
|
|
if ! command -v whiptail &> /dev/null; then
|
|
echo "Erro: whiptail não encontrado. Instale-o antes de continuar."
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v unbound-checkconf &> /dev/null; then
|
|
deps_faltando="$deps_faltando unbound-checkconf"
|
|
fi
|
|
|
|
if [ -n "$deps_faltando" ]; then
|
|
whiptail --title "Dependências Faltando" \
|
|
--msgbox "As seguintes dependências não foram encontradas:\n$deps_faltando\n\nPor favor, instale-as antes de continuar." 12 55
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# FUNÇÕES DE SERIAL
|
|
# ============================================================================
|
|
|
|
# Solicitar o serial via whiptail
|
|
solicitar_serial() {
|
|
local input=""
|
|
|
|
input=$(whiptail --title "DNSBlock Agent - Ativação" \
|
|
--inputbox "Digite o serial de ativação do agente:\n\n(Deixe em branco para instalar sem serial)" \
|
|
12 60 "" 3>&1 1>&2 2>&3)
|
|
|
|
local status=$?
|
|
|
|
if [ $status -ne 0 ]; then
|
|
whiptail --title "Instalação Cancelada" \
|
|
--msgbox "A instalação foi cancelada pelo usuário." 8 45
|
|
exit 0
|
|
fi
|
|
|
|
if [ -z "$input" ]; then
|
|
if whiptail --title "Instalação sem Serial" \
|
|
--yesno "Você não informou um serial.\n\nDeseja instalar sem serial?\n\n(O serviço será ativado mas não inicializado)\n\nVocê pode obter seu serial em:\nhttp://painel.dnsblock.com.br" \
|
|
14 55; then
|
|
NO_SERIAL=true
|
|
SERIAL=""
|
|
else
|
|
whiptail --title "Instalação Cancelada" \
|
|
--msgbox "A instalação foi cancelada pelo usuário." 8 45
|
|
exit 0
|
|
fi
|
|
else
|
|
SERIAL="$input"
|
|
fi
|
|
}
|
|
|
|
# Atualizar o serial no config.json
|
|
atualizar_config_serial() {
|
|
local serial="$1"
|
|
local config_file="$INSTALL_DIR/config.json"
|
|
|
|
if [ -f "$config_file" ] && [ -n "$serial" ]; then
|
|
sed -i "s/\"serial_key\":[[:space:]]*\"[^\"]*\"/\"serial_key\": \"$serial\"/" "$config_file"
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# FUNÇÕES DE CONFIGURAÇÃO DO UNBOUND
|
|
# ============================================================================
|
|
|
|
# Encontrar arquivo de configuração do Unbound para adicionar o include
|
|
encontrar_arquivo_config_unbound() {
|
|
# Prioridade: arquivo com RPZ existente > local.conf > unbound.conf principal
|
|
|
|
# Primeiro, verificar se existe algum arquivo com bloco RPZ
|
|
if [ -d "$UNBOUND_CONF_DIR" ]; then
|
|
for conf in "$UNBOUND_CONF_DIR"/*.conf; do
|
|
if [ -f "$conf" ] && grep -q "^[[:space:]]*rpz:" "$conf" 2>/dev/null; then
|
|
echo "$conf"
|
|
return 0
|
|
fi
|
|
done
|
|
|
|
# Se existe local.conf, usar ele
|
|
if [ -f "$UNBOUND_CONF_DIR/local.conf" ]; then
|
|
echo "$UNBOUND_CONF_DIR/local.conf"
|
|
return 0
|
|
fi
|
|
fi
|
|
|
|
# Verificar arquivo principal
|
|
if [ -f "$UNBOUND_MAIN_CONF" ]; then
|
|
# Verificar se tem bloco RPZ
|
|
if grep -q "^[[:space:]]*rpz:" "$UNBOUND_MAIN_CONF" 2>/dev/null; then
|
|
echo "$UNBOUND_MAIN_CONF"
|
|
return 0
|
|
fi
|
|
# Mesmo sem RPZ, usar o principal
|
|
echo "$UNBOUND_MAIN_CONF"
|
|
return 0
|
|
fi
|
|
|
|
# Nenhum arquivo encontrado
|
|
return 1
|
|
}
|
|
|
|
# Verificar se o include do DNSBlock já existe
|
|
verificar_include_existente() {
|
|
local include_pattern='include:[[:space:]]*"/opt/dnsblock/unbound.conf"'
|
|
|
|
# Verificar no arquivo principal
|
|
if [ -f "$UNBOUND_MAIN_CONF" ] && grep -qE "$include_pattern" "$UNBOUND_MAIN_CONF" 2>/dev/null; then
|
|
return 0
|
|
fi
|
|
|
|
# Verificar nos arquivos do diretório conf.d
|
|
if [ -d "$UNBOUND_CONF_DIR" ]; then
|
|
for conf in "$UNBOUND_CONF_DIR"/*.conf; do
|
|
if [ -f "$conf" ] && grep -qE "$include_pattern" "$conf" 2>/dev/null; then
|
|
return 0
|
|
fi
|
|
done
|
|
fi
|
|
|
|
return 1
|
|
}
|
|
|
|
# Configurar o Unbound para usar o DNSBlock
|
|
configurar_unbound() {
|
|
UNBOUND_ERROR=""
|
|
|
|
# Criar o diretório RPZ
|
|
mkdir -p "$RPZ_DIR"
|
|
chown unbound:unbound "$RPZ_DIR"
|
|
|
|
# Copiar arquivo de configuração do DNSBlock para o Unbound (já vem no pacote)
|
|
if [ -f "$SCRIPT_DIR/unbound.conf" ]; then
|
|
cp "$SCRIPT_DIR/unbound.conf" "$DNSBLOCK_UNBOUND_CONF"
|
|
chown unbound:unbound "$DNSBLOCK_UNBOUND_CONF"
|
|
chmod 644 "$DNSBLOCK_UNBOUND_CONF"
|
|
fi
|
|
|
|
# Criar arquivo RPZ vazio se não existir
|
|
local rpz_file="$RPZ_DIR/rpz.dnsblock.zone"
|
|
if [ ! -f "$rpz_file" ]; then
|
|
cat > "$rpz_file" << 'EOF'
|
|
$TTL 1H
|
|
@ SOA localhost. hostmaster.localhost. (
|
|
1 ; Serial
|
|
1h ; Refresh
|
|
15m ; Retry
|
|
30d ; Expire
|
|
2h ; Negative Cache TTL
|
|
)
|
|
NS localhost.
|
|
; RPZ block hosts
|
|
EOF
|
|
chown unbound:unbound "$rpz_file"
|
|
chmod 644 "$rpz_file"
|
|
fi
|
|
|
|
# Verificar se o include já existe
|
|
if verificar_include_existente; then
|
|
# Já configurado, apenas verificar e reiniciar
|
|
if unbound-checkconf 2>&1; then
|
|
systemctl restart unbound 2>/dev/null || true
|
|
return 0
|
|
else
|
|
UNBOUND_ERROR="Configuração do Unbound com erros. Verifique manualmente."
|
|
return 1
|
|
fi
|
|
fi
|
|
|
|
# Encontrar arquivo de configuração do Unbound
|
|
local config_file
|
|
config_file=$(encontrar_arquivo_config_unbound)
|
|
|
|
if [ -z "$config_file" ]; then
|
|
UNBOUND_ERROR="Não foi possível encontrar arquivo de configuração do Unbound."
|
|
return 1
|
|
fi
|
|
|
|
# Fazer backup do arquivo
|
|
cp "$config_file" "${config_file}.bak.dnsblock"
|
|
|
|
# Verificar se existe bloco RPZ no arquivo
|
|
if grep -q "^[[:space:]]*rpz:" "$config_file" 2>/dev/null; then
|
|
# Existe bloco RPZ - adicionar include ANTES do primeiro bloco rpz
|
|
# Usando awk para inserir antes da primeira ocorrência de rpz:
|
|
awk -v include="# DNSBlock\n$DNSBLOCK_INCLUDE\n" '
|
|
/^[[:space:]]*rpz:/ && !inserted {
|
|
print "# DNSBlock"
|
|
print "include: \"/opt/dnsblock/unbound.conf\""
|
|
print ""
|
|
inserted=1
|
|
}
|
|
{print}
|
|
' "$config_file" > "${config_file}.tmp" && mv "${config_file}.tmp" "$config_file"
|
|
else
|
|
# Não existe bloco RPZ - adicionar include no final do arquivo
|
|
echo "" >> "$config_file"
|
|
echo "# DNSBlock" >> "$config_file"
|
|
echo "$DNSBLOCK_INCLUDE" >> "$config_file"
|
|
fi
|
|
|
|
# Verificar configuração do Unbound
|
|
local check_output
|
|
check_output=$(unbound-checkconf 2>&1)
|
|
|
|
if [ $? -ne 0 ]; then
|
|
# Erro na configuração - restaurar backup
|
|
mv "${config_file}.bak.dnsblock" "$config_file"
|
|
UNBOUND_ERROR="Erro na configuração do Unbound:\n$check_output"
|
|
return 1
|
|
fi
|
|
|
|
# Remover backup
|
|
rm -f "${config_file}.bak.dnsblock"
|
|
|
|
# Reiniciar o Unbound
|
|
if ! systemctl restart unbound 2>&1; then
|
|
UNBOUND_ERROR="Falha ao reiniciar o Unbound. Verifique o serviço manualmente."
|
|
return 1
|
|
fi
|
|
|
|
return 0
|
|
}
|
|
|
|
# Remover o include do DNSBlock dos arquivos de configuração
|
|
remover_include_unbound() {
|
|
# Remover do arquivo principal
|
|
if [ -f "$UNBOUND_MAIN_CONF" ]; then
|
|
# Criar arquivo temporário sem as linhas do DNSBlock
|
|
grep -v '/opt/dnsblock' "$UNBOUND_MAIN_CONF" | grep -v '^# DNSBlock' > "${UNBOUND_MAIN_CONF}.tmp" 2>/dev/null
|
|
if [ -s "${UNBOUND_MAIN_CONF}.tmp" ]; then
|
|
mv "${UNBOUND_MAIN_CONF}.tmp" "$UNBOUND_MAIN_CONF"
|
|
else
|
|
rm -f "${UNBOUND_MAIN_CONF}.tmp"
|
|
fi
|
|
fi
|
|
|
|
# Remover dos arquivos do diretório conf.d
|
|
if [ -d "$UNBOUND_CONF_DIR" ]; then
|
|
for conf in "$UNBOUND_CONF_DIR"/*.conf; do
|
|
if [ -f "$conf" ]; then
|
|
# Criar arquivo temporário sem as linhas do DNSBlock
|
|
grep -v '/opt/dnsblock' "$conf" | grep -v '^# DNSBlock' > "${conf}.tmp" 2>/dev/null
|
|
if [ -s "${conf}.tmp" ]; then
|
|
mv "${conf}.tmp" "$conf"
|
|
else
|
|
rm -f "${conf}.tmp"
|
|
fi
|
|
fi
|
|
done
|
|
fi
|
|
}
|
|
|
|
# Remover configuração do Unbound
|
|
remover_configuracao_unbound() {
|
|
# Remover include dos arquivos de configuração
|
|
remover_include_unbound
|
|
|
|
# Verificar se a configuração está OK e reiniciar
|
|
if unbound-checkconf &>/dev/null; then
|
|
systemctl restart unbound 2>/dev/null || true
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# FUNÇÃO DE INSTALAÇÃO
|
|
# ============================================================================
|
|
|
|
instalar() {
|
|
# Verificar dependências
|
|
verificar_dependencias
|
|
|
|
# Verificar se já está instalado
|
|
if [ -d "$INSTALL_DIR" ]; then
|
|
if ! whiptail --title "DNSBlock já instalado" \
|
|
--yesno "O DNSBlock Agent já está instalado.\n\nDeseja reinstalar?" 10 50; then
|
|
exit 0
|
|
fi
|
|
|
|
# Parar serviço se estiver rodando
|
|
systemctl stop dnsblock-agent 2>/dev/null || true
|
|
systemctl disable dnsblock-agent 2>/dev/null || true
|
|
rm -rf "$INSTALL_DIR"
|
|
rm -f "$SERVICE_FILE"
|
|
fi
|
|
|
|
# Exibir progresso - Fase 1: Criar diretórios e copiar arquivos
|
|
{
|
|
echo "5"; echo "# Criando diretórios..."
|
|
mkdir -p "$INSTALL_DIR"
|
|
mkdir -p "$INSTALL_DIR/logs"
|
|
mkdir -p "$INSTALL_DIR/rpz"
|
|
sleep 0.2
|
|
|
|
echo "15"; echo "# Copiando binário..."
|
|
if [ -f "$SCRIPT_DIR/dnsblock-agent" ]; then
|
|
cp "$SCRIPT_DIR/dnsblock-agent" "$INSTALL_DIR/"
|
|
chmod +x "$INSTALL_DIR/dnsblock-agent"
|
|
else
|
|
echo "ERRO: dnsblock-agent não encontrado!" >&2
|
|
exit 1
|
|
fi
|
|
sleep 0.2
|
|
|
|
echo "25"; echo "# Criando config.json..."
|
|
if [ -f "$SCRIPT_DIR/config.json.example" ]; then
|
|
cp "$SCRIPT_DIR/config.json.example" "$INSTALL_DIR/config.json"
|
|
else
|
|
echo "ERRO: config.json.example não encontrado!" >&2
|
|
exit 1
|
|
fi
|
|
sleep 0.2
|
|
|
|
echo "30"; echo "# Copiando configuração do Unbound..."
|
|
if [ -f "$SCRIPT_DIR/unbound.conf" ]; then
|
|
cp "$SCRIPT_DIR/unbound.conf" "$INSTALL_DIR/"
|
|
fi
|
|
sleep 0.2
|
|
|
|
echo "35"; echo "# Configurando permissões..."
|
|
touch "$INSTALL_DIR/logs/agent.log"
|
|
chown -R unbound:unbound "$INSTALL_DIR"
|
|
chmod 755 "$INSTALL_DIR"
|
|
sleep 0.2
|
|
|
|
echo "40"
|
|
} | whiptail --title "DNSBlock Agent - Instalação" --gauge "Preparando arquivos..." 8 60 0
|
|
|
|
# Solicitar serial (fora do gauge para funcionar corretamente)
|
|
solicitar_serial
|
|
|
|
# Exibir progresso - Fase 2: Configurar serial e serviço
|
|
{
|
|
echo "45"; echo "# Configurando serial..."
|
|
if [ -n "$SERIAL" ]; then
|
|
atualizar_config_serial "$SERIAL"
|
|
fi
|
|
sleep 0.2
|
|
|
|
echo "55"; echo "# Instalando serviço systemd..."
|
|
if [ -f "$SCRIPT_DIR/dnsblock-agent.service" ]; then
|
|
cp "$SCRIPT_DIR/dnsblock-agent.service" "$SERVICE_FILE"
|
|
else
|
|
echo "ERRO: dnsblock-agent.service não encontrado!" >&2
|
|
exit 1
|
|
fi
|
|
sleep 0.2
|
|
|
|
echo "65"; echo "# Habilitando serviço..."
|
|
systemctl daemon-reload
|
|
systemctl enable dnsblock-agent 2>/dev/null || true
|
|
sleep 0.2
|
|
|
|
echo "75"; echo "# Configurando Unbound..."
|
|
configurar_unbound || true
|
|
sleep 0.2
|
|
|
|
echo "90"; echo "# Finalizando..."
|
|
if [ -n "$SERIAL" ]; then
|
|
systemctl start dnsblock-agent 2>/dev/null || true
|
|
fi
|
|
sleep 0.2
|
|
|
|
echo "100"
|
|
} | whiptail --title "DNSBlock Agent - Instalação" --gauge "Configurando sistema..." 8 60 45
|
|
|
|
# Verificar se houve erro no Unbound
|
|
if [ -n "$UNBOUND_ERROR" ]; then
|
|
whiptail --title "Aviso - Configuração do Unbound" \
|
|
--msgbox "Houve um problema ao configurar o Unbound:\n\n$UNBOUND_ERROR\n\nO agente foi instalado, mas você precisará configurar o Unbound manualmente." 14 65
|
|
fi
|
|
|
|
# Exibir mensagem final
|
|
if [ -n "$SERIAL" ]; then
|
|
whiptail --title "Instalação Concluída" \
|
|
--msgbox "O DNSBlock Agent foi instalado e iniciado com sucesso!\n\nComandos úteis:\n • Status: systemctl status dnsblock-agent\n • Logs: journalctl -u dnsblock-agent -f\n • Reiniciar: systemctl restart dnsblock-agent" 14 60
|
|
else
|
|
whiptail --title "Instalação Concluída (sem serial)" \
|
|
--msgbox "O DNSBlock Agent foi instalado mas NÃO foi iniciado.\n\nPara ativar o agente:\n\n1. Obtenha seu serial em:\n http://painel.dnsblock.com.br\n\n2. Edite o arquivo:\n $INSTALL_DIR/config.json\n\n3. Inicie o serviço:\n systemctl start dnsblock-agent" 18 60
|
|
fi
|
|
}
|
|
|
|
# ============================================================================
|
|
# FUNÇÃO DE DESINSTALAÇÃO
|
|
# ============================================================================
|
|
|
|
desinstalar() {
|
|
if [ ! -d "$INSTALL_DIR" ] && [ ! -f "$SERVICE_FILE" ]; then
|
|
whiptail --title "Não Instalado" \
|
|
--msgbox "O DNSBlock Agent não parece estar instalado." 8 50
|
|
exit 0
|
|
fi
|
|
|
|
if ! whiptail --title "Confirmar Desinstalação" \
|
|
--yesno "Você está prestes a desinstalar o DNSBlock Agent.\n\nTodos os arquivos e configurações serão removidos.\n\nDeseja continuar?" 12 55; then
|
|
exit 0
|
|
fi
|
|
|
|
# Exibir progresso
|
|
{
|
|
echo "10"; echo "# Parando serviço..."
|
|
systemctl stop dnsblock-agent 2>/dev/null || true
|
|
sleep 0.3
|
|
|
|
echo "30"; echo "# Desabilitando serviço..."
|
|
systemctl disable dnsblock-agent 2>/dev/null || true
|
|
sleep 0.3
|
|
|
|
echo "50"; echo "# Removendo arquivo de serviço..."
|
|
rm -f "$SERVICE_FILE"
|
|
systemctl daemon-reload
|
|
sleep 0.3
|
|
|
|
echo "70"; echo "# Removendo configuração do Unbound..."
|
|
remover_configuracao_unbound
|
|
sleep 0.3
|
|
|
|
echo "90"; echo "# Removendo arquivos..."
|
|
rm -rf "$INSTALL_DIR"
|
|
sleep 0.3
|
|
|
|
echo "100"
|
|
} | whiptail --title "DNSBlock Agent - Desinstalação" --gauge "Removendo DNSBlock Agent..." 8 60 0
|
|
|
|
whiptail --title "Desinstalação Concluída" \
|
|
--msgbox "O DNSBlock Agent foi completamente removido do sistema." 8 55
|
|
}
|
|
|
|
# ============================================================================
|
|
# MENU PRINCIPAL
|
|
# ============================================================================
|
|
|
|
menu_principal() {
|
|
local opcao
|
|
|
|
opcao=$(whiptail --title "DNSBlock Agent" \
|
|
--menu "Selecione uma opção:" 15 60 4 \
|
|
"1" "Instalar DNSBlock Agent" \
|
|
"2" "Desinstalar DNSBlock Agent" \
|
|
"3" "Sair" \
|
|
3>&1 1>&2 2>&3)
|
|
|
|
local status=$?
|
|
|
|
if [ $status -ne 0 ] || [ "$opcao" = "3" ]; then
|
|
exit 0
|
|
fi
|
|
|
|
case "$opcao" in
|
|
1) instalar ;;
|
|
2) desinstalar ;;
|
|
esac
|
|
}
|
|
|
|
# ============================================================================
|
|
# INÍCIO DO SCRIPT
|
|
# ============================================================================
|
|
|
|
# Verificar root
|
|
verificar_root
|
|
|
|
# Processar argumentos
|
|
case "${1:-}" in
|
|
install)
|
|
instalar
|
|
;;
|
|
uninstall|remove)
|
|
desinstalar
|
|
;;
|
|
--help|-h)
|
|
echo ""
|
|
echo "DNSBlock Agent - Script de Instalação"
|
|
echo ""
|
|
echo "Uso: $0 [install|uninstall]"
|
|
echo ""
|
|
echo "Opções:"
|
|
echo " install Instalar o DNSBlock Agent"
|
|
echo " uninstall Desinstalar o DNSBlock Agent"
|
|
echo " --help Exibir esta mensagem"
|
|
echo ""
|
|
echo "Se executado sem argumentos, exibe o menu interativo."
|
|
echo ""
|
|
;;
|
|
"")
|
|
menu_principal
|
|
;;
|
|
*)
|
|
echo "Opção inválida: $1"
|
|
echo "Use --help para ver as opções disponíveis."
|
|
exit 1
|
|
;;
|
|
esac
|