#!/bin/bash
##################################
# NXFILTER - OPENFW UTM
##################################

NXSET="/var/efw/nxfilter/settings"
NXBIN="/var/nxfilter/bin"
NXRUN="/var/run/nxfilter.pid"
DOH_LIST="/var/efw/nxfilter/servers-doh"
STARTLOCAL="/var/efw/inithooks/start.local"
RCFW="/var/efw/inithooks/rc.firewall.local"
PORT_APACHE=85
PORT_DNSMASQ=54

log() { echo -e "\e[1;32m[ NXFilter ] $*\e[0m"; }
fail() { echo -e "\e[1;31m[ NXFilter ] $*\e[0m"; exit 1; }

set -a
. "$NXSET"
set +a

: "${NXFILTER_ENABLE:?NXFILTER_ENABLE not set}"
: "${DROP_DOH:?DROP_DOH not set}"

enabled="$NXFILTER_ENABLE"
drop_doh="$DROP_DOH"

#Checa estatus dos serviços para mudar ou não as confs
nxfilter_is_up() {
    /var/nxfilter/bin/ping.sh 2>/dev/null | grep -q "Still working"
}

get_apache_listening() {
    netstat -lnt 2>/dev/null | \
    awk -v port="$PORT_APACHE" '$6=="LISTEN" && $4 ~ ":"port"$" {found=1} END {exit !found}'
}

get_dnsmasq_listening() {
    netstat -lnt 2>/dev/null | \
    awk -v port="$PORT_DNSMASQ" '$6=="LISTEN" && $4 ~ ":"port"$" {found=1} END {exit !found}'
}

get_wpad_port() {
    grep -q 'option wpad "http://.*:'$PORT_APACHE'/proxy\.pac"' /etc/dhcpd.conf.tmpl 2>/dev/null
}


#########################################
# Apache Port Handling
#########################################
set_apache_port() {

    # NXFilter ativo e saudável
    if [ "$enabled" = "on" ]; then

        # Apache já está corretamente na porta 85
        if get_apache_listening; then
            log "Apache already listening on port $PORT_APACHE — no restart needed"
            return
        fi

        log "Configuring Apache for NXFilter (port 85)"

        cat /etc/nxfilter/tmpl/nx-httpd.conf.tmpl \
            > /etc/httpd/sites-available/000-default.conf.tmpl
            /etc/httpd/sites-available/000-default.conf

        cat /etc/nxfilter/tmpl/nx-ports.conf.tmpl \
            > /etc/httpd/ports.conf.tmpl

        /usr/local/bin/restarthttpd --force
    else

        # NXFilter desativado OU não saudável → restaura padrão
        log "Restoring Apache default configuration"

        cat /etc/nxfilter/tmpl/default-httpd.conf.tmpl \
            > /etc/httpd/sites-available/000-default.conf.tmpl

        cat /etc/nxfilter/tmpl/default-ports.conf.tmpl \
            > /etc/httpd/ports.conf.tmpl

        /usr/local/bin/restarthttpd --force

    fi
}



#########################################
# WPAD
#########################################
set_wpad() {

    # NXFilter ativo e saudável
    if [ "$enabled" = "on" ]; then

        # WPAD já configurado para porta 85
        if get_wpad_port; then
            log "WPAD already configured on port 85 — no DHCP restart needed"
            return
        fi

        log "Configuring WPAD for NXFilter (port 85)"

        cat /etc/nxfilter/tmpl/nx-dhcpd.conf.tmpl \
            > /etc/dhcpd.conf.tmpl

        /usr/local/bin/restartdhcp --force
    else

        # NXFilter desativado ou não saudável → restaura padrão
        log "Restoring default WPAD configuration"

        cat /etc/nxfilter/tmpl/default-dhcpd.conf.tmpl \
            > /etc/dhcpd.conf.tmpl

        /usr/local/bin/restartdhcp --force
    fi
}


