0799bfbae8
Sanitized version of red team infrastructure automation platform. Operational content (implant pipelines, lures, credential capture) replaced with documented stubs. Architecture and infrastructure automation code intact.
190 lines
7.1 KiB
YAML
Executable File
190 lines
7.1 KiB
YAML
Executable File
---
|
|
# Linode Redirector-only Deployment Playbook
|
|
|
|
- name: Deploy Linode redirector
|
|
hosts: localhost
|
|
gather_facts: false
|
|
connection: local
|
|
vars_files:
|
|
- vars.yaml
|
|
vars:
|
|
# Use constant values directly to avoid recursive template resolution
|
|
redirector_image_static: "linode/debian12"
|
|
|
|
tasks:
|
|
- name: Validate required Linode token
|
|
assert:
|
|
that:
|
|
- linode_token is defined and linode_token != ""
|
|
fail_msg: "Linode API token is required. Set linode_token in vars.yaml or via --linode-token."
|
|
|
|
# Update the region selection logic in Linode/redirector.yml
|
|
- name: Set region for redirector
|
|
set_fact:
|
|
deployment_region: "{{ selected_region | default(linode_region, true) | default('us-east', true) }}"
|
|
|
|
- name: Display region selection for redirector
|
|
debug:
|
|
msg: "Using region for redirector: {{ deployment_region }}"
|
|
when: debug | default(false) | bool
|
|
|
|
# Only use random region as a last resort
|
|
- name: Set random region only if no region specified
|
|
set_fact:
|
|
deployment_region: "{{ region_choices | random }}"
|
|
when: region_choices is defined and region_choices|length > 0 and not selected_region is defined and not linode_region is defined and not deployment_region is defined
|
|
|
|
- name: Create redirector Linode instance
|
|
block:
|
|
- name: Try creating instance in specified region
|
|
community.general.linode_v4:
|
|
access_token: "{{ linode_token }}"
|
|
label: "{{ redirector_name }}"
|
|
type: "{{ redirector_plan | default('g6-nanode-1') }}"
|
|
region: "{{ deployment_region }}"
|
|
image: "linode/debian12"
|
|
root_pass: "{{ lookup('password', '/dev/null length=16') }}"
|
|
authorized_keys:
|
|
- "{{ lookup('file', ssh_key_path) }}"
|
|
state: present
|
|
register: redirector_instance
|
|
rescue:
|
|
- name: Log region restriction error
|
|
debug:
|
|
msg: "Region {{ deployment_region }} is restricted. Trying fallback regions..."
|
|
|
|
- name: Set fallback regions (most reliable ones first)
|
|
set_fact:
|
|
fallback_regions:
|
|
- "us-east"
|
|
- "us-central"
|
|
- "eu-west"
|
|
- "us-west"
|
|
|
|
- name: Try fallback regions
|
|
community.general.linode_v4:
|
|
access_token: "{{ linode_token }}"
|
|
label: "{{ redirector_name }}"
|
|
type: "{{ redirector_plan | default('g6-nanode-1') }}"
|
|
region: "{{ item }}"
|
|
image: "linode/debian12"
|
|
root_pass: "{{ lookup('password', '/dev/null length=16') }}"
|
|
authorized_keys:
|
|
- "{{ lookup('file', ssh_key_path) }}"
|
|
state: present
|
|
register: redirector_instance
|
|
loop: "{{ fallback_regions }}"
|
|
when: redirector_instance is not defined or redirector_instance.failed
|
|
ignore_errors: yes
|
|
|
|
- name: Update deployment region with successful fallback
|
|
set_fact:
|
|
deployment_region: "{{ item }}"
|
|
loop: "{{ fallback_regions }}"
|
|
when: redirector_instance.results is defined and redirector_instance.results[ansible_loop.index0] is defined and not redirector_instance.results[ansible_loop.index0].failed
|
|
|
|
- name: Fail if all regions are restricted
|
|
fail:
|
|
msg: "All attempted regions are restricted. Please try again later or contact Linode support."
|
|
when: redirector_instance.failed | default(true)
|
|
|
|
- name: Set redirector_ip for later use
|
|
block:
|
|
- name: Extract instance info from direct creation
|
|
set_fact:
|
|
redirector_ip: "{{ redirector_instance.instance.ipv4[0] }}"
|
|
redirector_instance_id: "{{ redirector_instance.instance.id }}"
|
|
when: redirector_instance.instance is defined
|
|
|
|
- name: Extract instance info from fallback creation
|
|
set_fact:
|
|
redirector_ip: "{{ item.instance.ipv4[0] }}"
|
|
redirector_instance_id: "{{ item.instance.id }}"
|
|
loop: "{{ redirector_instance.results | default([]) }}"
|
|
when: redirector_instance.results is defined and item.instance is defined and not item.failed
|
|
|
|
- name: Display final deployment region and IP
|
|
debug:
|
|
msg: "Redirector deployed successfully in region {{ deployment_region }} with IP {{ redirector_ip }}"
|
|
|
|
# Enhanced SSH wait task with better retry mechanism
|
|
- name: Wait for redirector SSH to be available
|
|
block:
|
|
- name: Initial wait for port to be open
|
|
wait_for:
|
|
host: "{{ redirector_instance.instance.ipv4[0] }}"
|
|
port: 22
|
|
delay: 60
|
|
timeout: 180
|
|
state: started
|
|
|
|
- name: Additional pause for SSH initialization
|
|
pause:
|
|
seconds: 60
|
|
|
|
- name: Test SSH connection
|
|
command: >
|
|
ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ConnectTimeout=10
|
|
-i {{ ssh_key_path | replace('.pub', '') }} root@{{ redirector_instance.instance.ipv4[0] }} echo "SSH Ready"
|
|
register: ssh_test
|
|
retries: 5
|
|
delay: 20
|
|
until: ssh_test.rc == 0
|
|
ignore_errors: yes
|
|
|
|
- name: Fail if SSH test unsuccessful
|
|
fail:
|
|
msg: "Could not connect to redirector via SSH after multiple attempts"
|
|
when: ssh_test.rc != 0
|
|
|
|
- name: Add redirector to inventory
|
|
add_host:
|
|
name: "redirector"
|
|
groups: "redirectors"
|
|
ansible_host: "{{ redirector_ip }}"
|
|
ansible_user: "root"
|
|
ansible_ssh_private_key_file: "{{ ssh_key_path | replace('.pub', '') }}"
|
|
ansible_ssh_common_args: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
|
|
|
|
- name: Configure redirector server
|
|
hosts: redirectors
|
|
become: true
|
|
gather_facts: true
|
|
vars_files:
|
|
- vars.yaml
|
|
vars:
|
|
c2_ip: "{{ hostvars['localhost']['c2_ip'] | default('127.0.0.1') }}"
|
|
redirector_subdomain: "{{ redirector_subdomain | default('cdn') }}"
|
|
ansible_python_interpreter: auto # Explicitly add this line
|
|
tasks:
|
|
- name: Wait for apt to be available
|
|
apt:
|
|
update_cache: yes
|
|
register: apt_result
|
|
until: apt_result is success
|
|
retries: 5
|
|
delay: 10
|
|
|
|
- name: Disable root password authentication for SSH immediately
|
|
lineinfile:
|
|
path: /etc/ssh/sshd_config
|
|
regexp: '^#?PasswordAuthentication'
|
|
line: 'PasswordAuthentication no'
|
|
state: present
|
|
|
|
- name: Restart SSH service to apply changes
|
|
service:
|
|
name: ssh
|
|
state: restarted
|
|
|
|
- name: Include common redirector configuration tasks
|
|
include_tasks: "../../modules/redirectors/tasks/configure_redirector.yml"
|
|
|
|
- name: Print deployment summary
|
|
debug:
|
|
msg:
|
|
- "Redirector Deployment Complete!"
|
|
- "-------------------------------"
|
|
- "Redirector IP: {{ ansible_host }}"
|
|
- "Redirector Domain: {{ redirector_subdomain }}.{{ domain }} (Update DNS A record)"
|
|
when: not disable_summary | default(false) |