#!/usr/bin/env bash set -euo pipefail export DEBIAN_FRONTEND=noninteractive export LC_ALL=C # ======================== НАСТРОЙКИ ========================== SSH_PORT=22 # порт SSH VPN_TCP_PORTS="443" # TCP-порты VPN (через пробел) VPN_UDP_PORTS="443" # UDP-порты VPN (QUIC) NODE_PORT="2345" # порт панели / ноды MY_IP="5.180.253.38" # ВПИШИ СВОЙ IP — crowdsec не забанит SECRET_KEY="eyJub2RlQ2VydFBlbSI6Ii0tLS0tQkVHSU4gQ0VSVElGSUNBVEUtLS0tLVxuTUlJQmhqQ0NBU3lnQXdJQkFnSUhBWGMxSkVaWFZqQUtCZ2dxaGtqT1BRUURBakF2TVMwd0t3WURWUVFERXlSclxuV0Zkb2R6UkJOSGxrVlRSdU1qTmxkelpMTlVGWlVFNUJjbEoyVWxONWRpMHhiVmt3SGhjTk1qWXdNekUwTWpFMFxuTVRBMVdoY05Namt3TXpFME1qRTBNVEExV2pBcU1TZ3dKZ1lEVlFRREV4OUJUR2gyVkZGRGRFRXhjRkpDV2tKeFxuV2sxa1JIRTVORmh1VVhsTFFYZ3pNRmt3RXdZSEtvWkl6ajBDQVFZSUtvWkl6ajBEQVFjRFFnQUVNUG84Uzl5SFxuK0F2TEFXalhVZENGYk4xdWlkY0xOTEZUZ0lwVUdBcFZBR0xQZUJhY0RvUWI5RTNPT3lOUHZxOCtwUTcwR0ozSlxubnlZRUlUKytEWHdGazZNNE1EWXdEQVlEVlIwVEFRSC9CQUl3QURBT0JnTlZIUThCQWY4RUJBTUNCYUF3RmdZRFxuVlIwbEFRSC9CQXd3Q2dZSUt3WUJCUVVIQXdFd0NnWUlLb1pJemowRUF3SURTQUF3UlFJaEFKc2Y1YnVzd3FvU1xuQTlMeTJLaEUxaUU3THlQTGVKOWRYbW9FT01VeThGblJBaUFROXJXMFJmWVJpdk1JMGdBVGprZ2V6TU9IbWpaQlxuZ0xMSkxmaCt4T0hIdnc9PVxuLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLSIsIm5vZGVLZXlQZW0iOiItLS0tLUJFR0lOIFBSSVZBVEUgS0VZLS0tLS1cbk1JR0hBZ0VBTUJNR0J5cUdTTTQ5QWdFR0NDcUdTTTQ5QXdFSEJHMHdhd0lCQVFRZ044VWVreUtQUEZ2YmQzdDBcbnRUODBMSDNVcS9IU1premU2WG5OclFkYXJzU2hSQU5DQUFRdytqeEwzSWY0QzhzQmFOZFIwSVZzM1c2SjF3czBcbnNWT0FpbFFZQ2xVQVlzOTRGcHdPaEJ2MFRjNDdJMCsrcno2bER2UVluY21mSmdRaFA3NE5mQVdUXG4tLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tIiwiY2FDZXJ0UGVtIjoiLS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tXG5NSUlCY1RDQ0FSYWdBd0lCQWdJQkFUQUtCZ2dxaGtqT1BRUURBakF2TVMwd0t3WURWUVFERXlScldGZG9kelJCXG5OSGxrVlRSdU1qTmxkelpMTlVGWlVFNUJjbEoyVWxONWRpMHhiVmt3SGhjTk1qWXdNekEwTVRnd05qTXpXaGNOXG5Nell3TXpBME1UZ3dOak16V2pBdk1TMHdLd1lEVlFRREV5UnJXRmRvZHpSQk5IbGtWVFJ1TWpObGR6WkxOVUZaXG5VRTVCY2xKMlVsTjVkaTB4YlZrd1dUQVRCZ2NxaGtqT1BRSUJCZ2dxaGtqT1BRTUJCd05DQUFUMzVxamh6V1NhXG4vdFJxbDRtQXkwanQ0ZXNEWUo2YkdoMUpoY0pmQisxdWRVV2tBS1dqazBLQVd1WnBNR1ZORjZvblNOVVZ0R1RQXG5GU0NlMTlIVElLOXBveU13SVRBUEJnTlZIUk1CQWY4RUJUQURBUUgvTUE0R0ExVWREd0VCL3dRRUF3SUNoREFLXG5CZ2dxaGtqT1BRUURBZ05KQURCR0FpRUF1QS9UZFVyYlZEVG5ORGJycHJlYm83T0VaNHdpTXVzbVpmWjhqSDFBXG5yWWdDSVFEMHVSSnhPeGNPWnFJRTlXMDJVVHcwcHQwRGJId2U0NWJVc1V6dkhpQ3ZwQT09XG4tLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tIiwiand0UHVibGljS2V5IjoiLS0tLS1CRUdJTiBQVUJMSUMgS0VZLS0tLS1cbk1JSUJJakFOQmdrcWhraUc5dzBCQVFFRkFBT0NBUThBTUlJQkNnS0NBUUVBMVNLY1ZSR282N01yNXdENGJmQVNcbllCOWdRS0ZsdHg3aFh5dXRpaG13c0x4ZW5vN2xNb1VRWEVqclpJdVNJK1FQU1p6aVQ4b0dlSG1sK2psQWI3SHZcblBNbVN6KzdFdHIwRmVDazhtTENIaGpucG1YSk10ZVY1ZndyZkJwcHdLY1hkMFRzWlhrR0dEcVRMSVA5L29hTjhcblN3UW9reW5iUzNjYUN0LzhPSDJUMWI1anpJYlZXNS9NcFUxY1hIL2cxemdmOW10SGsxYkJSeFA0d1ZYdlVhS0NcblZyWldGalVZZUN2N2hoQjhmNzVRVWJBbERHMEMyaHZxV1h1Tm9Cc0NpVmEvS01RZkh5ZUMvTENaUnd5dWxhemxcblNPQ0pEVU5IUUdoOS9QR0trZ3BGVHFKUS9hbVJpZnZUMDVMclFQLzlsMHZkRTRqNjJOUGF1U1R0UmxWL1NqTGhcbkN3SURBUUFCXG4tLS0tLUVORCBQVUJMSUMgS0VZLS0tLS1cbiJ9" # ВПИШИ SECRET_KEY ноды # ============================================================= RED='\033[0;31m'; GREEN='\033[0;32m'; YEL='\033[1;33m'; NC='\033[0m' log() { echo -e "${GREEN}[+]${NC} $*"; } warn() { echo -e "${YEL}[!]${NC} $*"; } [ "$(id -u)" -eq 0 ] || { echo "Run as root"; exit 1; } [ -n "$SECRET_KEY" ] || { echo "Впиши SECRET_KEY вверху скрипта"; exit 1; } # ============================================================ # 1. ОБНОВЛЕНИЕ + ПАКЕТЫ # ============================================================ log "1/15 System update..." apt-get update -y && apt-get upgrade -y apt-get install -y sudo curl wget net-tools socat git jq htop \ chrony ca-certificates irqbalance zram-tools ufw \ unattended-upgrades apt-listchanges # ============================================================ # 2. DOCKER # ============================================================ log "2/15 Installing Docker..." curl -fsSL https://get.docker.com | sh # ============================================================ # 3. REMNANODE # ============================================================ log "3/15 Setting up remnanode..." mkdir -p /opt/remnanode cd /opt/remnanode cat > docker-compose.yml << EOF services: remnanode: container_name: remnanode hostname: remnanode image: remnawave/node:latest network_mode: host restart: always cap_add: - NET_ADMIN volumes: - /var/log/remnanode:/var/log/remnanode ulimits: nofile: soft: 1048576 hard: 1048576 environment: - NODE_PORT=${NODE_PORT} - SECRET_KEY="${SECRET_KEY}" EOF mkdir -p /var/log/remnanode touch /var/log/remnanode/access.log chmod -R 755 /var/log/remnanode docker compose up -d log "remnanode started" # ============================================================ # 4. CHRONY # ============================================================ log "4/15 Chrony..." systemctl disable --now systemd-timesyncd 2>/dev/null || true systemctl enable --now chrony chronyc -a makestep 2>/dev/null || true # ============================================================ # 5. SYSCTL — BBR + ТЮНИНГ ПОД МОБИЛЬНЫЙ VPN # ============================================================ log "5/15 Sysctl (BBR + mobile)..." cat > /etc/sysctl.d/90-vpn-tuning.conf << 'SYSCTL' # BBR net.core.default_qdisc = fq net.ipv4.tcp_congestion_control = bbr # TCP fast open (client + server) net.ipv4.tcp_fastopen = 3 # MTU probing (compensate blocked ICMP on path) net.ipv4.tcp_mtu_probing = 1 # CRITICAL for mobile: dont reset cwnd after idle net.ipv4.tcp_slow_start_after_idle = 0 # Reduce bufferbloat (critical for mobile latency) net.ipv4.tcp_notsent_lowat = 16384 # Keepalive (drop dead mobile connections faster) net.ipv4.tcp_keepalive_time = 300 net.ipv4.tcp_keepalive_intvl = 30 net.ipv4.tcp_keepalive_probes = 5 # Fast socket recycling net.ipv4.tcp_fin_timeout = 15 net.ipv4.tcp_tw_reuse = 1 # TCP stack net.ipv4.tcp_window_scaling = 1 net.ipv4.tcp_timestamps = 1 net.ipv4.tcp_sack = 1 net.ipv4.tcp_ecn = 2 # Buffers (balanced for 1-10 Gbit VPS) net.ipv4.tcp_rmem = 4096 262144 16777216 net.ipv4.tcp_wmem = 4096 262144 16777216 net.core.rmem_max = 16777216 net.core.wmem_max = 16777216 # Backlog / queues net.core.somaxconn = 65535 net.core.netdev_max_backlog = 16384 net.core.netdev_budget = 600 net.core.netdev_budget_usecs = 8000 # SYN flood protection net.ipv4.tcp_syncookies = 1 net.ipv4.tcp_max_syn_backlog = 8192 # OS limits fs.file-max = 2097152 net.ipv4.ip_local_port_range = 10240 65535 SYSCTL sysctl --system 2>&1 | grep -v "^$" || true sysctl net.ipv4.tcp_congestion_control | grep -q bbr && log "BBR active" || warn "BBR unavailable — need kernel 5.4+" # ============================================================ # 6. ЛИМИТЫ ФАЙЛОВЫХ ДЕСКРИПТОРОВ # ============================================================ log "6/15 File descriptor limits..." cat > /etc/security/limits.d/99-nofile.conf << 'FLIM' * soft nofile 1048576 * hard nofile 1048576 root soft nofile 1048576 root hard nofile 1048576 FLIM mkdir -p /etc/systemd/system.conf.d cat > /etc/systemd/system.conf.d/99-limits.conf << 'SLIM' [Manager] DefaultLimitNOFILE=1048576 DefaultTasksMax=infinity SLIM systemctl daemon-reload # ============================================================ # 7. CROWDSEC # ============================================================ log "7/15 CrowdSec..." curl -s https://install.crowdsec.net | sh apt-get install -y crowdsec apt-get install -y crowdsec-firewall-bouncer-iptables cscli console enroll cmmrouhcj000u02jpy3b98fsc if [ -n "$MY_IP" ]; then log " -> Adding ${MY_IP} to CrowdSec whitelist..." mkdir -p /etc/crowdsec/parsers/s02-enrich cat > /etc/crowdsec/parsers/s02-enrich/myip-whitelist.yaml << WHITELIST name: custom/myip-whitelist description: "Whitelist my personal IP" whitelist: reason: "my personal IP" ip: - "${MY_IP}" WHITELIST fi systemctl enable --now crowdsec systemctl restart crowdsec systemctl enable --now crowdsec-firewall-bouncer systemctl restart crowdsec-firewall-bouncer log "CrowdSec active" # ============================================================ # 8. УДАЛЕНИЕ ПОЧТЫ # ============================================================ log "8/15 Remove mail stack..." systemctl disable --now postfix sendmail exim4 nullmailer msmtp 2>/dev/null || true systemctl mask postfix sendmail exim4 nullmailer msmtp 2>/dev/null || true apt-get purge -y postfix sendmail sendmail-bin sendmail-base \ exim4 exim4-base exim4-config exim4-daemon-light exim4-daemon-heavy \ mailutils bsd-mailx s-nail heirloom-mailx msmtp msmtp-mta nullmailer dma ssmtp 2>/dev/null || true apt-get autoremove -y 2>/dev/null || true rm -rf /var/spool/mail/* /var/mail/* /etc/postfix /etc/exim4 2>/dev/null || true if [ -f /etc/crontab ]; then grep -qE '^\s*MAILTO=' /etc/crontab \ && sed -i 's/^\s*MAILTO=.*/MAILTO=""/' /etc/crontab \ || printf '\nMAILTO=""\n' >> /etc/crontab fi # ============================================================ # 9. UFW (единственный файрвол, без ручных iptables) # ============================================================ log "9/15 UFW firewall..." ufw --force reset ufw default deny incoming ufw default allow outgoing # Входящие ufw allow "${SSH_PORT}/tcp" comment 'SSH' for p in $VPN_TCP_PORTS; do ufw allow "${p}/tcp" comment 'VPN-TCP'; done for p in $VPN_UDP_PORTS; do ufw allow "${p}/udp" comment 'VPN-UDP'; done ufw allow "${NODE_PORT}/tcp" comment 'Panel-Node' ufw allow 6060/tcp comment 'CrowdSec' # Блокировка исходящего абьюза (DROP, не REJECT — REGXA-safe) ufw deny out to any port 25 proto tcp comment 'Block-SMTP' ufw deny out to any port 465 proto tcp comment 'Block-SMTPS' ufw deny out to any port 587 proto tcp comment 'Block-Submission' ufw deny out to any port 2525 proto tcp comment 'Block-AltSMTP' ufw deny out to any port 6667 proto tcp comment 'Block-IRC' ufw deny out to any port 6697 proto tcp comment 'Block-IRC-TLS' for tp in 9001 9030 9050 9051 9150; do ufw deny out to any port $tp proto tcp comment 'Block-TOR' done ufw deny out to any port 51413 proto tcp comment 'Block-Torrent' ufw deny out to any port 51413 proto udp comment 'Block-Torrent' # ICMP: разрешаем PMTUD (критично для VPN!), блокируем ping BF="/etc/ufw/before.rules" if ! grep -q "CUSTOM-ICMP-RULES" "$BF" 2>/dev/null; then sed -i '/-A ufw-before-input -p icmp --icmp-type echo-request -j ACCEPT/d' "$BF" sed -i '/^COMMIT/i \ # === CUSTOM-ICMP-RULES ===\ -A ufw-before-input -p icmp --icmp-type destination-unreachable -j ACCEPT\ -A ufw-before-input -p icmp --icmp-type time-exceeded -j ACCEPT\ -A ufw-before-input -p icmp --icmp-type parameter-problem -j ACCEPT\ -A ufw-before-input -p icmp --icmp-type echo-request -j DROP\ # === END CUSTOM-ICMP-RULES ===' "$BF" fi ufw --force enable log "UFW active" # ============================================================ # 10. JOURNALD # ============================================================ log "10/15 Journald..." mkdir -p /etc/systemd/journald.conf.d cat > /etc/systemd/journald.conf.d/override.conf << 'JRNL' [Journal] SystemMaxUse=200M RuntimeMaxUse=200M Compress=yes Storage=auto JRNL systemctl restart systemd-journald # ============================================================ # 11. ZRAM # ============================================================ log "11/15 Zram..." modprobe zram 2>/dev/null || { apt-get install -y "linux-modules-extra-$(uname -r)" 2>/dev/null || true modprobe zram 2>/dev/null || warn "zram unavailable" } cat > /etc/default/zramswap << 'ZRM' ALGO=lz4 PERCENTAGE=50 PRIORITY=100 ZRM systemctl enable --now zramswap 2>/dev/null || true # ============================================================ # 12. IRQBALANCE # ============================================================ log "12/15 Irqbalance..." systemctl enable --now irqbalance # ============================================================ # 13. АВТООБНОВЛЕНИЯ БЕЗОПАСНОСТИ # ============================================================ log "13/15 Security auto-updates..." cat > /etc/apt/apt.conf.d/20auto-upgrades << 'AUTOUP' APT::Periodic::Update-Package-Lists "1"; APT::Periodic::Unattended-Upgrade "1"; APT::Periodic::AutocleanInterval "7"; AUTOUP # ============================================================ # 14. OVERRIDE ДЛЯ XRAY / SING-BOX # ============================================================ log "14/15 Xray/sing-box override..." for SVC in xray xray-core sing-box; do if systemctl list-unit-files 2>/dev/null | grep -q "^${SVC}.service"; then log " -> override for ${SVC}" mkdir -p "/etc/systemd/system/${SVC}.service.d" cat > "/etc/systemd/system/${SVC}.service.d/override.conf" << XOVER [Service] LimitNOFILE=1048576 LimitNPROC=infinity Restart=always RestartSec=3s XOVER systemctl daemon-reload systemctl restart "${SVC}" 2>/dev/null || true fi done # ============================================================ # 15. SSH HARDENING # ============================================================ log "15/15 SSH hardening..." SC="/etc/ssh/sshd_config" [ -s /root/.ssh/authorized_keys ] && \ sed -i 's/^#\?PermitRootLogin.*/PermitRootLogin prohibit-password/' "$SC" sed -i 's/^#\?MaxAuthTries.*/MaxAuthTries 3/' "$SC" sed -i 's/^#\?ClientAliveInterval.*/ClientAliveInterval 120/' "$SC" sed -i 's/^#\?ClientAliveCountMax.*/ClientAliveCountMax 3/' "$SC" systemctl reload sshd 2>/dev/null || systemctl reload ssh 2>/dev/null || true # ============================================================ # ФИНАЛ # ============================================================ echo "" echo "==========================================" echo -e "${GREEN} SETUP COMPLETE${NC}" echo "==========================================" echo "" echo "--- remnanode ---" docker ps | grep remnanode || true echo "" echo "--- BBR ---" sysctl net.ipv4.tcp_congestion_control sysctl net.core.default_qdisc echo "" echo "--- UFW ---" ufw status numbered echo "" echo "--- CrowdSec ---" cscli version 2>/dev/null || true cscli machines list 2>/dev/null || true echo "" echo "--- SMTP check ---" ss -lntp | grep -E ':(25|465|587)\b' || echo " [OK] No SMTP listeners" echo "" echo "--- zram ---" swapon --show 2>/dev/null || true echo "" echo "==========================================" echo -e "${YEL}ПОСЛЕ ЗАПУСКА:${NC}" echo " 1. Подтверди enroll в консоли: https://app.crowdsec.net" echo " 2. reboot" echo "=========================================="