#########################################
# DNS & dnsmasq
#########################################
set_dns_redirect() {

    # Caso ideal: tudo certo, não faz nada
    if [ "$enabled" = "on" ]; then

        # DNSmasq já está na porta 54
        if get_dnsmasq_listening; then
            log "DNSMasq already listening on port 54 — no restart needed"
            return
        fi

        mkdir -p /etc/dnsmasq/dnsmasq.d
        echo "port=54" > /etc/dnsmasq/dnsmasq.d/nxfilter.conf
        /usr/local/bin/restartdnsmasq --force

        log "Updating dnsmasq port 54!"
    else

        mkdir -p /etc/dnsmasq/dnsmasq.d
        rm -rf /etc/dnsmasq/dnsmasq.d/nxfilter.conf
        /usr/local/bin/restartdnsmasq --force

        log "Updating dnsmasq port default 53!"
    fi

}

#########################################
# INPUT Firewall
#########################################
set_input_firewall() {

    # Caso ideal: tudo certo, não faz nada
    if [ "$enabled" = "on" ]; then

        cp /etc/nxfilter/tmpl/nx-firewall.conf \
           /etc/firewall/inputfw/nxfilter.conf
        /usr/local/bin/setxtaccess

        log "Updating Inputfw Rules!"
    else

        rm -rf /etc/firewall/inputfw/nxfilter.conf
        /usr/local/bin/setxtaccess

        log "Updating Inputfw Rules!"
    fi

}

#########################################
# DoH Firewall
#########################################
enable_nxfilter_doh() {

    IPT="iptables -w 5"

    # Cria chain se não existir
    $IPT -S DOH_DROP >/dev/null 2>&1 || $IPT -N DOH_DROP

    # Limpa regras
    $IPT -F DOH_DROP

    # Garante hook no CUSTOMFORWARD
    $IPT -C CUSTOMFORWARD -j DOH_DROP >/dev/null 2>&1 || \
        $IPT -I CUSTOMFORWARD -j DOH_DROP

    ########################################################
    # Permite NXFilter local
    ########################################################
    $IPT -A DOH_DROP -d 127.0.0.1 -p udp --dport 53 -j RETURN
    $IPT -A DOH_DROP -d 127.0.0.1 -p tcp --dport 53 -j RETURN

    ########################################################
    # DoT (853)
    ########################################################
    $IPT -A DOH_DROP -p tcp --dport 853 -j NFLOG --nflog-prefix "NXFILTER_DOH:REJECT "
    $IPT -A DOH_DROP -p tcp --dport 853 -j REJECT

    $IPT -A DOH_DROP -p udp --dport 853 -j NFLOG --nflog-prefix "NXFILTER_DOH:REJECT "
    $IPT -A DOH_DROP -p udp --dport 853 -j REJECT

    ########################################################
    # DoH 443 por lista
    ########################################################
    if [ -f "$DOH_LIST" ]; then
        while read ip; do
            [ -z "$ip" ] && continue

            $IPT -A DOH_DROP -d "$ip" -p tcp --dport 443 \
                -j NFLOG --nflog-prefix "NXFILTER_DOH:REJECT "

            $IPT -A DOH_DROP -d "$ip" -p tcp --dport 443 -j REJECT
        done < "$DOH_LIST"
    fi

    log "DoH / DoT blocking with NFLOG enabled"
}


disable_nxfilter_doh() {

    # Remove jump do CUSTOMFORWARD se existir
    iptables -C CUSTOMFORWARD -j DOH_DROP >/dev/null 2>&1 && iptables -D CUSTOMFORWARD -j DOH_DROP

    # Limpa regras da chain
    iptables -F DOH_DROP 2>/dev/null || true

    # Deleta a chain se possível
    iptables -X DOH_DROP 2>/dev/null || true

    log "DoH / DoT blocking disabled"
}

#########################################
# NXFilter runtime
#########################################
stop() {
    # Verifica se o processo já está rodando
    if ! pgrep -f 'nxd.Main' >/dev/null 2>&1; then
        log "NXFilter already stopped"
        rm -f "$NXRUN" 2>/dev/null || true
        return
    fi

    # Para o NXFilter
    JAVA_TOOL_OPTIONS= $NXBIN/shutdown.sh -d 2>&1 | grep -v "Picked up JAVA_TOOL_OPTIONS" || true
    sleep 5

    # Remove PID file se existir
    rm -f "$NXRUN" 2>/dev/null || true
    log "NXFilter stopped"
}

