This commit is contained in:
n0mad1k
2025-04-11 12:46:11 -04:00
parent 7962c574de
commit 5d92761405
3 changed files with 58 additions and 20 deletions
+5 -5
View File
@@ -9,10 +9,9 @@
- vars.yaml - vars.yaml
vars: vars:
# Default values for required variables # Default values for required variables
ssh_user: "{{ ssh_user | default('root') }}"
linode_region: "{{ linode_region | default(region_choices | random) }}" linode_region: "{{ linode_region | default(region_choices | random) }}"
plan: "{{ plan | default('g6-standard-1') }}" plan: "{{ plan | default('g6-standard-2') }}"
image: "{{ image | default('linode/debian11') }}" image: "{{ image | default('linode/kali') }}"
# Generate random instance name if not provided # Generate random instance name if not provided
c2_name: "{{ c2_name | default('node-' + 9999999999 | random | to_uuid | hash('md5') | truncate(8, True, '')) }}" c2_name: "{{ c2_name | default('node-' + 9999999999 | random | to_uuid | hash('md5') | truncate(8, True, '')) }}"
@@ -31,7 +30,7 @@
type: "{{ plan }}" type: "{{ plan }}"
region: "{{ linode_region }}" region: "{{ linode_region }}"
image: "{{ image }}" image: "{{ image }}"
root_pass: "{{ lookup('password', '/dev/null length=24 chars=ascii_letters,digits') }}" root_pass: "{{ lookup('password', '/dev/null length=16') }}"
authorized_keys: authorized_keys:
- "{{ lookup('file', ssh_key_path) }}" - "{{ lookup('file', ssh_key_path) }}"
state: present state: present
@@ -72,12 +71,13 @@
msg: "Could not connect to C2 server via SSH after multiple attempts" msg: "Could not connect to C2 server via SSH after multiple attempts"
when: ssh_test.rc != 0 when: ssh_test.rc != 0
# Fix: use hardcoded "root" instead of a nested templating expression
- name: Add C2 to inventory - name: Add C2 to inventory
add_host: add_host:
name: "c2" name: "c2"
groups: "c2servers" groups: "c2servers"
ansible_host: "{{ c2_ip }}" ansible_host: "{{ c2_ip }}"
ansible_user: "root" # Hard-coded instead of using ssh_user ansible_user: "root"
ansible_ssh_private_key_file: "{{ ssh_key_path | replace('.pub', '') }}" ansible_ssh_private_key_file: "{{ ssh_key_path | replace('.pub', '') }}"
ansible_ssh_common_args: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null" ansible_ssh_common_args: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
+10 -11
View File
@@ -9,10 +9,9 @@
- vars.yaml - vars.yaml
vars: vars:
# Default values for required variables # Default values for required variables
ssh_user: "{{ ssh_user | default('root') }}"
linode_region: "{{ linode_region | default(region_choices | random) }}" linode_region: "{{ linode_region | default(region_choices | random) }}"
plan: "{{ plan | default('g6-standard-1') }}" plan: "{{ plan | default('g6-nanode-1') }}"
image: "{{ image | default('linode/debian11') }}" image: "{{ image | default('linode/kali') }}"
# Generate random instance name if not provided # Generate random instance name if not provided
redirector_name: "{{ redirector_name | default('srv-' + 9999999999 | random | to_uuid | hash('md5') | truncate(8, True, '')) }}" redirector_name: "{{ redirector_name | default('srv-' + 9999999999 | random | to_uuid | hash('md5') | truncate(8, True, '')) }}"
@@ -34,7 +33,7 @@
type: "{{ plan }}" type: "{{ plan }}"
region: "{{ linode_region }}" region: "{{ linode_region }}"
image: "{{ image }}" image: "{{ image }}"
root_pass: "{{ lookup('password', '/dev/null length=24 chars=ascii_letters,digits') }}" root_pass: "{{ lookup('password', '/dev/null length=16') }}"
authorized_keys: authorized_keys:
- "{{ lookup('file', ssh_key_path) }}" - "{{ lookup('file', ssh_key_path) }}"
state: present state: present
@@ -45,7 +44,7 @@
redirector_ip: "{{ redirector_instance.instance.ipv4[0] }}" redirector_ip: "{{ redirector_instance.instance.ipv4[0] }}"
redirector_instance_id: "{{ redirector_instance.instance.id }}" redirector_instance_id: "{{ redirector_instance.instance.id }}"
# Enhanced SSH wait task for Linode/redirector.yml # Enhanced SSH wait task with better retry mechanism
- name: Wait for redirector SSH to be available - name: Wait for redirector SSH to be available
block: block:
- name: Initial wait for port to be open - name: Initial wait for port to be open
@@ -75,12 +74,15 @@
msg: "Could not connect to redirector via SSH after multiple attempts" msg: "Could not connect to redirector via SSH after multiple attempts"
when: ssh_test.rc != 0 when: ssh_test.rc != 0
# Fix: Use hardcoded "redirector" for the name and "root" for the user
- name: Add redirector to inventory - name: Add redirector to inventory
add_host: add_host:
name: "{{ redirector_name }}" name: "redirector"
groups: "redirectors"
ansible_host: "{{ redirector_ip }}" ansible_host: "{{ redirector_ip }}"
ansible_user: "root" # Or directly use the user you need ansible_user: "root"
ansible_ssh_private_key_file: "{{ ssh_key_path | replace('.pub', '') }}" 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 - name: Configure redirector server
hosts: redirectors hosts: redirectors
@@ -89,7 +91,7 @@
vars_files: vars_files:
- vars.yaml - vars.yaml
vars: vars:
c2_ip: "{{ c2_ip | default('127.0.0.1') }}" c2_ip: "{{ hostvars['localhost']['c2_ip'] | default('127.0.0.1') }}"
redirector_subdomain: "{{ redirector_subdomain | default('cdn') }}" redirector_subdomain: "{{ redirector_subdomain | default('cdn') }}"
tasks: tasks:
- name: Wait for apt to be available - name: Wait for apt to be available
@@ -115,9 +117,6 @@
- name: Include common redirector configuration tasks - name: Include common redirector configuration tasks
include_tasks: "../tasks/configure_redirector.yml" include_tasks: "../tasks/configure_redirector.yml"
- name: Include common security hardening tasks
include_tasks: "../tasks/security_hardening.yml"
- name: Print deployment summary - name: Print deployment summary
debug: debug:
msg: msg:
+43 -4
View File
@@ -436,10 +436,23 @@ def select_random_region(config):
if provider == "aws": if provider == "aws":
region_choices = config.get("aws_region_choices", []) region_choices = config.get("aws_region_choices", [])
elif provider == "linode": elif provider == "linode":
# Look for multiple possible key names in the Linode config # Look for both variations of the key name
region_choices = config.get("region_choices", []) region_choices = config.get("region_choices", [])
# Debug the vars_data content
logging.debug(f"Linode config keys: {config.keys()}")
if not region_choices: if not region_choices:
region_choices = config.get("linode_region_choices", []) # Load directly from vars.yaml as fallback
try:
vars_file = "Linode/vars.yaml"
if os.path.exists(vars_file):
with open(vars_file, 'r') as f:
vars_data = yaml.safe_load(f)
region_choices = vars_data.get('region_choices', [])
logging.debug(f"Loaded region_choices directly from {vars_file}: {region_choices}")
except Exception as e:
logging.warning(f"Failed to load regions from vars file: {e}")
elif provider == "flokinet": elif provider == "flokinet":
region_choices = config.get("flokinet_region_choices", []) region_choices = config.get("flokinet_region_choices", [])
@@ -505,6 +518,15 @@ def run_ansible_playbook(playbook, inventory, config, debug=False):
# Convert config dict to JSON for extra-vars # Convert config dict to JSON for extra-vars
# Filter out None values and complex objects # Filter out None values and complex objects
extra_vars = {k: v for k, v in config.items() if v is not None and not isinstance(v, (dict, list, tuple))} extra_vars = {k: v for k, v in config.items() if v is not None and not isinstance(v, (dict, list, tuple))}
# Explicitly set hard-coded user values rather than using templated defaults
if 'ssh_user' in extra_vars:
extra_vars.pop('ssh_user')
if config['provider'] == 'linode':
extra_vars['ssh_user'] = 'root'
else:
extra_vars['ssh_user'] = 'kali'
extra_vars_json = json.dumps(extra_vars) extra_vars_json = json.dumps(extra_vars)
# Build command # Build command
@@ -561,6 +583,12 @@ def deploy_infrastructure(config):
if config.get('linode_token'): if config.get('linode_token'):
os.environ['LINODE_TOKEN'] = config['linode_token'] os.environ['LINODE_TOKEN'] = config['linode_token']
# IMPORTANT: Ensure ssh_user is explicitly set to avoid template recursion
if provider == "linode":
config['ssh_user'] = "root"
elif provider == "aws":
config['ssh_user'] = "kali"
# Select random region if not specified # Select random region if not specified
if not config.get('region'): if not config.get('region'):
config['region'] = select_random_region(config) config['region'] = select_random_region(config)
@@ -1097,6 +1125,10 @@ C2itAll - Red Team Infrastructure Setup
# Provider settings # Provider settings
config['provider'] = args.provider config['provider'] = args.provider
# Copy all values from vars_data to config first
for key, value in vars_data.items():
config[key] = value
# AWS settings # AWS settings
if args.provider == "aws": if args.provider == "aws":
config['aws_access_key'] = args.aws_key or vars_data.get('aws_access_key') config['aws_access_key'] = args.aws_key or vars_data.get('aws_access_key')
@@ -1110,6 +1142,7 @@ C2itAll - Red Team Infrastructure Setup
elif args.provider == "linode": elif args.provider == "linode":
config['linode_token'] = args.linode_token or vars_data.get('linode_token') config['linode_token'] = args.linode_token or vars_data.get('linode_token')
config['linode_region'] = args.linode_region or args.region or vars_data.get('linode_region') config['linode_region'] = args.linode_region or args.region or vars_data.get('linode_region')
# Ensure region_choices are correctly set
config['region_choices'] = vars_data.get('region_choices', []) config['region_choices'] = vars_data.get('region_choices', [])
config['plan'] = args.size or vars_data.get('plan', 'g6-standard-2') config['plan'] = args.size or vars_data.get('plan', 'g6-standard-2')
config['image'] = vars_data.get('image', 'linode/kali') config['image'] = vars_data.get('image', 'linode/kali')
@@ -1121,8 +1154,14 @@ C2itAll - Red Team Infrastructure Setup
config['flokinet_region_choices'] = vars_data.get('flokinet_region_choices', []) config['flokinet_region_choices'] = vars_data.get('flokinet_region_choices', [])
config['ssh_port'] = vars_data.get('ssh_port', 22) config['ssh_port'] = vars_data.get('ssh_port', 22)
# SSH settings # SSH settings - explicitly set SSH user to avoid template recursion
config['ssh_user'] = args.ssh_user or vars_data.get('ssh_user') or (DEFAULT_SSH_USER.get(args.provider) if args.provider else None) if args.provider == "linode":
config['ssh_user'] = "root"
elif args.provider == "aws":
config['ssh_user'] = "kali"
else:
config['ssh_user'] = args.ssh_user or vars_data.get('ssh_user') or (DEFAULT_SSH_USER.get(args.provider) if args.provider else None)
if args.ssh_key: if args.ssh_key:
config['ssh_key'] = os.path.expanduser(args.ssh_key) config['ssh_key'] = os.path.expanduser(args.ssh_key)
else: else: