#!/bin/bash
set -e

###########################
# Install package
###########################
function installPackages(){

    echo "Updating system and installing Keepalived dnsdist nftables..."
    apt update
    apt install -y wget curl nftables irqbalance

    DOWNLOAD_URL=$(curl -s https://api.github.com/repos/pymumu/smartdns/releases/latest | grep browser_download_url | grep "x86_64.deb" | cut -d '"' -f 4)
    if [ -z "$DOWNLOAD_URL" ]; then
        echo "Failed to fetch the SmartDNS download URL. Please check your network or GitHub API status."
        exit 1
    fi

    wget -O /tmp/smartdns.deb "$DOWNLOAD_URL"
    if [ $? -ne 0 ];then
        echo "Download $DOWNLOAD_URL failed."
        exit 1
    fi

    # Install the .deb package
    echo "Installing the SmartDNS .deb package..."
    dpkg -i /tmp/smartdns.deb || apt-get -f install -y

}
function configSmartDns(){
    cat <<EOF > /etc/smartdns/smartdns.conf
bind :53@eth0
# Read the previous cache on restart
cache-persist yes
# Cache file storage location
cache-file /var/cache/smartdns.cache
#Periodically save cache files
cache-checkpoint-time 86400
#TCP Idle Time
tcp-idle-time 120
#Maximum number of IP Num returned to clients
max-reply-ip-num 1
#Max Query Limit
max-query-limit 65535
# log setting
log-level error
log-size 1G
log-num 30
log-file /var/log/smartdns/smartdns.log
#Domain Pre-Fetch function
prefetch-domain yes
# After the TTL expires, TTL=0 will be returned to the client and the results will be requeried and cached.
serve-expired yes
serve-expired-ttl 0
serve-expired-reply-ttl 5
serve-expired-prefetch-time 28800
#Compare v4 and v6 to get the fastest result, the default is yes
dualstack-ip-selection yes
dualstack-ip-selection-threshold 10
#In response to the slow query problem of IOS 14 system, turn off TYPE65 record query
force-qtype-SOA 65
#Speed Test
speed-check-mode ping,tcp:80,tcp:443
response-mode first-ping

# ----- Default Group -----
# Google

server 8.8.8.8
server-tcp 8.8.8.8
server-tls 8.8.8.8
server 8.8.4.4
server-tcp 8.8.4.4
server-tls 8.8.4.4
server 2001:4860:4860::8888
server 2001:4860:4860::8844
server-https https://dns.google/dns-query

#CloudFlare
server 1.1.1.1
server-tcp 1.1.1.1
server-tls 1.1.1.1
server 1.0.0.1
server-tcp 1.0.0.1
server-tls 1.0.0.1
server 2606:4700:4700::1111
server 2606:4700:4700::1001
server-https https://cloudflare-dns.com/dns-query
server-tls https://1.1.1.1/dns-query

EOF

    ## file limit
    sed -i '/^\[Service\]/a LimitNOFILE=1048576' /usr/lib/systemd/system/smartdns.service
    systemctl daemon-reload

    # Start the SmartDNS service
    echo "Starting the SmartDNS service..."
    systemctl enable smartdns
    systemctl restart smartdns

    if [ $? -ne 0 ];then
        echo "Start smartdns service failed."
        exit 1
    fi

}

function configKernelParameter(){
    
    # Update sysctl.conf with optimization parameters
    echo "Applying kernel parameter optimizations..."

    cat <<EOF >> /etc/sysctl.conf

# SmartDNS performance optimization
fs.file-max = 2097152

# TCP performance
net.core.somaxconn = 4096
net.core.netdev_max_backlog = 8192
net.ipv4.tcp_max_syn_backlog = 4096
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_syncookies = 1

# UDP performance
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.core.rmem_default = 262144
net.core.wmem_default = 262144
net.ipv4.udp_rmem_min = 8192
net.ipv4.udp_wmem_min = 8192

# Routing cache
net.ipv4.route.gc_timeout = 100
net.ipv4.route.gc_elasticity = 10

# Memory management
vm.swappiness = 10
vm.dirty_ratio = 20
vm.dirty_background_ratio = 10

# Multi-core optimization
net.core.netdev_budget = 300
net.core.netdev_budget_usecs = 3000

EOF

    # Apply sysctl parameters
    sysctl -p

    # Increase file descriptor limits for SmartDNS
cat <<EOF >> /etc/security/limits.conf
    *               soft    nofile          1048576
    *               hard    nofile          1048576
EOF
    
    

    echo "SmartDNS kernel optimization completed."

}

############################
# config firewall role
# Allow Form: 10.0.0.0/24 
############################
function configFirewallRole(){

    echo "Configuring Firewall..."
    # Flush existing rules
    echo "Flushing existing rules..."
    nft flush ruleset

    # Create the 'firewall' table
    echo "Creating nftables table and chains..."
    nft add table inet firewall

    # Add input chain with default policy 'drop'
    nft add chain inet firewall input { type filter hook input priority 0 \; policy drop \; }

    # Allow loopback traffic
    nft add rule inet firewall input iif "lo" accept

    # Allow established and related connections
    nft add rule inet firewall input ct state established,related accept

    # Allow all traffic from 10.0.0.0/24
    nft add rule inet firewall input ip saddr 10.0.0.0/24 accept

    # Drop all other traffic
    nft add rule inet firewall input drop

    # Add forward chain with default policy 'drop'
    nft add chain inet firewall forward { type filter hook forward priority 0 \; policy drop \; }

    # Add output chain with default policy 'accept'
    nft add chain inet firewall output { type filter hook output priority 0 \; policy accept \; }

    # Save rules to configuration file
    echo "Saving rules to /etc/nftables.conf..."
    nft list ruleset > /etc/nftables.conf

    # Enable and restart nftables service
    echo "Ensuring nftables service is enabled..."
    systemctl enable nftables
    systemctl restart nftables

    echo "nftables configuration completed successfully."
}


echo "Starting installation of the latest stable version of SmartDNS..."

# Ensure the script is run as root
if [ "$(id -u)" -ne 0 ]; then
    echo "Please run this script as root or with sudo."
    exit 1
fi



#1. install package
installPackages

#2. config Smartdns
configSmartDns

#3. config kernel
configKernelParameter

#4. config firewall
configFirewallRole


echo "SmartDNS has been successfully installed and is running on eth0, port 53!"