start() {
    log "Starting NXFilter..."

    # Inicia o NXFilter em background
    env -u JAVA_TOOL_OPTIONS $NXBIN/startup.sh -d 2>&1 | \
        grep -v "Picked up JAVA_TOOL_OPTIONS"

    # Aguarda NXFilter responder ao ping.sh
    for i in $(seq 1 30); do
        sleep 1
        if nxfilter_is_up; then
            break
        fi
    done

    # Validação final
    if ! nxfilter_is_up; then
        fail "NXFilter did not respond. (service not UP)"
    fi

    # Busca PID real do Java
    pid=$(pgrep -f 'nxd.Main')
    [ -n "$pid" ] || fail "NXFilter process not found"

    echo "$pid" > "$NXRUN"
    chown nobody:nogroup "$NXRUN"

    log "NXFilter running (healthcheck OK, PID $pid)"
}



#########################################
# Boot persistence
#########################################
persist_boot() {

#############################
# start.local (boot)
#############################

    if [ ! -f "$STARTLOCAL" ]; then
        echo "#!/bin/bash" > "$STARTLOCAL"
        chmod 755 "$STARTLOCAL"
    fi

    sed -i '/nxfilter/d' "$STARTLOCAL"
    echo "/usr/local/bin/nxfilter --restart" >> "$STARTLOCAL"


#############################
# rc.firewall.local
#############################

    if [ ! -f "$RCFW" ]; then
        cat > "$RCFW" <<'EOF'
#!/bin/bash

start() {
echo
}

stop() {
echo
}

case "$1" in
    start) start ;;
    stop) stop ;;
    reload)
        stop
        start
    ;;
    *)
        echo "Usage: $0 {start|reload|stop}"
        exit 1
    ;;
esac

exit $?
EOF
        chmod 755 "$RCFW"
    fi

    # remove entradas antigas
    sed -i '/nxfilter/d' "$RCFW"
    # chama DoH no start do firewall
    sed -i '/^start()/a\    /usr/local/bin/nxfilter --nxfilter_doh' "$RCFW"
}


remove_boot() {

    # start.local
    [ -f "$STARTLOCAL" ] && sed -i '/nxfilter/d' "$STARTLOCAL"

    # rc.firewall.local
    [ -f "$RCFW" ] && sed -i '/nxfilter/d' "$RCFW"
    rm -rf /etc/firewall/inputfw/nxfilter.conf
    setxtaccess
}


#########################################
# MAIN
#########################################

case "$1" in
    --restart)

        if [ "$enabled" = "on" ]; then
            log "NXFilter enabled"         
            stop
            sleep 3
            set_apache_port
            sleep 3
            set_dns_redirect
            sleep 3
            set_wpad
            sleep 3
            set_input_firewall

            if [ "$drop_doh" = "on" ]; then
                enable_nxfilter_doh
            else
                disable_nxfilter_doh
            fi

            start
            persist_boot

            log "NXFilter fully operational"

        else
            log "NXFilter disabled — restoring system"
            stop
            sleep 3
            set_apache_port
            sleep 3
            set_dns_redirect
            sleep 3
            set_wpad
            sleep 3
            set_input_firewall
            disable_nxfilter_doh
            remove_boot

            log "System restored to default"
        fi
        ;;

     --reload-doh)

            log "Applying DoH firewall rules only (no full restart)"

            # se NXFilter desligado → remove tudo
            if [ "$enabled" != "on" ]; then
                disable_nxfilter_doh
                exit 0
            fi

            # aplica conforme checkbox
            if [ "$drop_doh" = "on" ]; then
                enable_nxfilter_doh
            else
                disable_nxfilter_doh
            fi

            log "DoH rules reload finished"
            ;;
    *)
        echo "Usage: nxfilter --restart"
        ;;
esac
