Got attack box and c2-redirector working

This commit is contained in:
n0mad1k
2025-08-21 16:25:00 -04:00
parent 1450a55e50
commit 9bef2e7d31
93 changed files with 14924 additions and 3727 deletions
+171
View File
@@ -0,0 +1,171 @@
---
# AWS Attack Box Deployment Playbook
# Based on attk-box-setup but optimized for AWS deployment
- name: Deploy Attack Box on AWS
hosts: localhost
connection: local
gather_facts: false
vars_files:
- vars.yaml
vars:
ansible_python_interpreter: "{{ ansible_playbook_python }}"
deployment_type: "attack_box"
attack_box_name: "{{ attack_box_name | default('a-' + deployment_id) }}"
attack_box_type: "{{ attack_box_type | default('kali') }}"
aws_region: "{{ aws_region | default(aws_region_choices | random) }}"
instance_type: "{{ aws_instance_type | default('t2.medium') }}"
ssh_key_name: "attack-box-{{ deployment_id }}"
# Attack box AMI mapping (use Kali Linux AMIs)
attack_box_ami_map:
us-east-1: "{{ kali_ami_map['us-east-1'] | default('ami-061b17d332829ab1c') }}"
us-east-2: "{{ kali_ami_map['us-east-2'] | default('ami-061b17d332829ab1c') }}"
us-west-1: "{{ kali_ami_map['us-west-1'] | default('ami-061b17d332829ab1c') }}"
us-west-2: "{{ kali_ami_map['us-west-2'] | default('ami-061b17d332829ab1c') }}"
tasks:
- name: Validate AWS credentials
assert:
that:
- aws_access_key is defined and aws_access_key != ""
- aws_secret_key is defined and aws_secret_key != ""
fail_msg: "AWS credentials are required"
- name: Debug attack box deployment
debug:
msg: "Deploying {{ attack_box_type }} attack box on AWS in {{ aws_region }}"
- name: Set attack box AMI
set_fact:
attack_box_ami: "{{ attack_box_ami_map[aws_region] | default(attack_box_ami_map['us-east-1']) }}"
- name: Generate SSH key pair for attack box
ec2_key:
name: "{{ ssh_key_name }}"
region: "{{ aws_region }}"
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
state: present
register: ec2_key_result
- name: Save private key locally
copy:
content: "{{ ec2_key_result.key.private_key }}"
dest: "~/.ssh/{{ ssh_key_name }}"
mode: '0600'
when: ec2_key_result.key.private_key is defined
- name: Create security group for attack box
ec2_group:
name: "attack-box-sg-{{ deployment_id }}"
description: "Security group for attack box {{ deployment_id }}"
region: "{{ aws_region }}"
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
rules:
- proto: tcp
ports:
- 22
cidr_ip: "{{ operator_ip | default('0.0.0.0/0') }}/32"
rule_desc: "SSH access from operator IP"
- proto: tcp
ports:
- 80
- 443
cidr_ip: 0.0.0.0/0
rule_desc: "HTTP/HTTPS for tools"
rules_egress:
- proto: all
cidr_ip: 0.0.0.0/0
tags:
Name: "attack-box-sg-{{ deployment_id }}"
DeploymentID: "{{ deployment_id }}"
Type: "attack-box"
register: security_group
- name: Launch attack box EC2 instance
ec2:
key_name: "{{ ssh_key_name }}"
group: "{{ security_group.group_name }}"
instance_type: "{{ instance_type }}"
image: "{{ attack_box_ami }}"
region: "{{ aws_region }}"
aws_access_key: "{{ aws_access_key }}"
aws_secret_key: "{{ aws_secret_key }}"
wait: true
count: 1
instance_tags:
Name: "{{ attack_box_name }}"
DeploymentID: "{{ deployment_id }}"
Type: "attack-box"
Environment: "{{ attack_box_type }}"
user_data: |
#!/bin/bash
# Update system
apt-get update
apt-get upgrade -y
# Install additional tools if needed
{% if attack_box_type == 'kali' %}
# Kali already has most tools
apt-get install -y nmap curl wget git
{% else %}
# Install basic pentest tools for other distros
apt-get install -y nmap curl wget git python3-pip
{% endif %}
# Set hostname
echo "{{ attack_box_name }}" > /etc/hostname
hostname "{{ attack_box_name }}"
# Create deployment info
mkdir -p /root/deployment-info
cat > /root/deployment-info/info.txt << EOF
Deployment ID: {{ deployment_id }}
Attack Box Name: {{ attack_box_name }}
Attack Box Type: {{ attack_box_type }}
Region: {{ aws_region }}
Instance Type: {{ instance_type }}
SSH Key: {{ ssh_key_name }}
EOF
register: ec2_result
- name: Wait for SSH to be available
wait_for:
host: "{{ ec2_result.instances[0].public_ip }}"
port: 22
delay: 60
timeout: 300
- name: Display attack box information
debug:
msg:
- "Attack box deployed successfully!"
- "Instance ID: {{ ec2_result.instances[0].id }}"
- "Public IP: {{ ec2_result.instances[0].public_ip }}"
- "Private IP: {{ ec2_result.instances[0].private_ip }}"
- "SSH Command: ssh -i ~/.ssh/{{ ssh_key_name }} root@{{ ec2_result.instances[0].public_ip }}"
- name: Save deployment information
copy:
content: |
# Attack Box Deployment Information
Instance ID: {{ ec2_result.instances[0].id }}
Public IP: {{ ec2_result.instances[0].public_ip }}
Private IP: {{ ec2_result.instances[0].private_ip }}
SSH Key: ~/.ssh/{{ ssh_key_name }}
SSH Command: ssh -i ~/.ssh/{{ ssh_key_name }} root@{{ ec2_result.instances[0].public_ip }}
Region: {{ aws_region }}
Instance Type: {{ instance_type }}
AMI: {{ attack_box_ami }}
Security Group: {{ security_group.group_name }}
dest: "logs/attack_box_{{ deployment_id }}_info.txt"
- name: Set attack box facts for other playbooks
set_fact:
attack_box_instance_id: "{{ ec2_result.instances[0].id }}"
attack_box_public_ip: "{{ ec2_result.instances[0].public_ip }}"
attack_box_private_ip: "{{ ec2_result.instances[0].private_ip }}"
attack_box_security_group: "{{ security_group.group_name }}"
+63
View File
@@ -0,0 +1,63 @@
---
# AWS-specific phishing infrastructure tasks
- name: Set AWS-specific variables
set_fact:
region: "{{ aws_region | default('us-east-1') }}"
instance_type_map:
gophish: "{{ gophish_instance_type | default('t3.large') }}"
mta_front: "{{ mta_instance_type | default('t3.medium') }}"
redirector: "{{ redirector_instance_type | default('t3.small') }}"
webserver: "{{ webserver_instance_type | default('t3.medium') }}"
- name: Create security group for phishing infrastructure
debug:
msg: "Would create security group: phishing-{{ deployment_id }}"
- name: Deploy Gophish server
debug:
msg: |
Would deploy Gophish server:
- Instance type: {{ instance_type_map.gophish }}
- Region: {{ region }}
- Name: gophish-{{ deployment_id }}
- Framework: gophish
when: "'gophish' in deployment_components"
- name: Deploy MTA Front server
debug:
msg: |
Would deploy MTA Front server:
- Instance type: {{ instance_type_map.mta_front }}
- Region: {{ region }}
- Name: mta-{{ deployment_id }}
- Hostname: {{ mta_hostname | default('mail.' + (phishing_domain | default(domain))) }}
when: "'mta_front' in deployment_components"
- name: Deploy Phishing Redirector
debug:
msg: |
Would deploy Phishing Redirector:
- Instance type: {{ instance_type_map.redirector }}
- Region: {{ region }}
- Name: redirector-{{ deployment_id }}
when: "'redirector' in deployment_components"
- name: Deploy Phishing Webserver
debug:
msg: |
Would deploy Phishing Webserver:
- Instance type: {{ instance_type_map.webserver }}
- Region: {{ region }}
- Name: web-{{ deployment_id }}
when: "'webserver' in deployment_components"
- name: Set deployment results
set_fact:
phishing_deployment_results:
gophish_ip: "{{ '10.0.0.10' if 'gophish' in deployment_components else '' }}"
mta_ip: "{{ '10.0.0.11' if 'mta_front' in deployment_components else '' }}"
redirector_ip: "{{ '10.0.0.12' if 'redirector' in deployment_components else '' }}"
webserver_ip: "{{ '10.0.0.13' if 'webserver' in deployment_components else '' }}"
deployment_id: "{{ deployment_id }}"
domain: "{{ phishing_domain | default(domain) }}"
+1 -1
View File
@@ -8,7 +8,7 @@
- vars.yaml
vars:
aws_region: "{{ aws_region | default(aws_region_choices | random) }}"
confirm_cleanup: "{{ confirm_cleanup | default(true) }}"
confirm_cleanup: false # Skip confirmation in automated teardown
deployment_id: "{{ deployment_id | default('') }}"
redirector_name: "{{ redirector_name | default('r-' + deployment_id) }}"
c2_name: "{{ c2_name | default('s-' + deployment_id) }}"
+65
View File
@@ -0,0 +1,65 @@
---
# Phishing infrastructure deployment playbook
# This is a comprehensive playbook that handles all phishing components
- name: Deploy Phishing Infrastructure
hosts: localhost
gather_facts: true
connection: local
vars_files:
- vars.yaml
tasks:
- name: Display deployment information
debug:
msg: |
Deploying phishing infrastructure
Deployment ID: {{ deployment_id }}
Provider: {{ provider }}
Domain: {{ domain | default(phishing_domain) }}
Components: {{ deployment_type }}
- name: Set deployment facts
set_fact:
deployment_timestamp: "{{ ansible_date_time.epoch }}"
phishing_deployment_results: {}
deployment_components: >-
{% set components = [] %}
{% if deployment_type in ['gophish_only', 'basic_phishing', 'advanced_phishing', 'full_phishing', 'fedramp_phishing'] %}
{% set _ = components.append('gophish') %}
{% endif %}
{% if deployment_type in ['mta_front_only', 'basic_phishing', 'advanced_phishing', 'full_phishing', 'ephemeral_mta'] %}
{% set _ = components.append('mta_front') %}
{% endif %}
{% if deployment_type in ['phishing_redirector_only', 'advanced_phishing', 'full_phishing'] %}
{% set _ = components.append('redirector') %}
{% endif %}
{% if deployment_type in ['phishing_webserver_only', 'full_phishing', 'fedramp_phishing'] %}
{% set _ = components.append('webserver') %}
{% endif %}
{{ components }}
- name: Include provider-specific tasks
include_tasks: "{{ provider }}_phishing.yml"
when: deployment_components | length > 0
- name: Ensure logs directory exists
file:
path: "../../logs"
state: directory
mode: '0755'
delegate_to: localhost
- name: Save deployment information
template:
src: phishing_deployment_info.j2
dest: "{{ playbook_dir }}/logs/phishing_deployment_{{ deployment_id }}.json"
delegate_to: localhost
- name: Display success message
debug:
msg: |
✅ Phishing infrastructure deployment completed
Deployment ID: {{ deployment_id }}
Components deployed: {{ deployment_components | join(', ') }}
Check logs/phishing_deployment_{{ deployment_id }}.json for details
@@ -0,0 +1,10 @@
{
"deployment_id": "{{ deployment_id }}",
"deployment_type": "{{ deployment_type }}",
"provider": "{{ provider }}",
"domain": "{{ phishing_domain | default(domain) }}",
"timestamp": "{{ ansible_date_time.iso8601 }}",
"components": {{ deployment_components | to_json }},
"results": {{ phishing_deployment_results | default({}) | to_json }},
"status": "completed"
}
+1 -1
View File
@@ -11,7 +11,7 @@
vars:
cleanup_redirector: "{{ (redirector_ip is defined and redirector_ip != '') | ternary(true, false) }}"
cleanup_c2: "{{ (c2_ip is defined and c2_ip != '') | ternary(true, false) }}"
confirm_cleanup: "{{ confirm_cleanup | default(true) }}"
confirm_cleanup: false # Skip confirmation in automated teardown
tasks:
- name: Confirm cleanup if required
+119
View File
@@ -0,0 +1,119 @@
---
# FlokiNET-specific phishing infrastructure tasks
- name: Create FlokiNET instances for phishing
uri:
url: "{{ flokinet_api_endpoint }}/instances"
method: POST
headers:
Authorization: "Bearer {{ flokinet_api_token }}"
Content-Type: "application/json"
body_format: json
body:
plan: "{{ flokinet_plan | default('basic') }}"
region: "{{ flokinet_region | default('romania') }}"
os: "{{ flokinet_os | default('ubuntu-22.04') }}"
hostname: "{{ deployment_id }}-{{ item }}"
ssh_keys:
- "{{ ssh_public_key }}"
tags:
- "c2itall"
- "phishing"
- "{{ deployment_id }}"
status_code: [200, 201]
register: flokinet_instances
loop: "{{ deployment_components }}"
when: item in deployment_components
- name: Wait for instances to be active
uri:
url: "{{ flokinet_api_endpoint }}/instances/{{ item.json.id }}"
method: GET
headers:
Authorization: "Bearer {{ flokinet_api_token }}"
register: instance_status
until: instance_status.json.status == "active"
retries: 30
delay: 10
loop: "{{ flokinet_instances.results }}"
when: flokinet_instances.results is defined
- name: Get instance details
uri:
url: "{{ flokinet_api_endpoint }}/instances/{{ item.json.id }}"
method: GET
headers:
Authorization: "Bearer {{ flokinet_api_token }}"
register: instance_details
loop: "{{ flokinet_instances.results }}"
when: flokinet_instances.results is defined
- name: Set instance facts
set_fact:
phishing_instances: >-
{% set instances = [] %}
{% for result in instance_details.results %}
{% set instance = {
'id': result.json.id,
'hostname': result.json.hostname,
'ip': result.json.main_ip,
'region': result.json.region,
'plan': result.json.plan,
'status': result.json.status
} %}
{% set _ = instances.append(instance) %}
{% endfor %}
{{ instances }}
when: instance_details.results is defined
- name: Wait for SSH connectivity
wait_for:
host: "{{ item.ip }}"
port: 22
delay: 30
timeout: 300
loop: "{{ phishing_instances }}"
when: phishing_instances is defined
- name: Update instance inventory
add_host:
name: "{{ item.ip }}"
groups: "phishing_{{ item.hostname.split('-')[-1] }}"
ansible_host: "{{ item.ip }}"
ansible_user: root
ansible_ssh_private_key_file: "{{ ssh_private_key_path }}"
ansible_ssh_common_args: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
instance_id: "{{ item.id }}"
instance_hostname: "{{ item.hostname }}"
provider: "flokinet"
loop: "{{ phishing_instances }}"
when: phishing_instances is defined
- name: Configure Gophish servers
include_tasks: ../common/configure_gophish.yml
when: "'gophish' in deployment_components"
- name: Configure MTA fronts
include_tasks: ../common/configure_mta.yml
when: "'mta_front' in deployment_components"
- name: Configure redirectors
include_tasks: ../common/configure_redirector.yml
when: "'redirector' in deployment_components"
- name: Configure web servers
include_tasks: ../common/configure_webserver.yml
when: "'webserver' in deployment_components"
- name: Display deployment summary
debug:
msg: |
🎯 FlokiNET Phishing Infrastructure Deployed
{{ phishing_instances | length }} instances created
Provider: FlokiNET
Deployment ID: {{ deployment_id }}
Instances:
{% for instance in phishing_instances %}
- {{ instance.hostname }}: {{ instance.ip }} ({{ instance.plan }})
{% endfor %}
when: phishing_instances is defined
+65
View File
@@ -0,0 +1,65 @@
---
# Phishing infrastructure deployment playbook
# This is a comprehensive playbook that handles all phishing components
- name: Deploy Phishing Infrastructure
hosts: localhost
gather_facts: true
connection: local
vars_files:
- vars.yaml
tasks:
- name: Display deployment information
debug:
msg: |
Deploying phishing infrastructure
Deployment ID: {{ deployment_id }}
Provider: {{ provider }}
Domain: {{ domain | default(phishing_domain) }}
Components: {{ deployment_type }}
- name: Set deployment facts
set_fact:
deployment_timestamp: "{{ ansible_date_time.epoch }}"
phishing_deployment_results: {}
deployment_components: >-
{% set components = [] %}
{% if deployment_type in ['gophish_only', 'basic_phishing', 'advanced_phishing', 'full_phishing', 'fedramp_phishing'] %}
{% set _ = components.append('gophish') %}
{% endif %}
{% if deployment_type in ['mta_front_only', 'basic_phishing', 'advanced_phishing', 'full_phishing', 'ephemeral_mta'] %}
{% set _ = components.append('mta_front') %}
{% endif %}
{% if deployment_type in ['phishing_redirector_only', 'advanced_phishing', 'full_phishing'] %}
{% set _ = components.append('redirector') %}
{% endif %}
{% if deployment_type in ['phishing_webserver_only', 'full_phishing', 'fedramp_phishing'] %}
{% set _ = components.append('webserver') %}
{% endif %}
{{ components }}
- name: Include provider-specific tasks
include_tasks: "{{ provider }}_phishing.yml"
when: deployment_components | length > 0
- name: Ensure logs directory exists
file:
path: "../../logs"
state: directory
mode: '0755'
delegate_to: localhost
- name: Save deployment information
template:
src: phishing_deployment_info.j2
dest: "{{ playbook_dir }}/logs/phishing_deployment_{{ deployment_id }}.json"
delegate_to: localhost
- name: Display success message
debug:
msg: |
✅ Phishing infrastructure deployment completed
Deployment ID: {{ deployment_id }}
Components deployed: {{ deployment_components | join(', ') }}
Check logs/phishing_deployment_{{ deployment_id }}.json for details
@@ -0,0 +1,10 @@
{
"deployment_id": "{{ deployment_id }}",
"deployment_type": "{{ deployment_type }}",
"provider": "{{ provider }}",
"domain": "{{ phishing_domain | default(domain) }}",
"timestamp": "{{ ansible_date_time.iso8601 }}",
"components": {{ deployment_components | to_json }},
"results": {{ phishing_deployment_results | default({}) | to_json }},
"status": "completed"
}
+251
View File
@@ -0,0 +1,251 @@
---
# Linode Attack Box Deployment Playbook
# Based on attk-box-setup but optimized for headless server deployment
- name: Deploy Attack Box on Linode
hosts: localhost
connection: local
gather_facts: false
vars:
ansible_python_interpreter: "{{ ansible_playbook_python }}"
deployment_type: "attack_box"
attack_box_name: "{{ attack_box_name | default('a-' + deployment_id) }}"
attack_box_type: "{{ attack_box_type | default('kali') }}"
linode_instance_type: "{{ linode_instance_type | default('g6-standard-4') }}"
linode_region: "{{ linode_region | default('us-east') }}"
ssh_key_name: "{{ ssh_key_path | default('c2deploy_' + attack_box_name) | basename | regex_replace('\\.pub$', '') }}"
# Attack box image mapping (headless versions)
attack_box_images:
kali: "linode/kali"
custom: "linode/kali" # Use Kali as base for custom builds
quick_recon: "linode/kali" # Kali Linux for easy tool expansion
tasks:
- name: Debug attack box deployment
debug:
msg: "Deploying {{ attack_box_type }} attack box on Linode in {{ linode_region }}"
- name: Set attack box image
set_fact:
attack_box_image: "{{ attack_box_images[attack_box_type] | default('linode/kali') }}"
- name: Check if SSH key exists (should be pre-generated)
stat:
path: "~/.ssh/{{ ssh_key_name }}"
register: ssh_key_check
- name: Generate SSH key pair for attack box (if not exists)
openssh_keypair:
path: "~/.ssh/{{ ssh_key_name }}"
type: rsa
size: 2048
force: no
register: ssh_key_result
when: not ssh_key_check.stat.exists
- name: Read public key content
slurp:
src: "~/.ssh/{{ ssh_key_name }}.pub"
register: public_key_content
- name: Add SSH key to Linode
uri:
url: "https://api.linode.com/v4/profile/sshkeys"
method: POST
headers:
Authorization: "Bearer {{ linode_token }}"
Content-Type: "application/json"
body_format: json
body:
label: "{{ ssh_key_name }}"
ssh_key: "{{ public_key_content.content | b64decode | trim }}"
status_code: [200, 201]
register: linode_ssh_key
ignore_errors: yes
- name: Generate strong root password
set_fact:
root_password: "{{ lookup('password', '/dev/null chars=ascii_letters,digits,!@#$%^&*-_=+ length=32') }}"
when: ansible_password is not defined
- name: Set ansible_password if not defined
set_fact:
ansible_password: "{{ root_password }}"
when: ansible_password is not defined and root_password is defined
- name: Create Linode instance for attack box
uri:
url: "https://api.linode.com/v4/linode/instances"
method: POST
headers:
Authorization: "Bearer {{ linode_token }}"
Content-Type: "application/json"
body_format: json
body:
label: "{{ attack_box_name }}"
type: "{{ linode_instance_type }}"
region: "{{ linode_region }}"
image: "{{ attack_box_image }}"
root_pass: "{{ ansible_password | default(root_password) }}"
authorized_keys:
- "{{ public_key_content.content | b64decode | trim }}"
booted: true
backups_enabled: false
private_ip: false
tags:
- "attack-box"
- "c2itall"
- "{{ deployment_id }}"
status_code: [200, 201]
register: linode_instance
- name: Get current timestamp
setup:
gather_subset: min
delegate_to: localhost
- name: Ensure logs directory exists
file:
path: "{{ playbook_dir }}/logs"
state: directory
mode: '0755'
delegate_to: localhost
- name: Save attack box credentials to local file
copy:
content: |
Attack Box: {{ attack_box_name }}
Deployment ID: {{ deployment_id }}
Instance IP: {{ linode_instance.json.ipv4[0] if linode_instance.json.ipv4 else 'Pending' }}
SSH Key: ~/.ssh/{{ ssh_key_name }}
Root Password: {{ ansible_password | default(root_password) }}
SSH Command: ssh -i ~/.ssh/{{ ssh_key_name }} root@{{ linode_instance.json.ipv4[0] if linode_instance.json.ipv4 else 'IP_ADDRESS' }}
Generated at: {{ ansible_date_time.iso8601 }}
dest: "{{ playbook_dir }}/logs/deployment_info_{{ deployment_id }}.txt"
mode: '0600'
when: linode_instance is succeeded
delegate_to: localhost
- name: Save instance information
set_fact:
attack_box_ip: "{{ linode_instance.json.ipv4[0] }}"
attack_box_id: "{{ linode_instance.json.id }}"
- name: Display attack box information
debug:
msg:
- "Attack Box Created Successfully!"
- "Name: {{ attack_box_name }}"
- "IP Address: {{ attack_box_ip }}"
- "Instance ID: {{ attack_box_id }}"
- "Type: {{ attack_box_type }}"
- "SSH Key: ~/.ssh/{{ ssh_key_name }}"
- name: Wait for instance to be fully booted
wait_for:
host: "{{ attack_box_ip }}"
port: 22
delay: 30
timeout: 300
ignore_errors: yes
- name: Test SSH connectivity
command: ssh -o ConnectTimeout=10 -o StrictHostKeyChecking=no -i ~/.ssh/{{ ssh_key_name }} root@{{ attack_box_ip }} echo "SSH connection successful"
register: ssh_test
retries: 5
delay: 30
until: ssh_test.rc == 0
ignore_errors: yes
- name: Create dynamic inventory for attack box configuration
add_host:
name: "{{ attack_box_ip }}"
groups: attack_boxes
ansible_host: "{{ attack_box_ip }}"
ansible_user: root
ansible_ssh_private_key_file: "~/.ssh/{{ ssh_key_name }}"
ansible_ssh_common_args: "-o StrictHostKeyChecking=no"
attack_box_type: "{{ attack_box_type }}"
deployment_id: "{{ deployment_id }}"
- name: Save deployment information
copy:
content: |
# Attack Box Deployment Information
DEPLOYMENT_ID={{ deployment_id }}
ATTACK_BOX_NAME={{ attack_box_name }}
ATTACK_BOX_IP={{ attack_box_ip }}
ATTACK_BOX_ID={{ attack_box_id }}
ATTACK_BOX_TYPE={{ attack_box_type }}
SSH_KEY_PATH=~/.ssh/{{ ssh_key_name }}
PROVIDER=linode
REGION={{ linode_region }}
INSTANCE_TYPE={{ linode_instance_type }}
DEPLOYED_DATE={{ ansible_date_time.iso8601 }}
dest: "{{ playbook_dir }}/logs/attack_box_{{ deployment_id }}.env"
- name: Configure Attack Box
hosts: attack_boxes
gather_facts: yes
become: yes
vars:
setup_workspace: "{{ setup_workspace | default(true) }}"
setup_vpn: "{{ setup_vpn | default(false) }}"
setup_tor: "{{ setup_tor | default(false) }}"
tasks:
- name: Wait for system to be ready
wait_for_connection:
delay: 30
timeout: 300
- name: Update package cache only (avoid grub-pc issues)
apt:
update_cache: yes
cache_valid_time: 3600
when: ansible_os_family == "Debian"
retries: 3
delay: 10
- name: Include attack box configuration tasks
include_tasks: "{{ playbook_dir }}/../../modules/attack-box/tasks/configure_attack_box.yml"
when: deployment_type != "quick_recon_box"
- name: Include quick recon configuration tasks
include_tasks: "{{ playbook_dir }}/../../modules/attack-box/tasks/configure_quick_recon.yml"
when: deployment_type == "quick_recon_box"
- name: Display final setup information (Full Attack Box)
debug:
msg:
- "🎯 Attack Box Configuration Complete!"
- "📦 Instance: {{ attack_box_name }}"
- "🔑 SSH Command: ssh -i ~/.ssh/a-{{ deployment_id }} root@{{ ansible_host }}"
- "🔒 Root Password: {{ ansible_password | default('Check deployment_info_' + deployment_id + '.txt') }}"
- "📁 Credentials saved to: logs/deployment_info_{{ deployment_id }}.txt"
- ""
- "🛠️ Available Commands:"
- " recon <target> - Run reconnaissance automation"
- " portscan <target> - Run port scan automation"
- " webenum <target> - Run web enumeration automation"
when: deployment_type != "quick_recon_box"
- name: Display final setup information (Quick Recon Box)
debug:
msg:
- "🎯 Quick Recon Box Configuration Complete!"
- "📦 Instance: {{ attack_box_name }}"
- "🔑 SSH Command: ssh -i ~/.ssh/qr-{{ deployment_id }} root@{{ ansible_host }}"
- "🔒 Root Password: {{ ansible_password | default('Check deployment_info_' + deployment_id + '.txt') }}"
- "📁 Credentials saved to: logs/deployment_info_{{ deployment_id }}.txt"
- ""
- "🎯 Quick Recon Commands:"
- " qr - Go to working directory"
- " toolkit - Show available tools"
- " portscan <target> - Port scan"
- " subfind <domain> - Subdomain enumeration"
- " webscan <url> - Web application scan"
- " tor-recon <target> - Anonymous reconnaissance"
when: deployment_type == "quick_recon_box"
+73 -18
View File
@@ -43,22 +43,77 @@
when: region_choices is defined and region_choices|length > 0 and not selected_region is defined and not linode_region is defined and not c2_region_value is defined
- name: Create C2 Linode instance
community.general.linode_v4:
access_token: "{{ linode_token }}"
label: "{{ c2_name }}"
type: "{{ plan }}"
region: "{{ c2_region_value }}"
image: "linode/kali"
root_pass: "{{ lookup('password', '/dev/null length=16') }}"
authorized_keys:
- "{{ lookup('file', ssh_key_path) }}"
state: present
register: c2_instance
block:
- name: Try creating instance in specified region
community.general.linode_v4:
access_token: "{{ linode_token }}"
label: "{{ c2_name }}"
type: "{{ plan }}"
region: "{{ c2_region_value }}"
image: "linode/kali"
root_pass: "{{ lookup('password', '/dev/null length=16') }}"
authorized_keys:
- "{{ lookup('file', ssh_key_path) }}"
state: present
register: c2_instance
rescue:
- name: Log region restriction error
debug:
msg: "Region {{ c2_region_value }} 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: "{{ c2_name }}"
type: "{{ plan }}"
region: "{{ item }}"
image: "linode/kali"
root_pass: "{{ lookup('password', '/dev/null length=16') }}"
authorized_keys:
- "{{ lookup('file', ssh_key_path) }}"
state: present
register: c2_instance
loop: "{{ fallback_regions }}"
when: c2_instance is not defined or c2_instance.failed
ignore_errors: yes
- name: Update deployment region with successful fallback
set_fact:
c2_region_value: "{{ item }}"
loop: "{{ fallback_regions }}"
when: c2_instance.results is defined and c2_instance.results[ansible_loop.index0] is defined and not c2_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: c2_instance.failed | default(true)
- name: Set c2_ip for later use
set_fact:
c2_ip: "{{ c2_instance.instance.ipv4[0] }}"
c2_instance_id: "{{ c2_instance.instance.id }}"
block:
- name: Extract instance info from direct creation
set_fact:
c2_ip: "{{ c2_instance.instance.ipv4[0] }}"
c2_instance_id: "{{ c2_instance.instance.id }}"
when: c2_instance.instance is defined
- name: Extract instance info from fallback creation
set_fact:
c2_ip: "{{ item.instance.ipv4[0] }}"
c2_instance_id: "{{ item.instance.id }}"
loop: "{{ c2_instance.results | default([]) }}"
when: c2_instance.results is defined and item.instance is defined and not item.failed
- name: Display final C2 deployment region and IP
debug:
msg: "C2 server deployed successfully in region {{ c2_region_value }} with IP {{ c2_ip }}"
# Enhanced SSH wait task for Linode/c2.yml
- name: Wait for C2 SSH to be available
@@ -107,7 +162,7 @@
vars_files:
- vars.yaml
vars:
redirector_ip: "{{ redirector_ip | default('127.0.0.1') }}"
redirector_ip: "{{ hostvars['localhost']['redirector_ip'] | default('127.0.0.1') }}"
c2_subdomain: "{{ c2_subdomain | default('mail') }}"
tasks:
- name: Wait for apt to be available
@@ -131,13 +186,13 @@
state: restarted
- name: Include common tool installation tasks
include_tasks: "../tasks/install_tools.yml"
include_tasks: "../../common/tasks/install_tools.yml"
- name: Include common C2 configuration tasks
include_tasks: "../tasks/configure_c2.yml"
include_tasks: "../../modules/c2/tasks/configure_c2.yml"
- name: Include common mail server configuration tasks
include_tasks: "../tasks/configure_mail.yml"
include_tasks: "../../common/tasks/configure_mail.yml"
- name: Print deployment summary
debug:
+19 -3
View File
@@ -10,7 +10,8 @@
cleanup_redirector: "{{ (redirector_name is defined and redirector_name != '') | ternary(true, false) }}"
cleanup_c2: "{{ (c2_name is defined and c2_name != '') | ternary(true, false) }}"
cleanup_tracker: "{{ (tracker_name is defined and tracker_name != '') | ternary(true, false) }}"
confirm_cleanup: "{{ confirm_cleanup | default(true) }}"
cleanup_attack_box: "{{ (attack_box_name is defined and attack_box_name != '') | ternary(true, false) }}"
confirm_cleanup: false # Skip confirmation in automated teardown
tasks:
- name: Validate required Linode token
@@ -35,6 +36,9 @@
{% if cleanup_tracker and tracker_name is defined %}
- Tracker instance: {{ tracker_name }}
{% endif %}
{% if cleanup_attack_box and attack_box_name is defined %}
- Attack Box instance: {{ attack_box_name }}
{% endif %}
when: confirm_cleanup | bool
- name: Confirm cleanup operation
@@ -74,6 +78,15 @@
register: tracker_deletion
ignore_errors: yes
- name: Delete attack box instance
community.general.linode_v4:
access_token: "{{ linode_token }}"
label: "{{ attack_box_name }}"
state: absent
when: cleanup_attack_box and attack_box_name is defined and attack_box_name != ""
register: attack_box_deletion
ignore_errors: yes
- name: Clean up deployment state file
file:
path: "{{ playbook_dir }}/../deployment_state_{{ deployment_id }}.json"
@@ -90,12 +103,15 @@
debug:
msg: |
Cleanup results:
{% if redirector_deletion is defined %}
{% if redirector_deletion is defined and redirector_name is defined %}
- Redirector {{ redirector_name }}: {{ redirector_deletion.changed | ternary('Deleted', 'Not found/Could not delete') }}
{% endif %}
{% if c2_deletion is defined %}
{% if c2_deletion is defined and c2_name is defined %}
- C2 {{ c2_name }}: {{ c2_deletion.changed | ternary('Deleted', 'Not found/Could not delete') }}
{% endif %}
{% if tracker_deletion is defined and tracker_name is defined %}
- Tracker {{ tracker_name }}: {{ tracker_deletion.changed | ternary('Deleted', 'Not found/Could not delete') }}
{% endif %}
{% if attack_box_deletion is defined and attack_box_name is defined %}
- Attack Box {{ attack_box_name }}: {{ attack_box_deletion.changed | ternary('Deleted', 'Not found/Could not delete') }}
{% endif %}
+120
View File
@@ -0,0 +1,120 @@
---
# Linode-specific phishing infrastructure tasks
- name: Create Linode instances for phishing
uri:
url: "https://api.linode.com/v4/linode/instances"
method: POST
headers:
Authorization: "Bearer {{ linode_api_token }}"
Content-Type: "application/json"
body_format: json
body:
type: "{{ linode_instance_type | default('g6-nanode-1') }}"
region: "{{ linode_region | default('us-east') }}"
image: "{{ linode_image | default('linode/ubuntu22.04') }}"
label: "{{ deployment_id }}-{{ item }}"
root_pass: "{{ instance_password }}"
authorized_keys:
- "{{ ssh_public_key }}"
tags:
- "c2itall"
- "phishing"
- "{{ deployment_id }}"
status_code: 200
register: linode_instances
loop: "{{ deployment_components }}"
when: item in deployment_components
- name: Wait for instances to be running
uri:
url: "https://api.linode.com/v4/linode/instances/{{ item.json.id }}"
method: GET
headers:
Authorization: "Bearer {{ linode_api_token }}"
register: instance_status
until: instance_status.json.status == "running"
retries: 30
delay: 10
loop: "{{ linode_instances.results }}"
when: linode_instances.results is defined
- name: Get instance details
uri:
url: "https://api.linode.com/v4/linode/instances/{{ item.json.id }}"
method: GET
headers:
Authorization: "Bearer {{ linode_api_token }}"
register: instance_details
loop: "{{ linode_instances.results }}"
when: linode_instances.results is defined
- name: Set instance facts
set_fact:
phishing_instances: >-
{% set instances = [] %}
{% for result in instance_details.results %}
{% set instance = {
'id': result.json.id,
'label': result.json.label,
'ipv4': result.json.ipv4[0],
'region': result.json.region,
'type': result.json.type,
'status': result.json.status
} %}
{% set _ = instances.append(instance) %}
{% endfor %}
{{ instances }}
when: instance_details.results is defined
- name: Wait for SSH connectivity
wait_for:
host: "{{ item.ipv4 }}"
port: 22
delay: 30
timeout: 300
loop: "{{ phishing_instances }}"
when: phishing_instances is defined
- name: Update instance inventory
add_host:
name: "{{ item.ipv4 }}"
groups: "phishing_{{ item.label.split('-')[-1] }}"
ansible_host: "{{ item.ipv4 }}"
ansible_user: root
ansible_ssh_private_key_file: "{{ ssh_private_key_path }}"
ansible_ssh_common_args: "-o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null"
instance_id: "{{ item.id }}"
instance_label: "{{ item.label }}"
provider: "linode"
loop: "{{ phishing_instances }}"
when: phishing_instances is defined
- name: Configure Gophish servers
include_tasks: ../common/configure_gophish.yml
when: "'gophish' in deployment_components"
- name: Configure MTA fronts
include_tasks: ../common/configure_mta.yml
when: "'mta_front' in deployment_components"
- name: Configure redirectors
include_tasks: ../common/configure_redirector.yml
when: "'redirector' in deployment_components"
- name: Configure web servers
include_tasks: ../common/configure_webserver.yml
when: "'webserver' in deployment_components"
- name: Display deployment summary
debug:
msg: |
🎯 Linode Phishing Infrastructure Deployed
{{ phishing_instances | length }} instances created
Provider: Linode
Deployment ID: {{ deployment_id }}
Instances:
{% for instance in phishing_instances %}
- {{ instance.label }}: {{ instance.ipv4 }} ({{ instance.type }})
{% endfor %}
when: phishing_instances is defined
+65
View File
@@ -0,0 +1,65 @@
---
# Phishing infrastructure deployment playbook
# This is a comprehensive playbook that handles all phishing components
- name: Deploy Phishing Infrastructure
hosts: localhost
gather_facts: true
connection: local
vars_files:
- vars.yaml
tasks:
- name: Display deployment information
debug:
msg: |
Deploying phishing infrastructure
Deployment ID: {{ deployment_id }}
Provider: {{ provider }}
Domain: {{ domain | default(phishing_domain) }}
Components: {{ deployment_type }}
- name: Set deployment facts
set_fact:
deployment_timestamp: "{{ ansible_date_time.epoch }}"
phishing_deployment_results: {}
deployment_components: >-
{% set components = [] %}
{% if deployment_type in ['gophish_only', 'basic_phishing', 'advanced_phishing', 'full_phishing', 'fedramp_phishing'] %}
{% set _ = components.append('gophish') %}
{% endif %}
{% if deployment_type in ['mta_front_only', 'basic_phishing', 'advanced_phishing', 'full_phishing', 'ephemeral_mta'] %}
{% set _ = components.append('mta_front') %}
{% endif %}
{% if deployment_type in ['phishing_redirector_only', 'advanced_phishing', 'full_phishing'] %}
{% set _ = components.append('redirector') %}
{% endif %}
{% if deployment_type in ['phishing_webserver_only', 'full_phishing', 'fedramp_phishing'] %}
{% set _ = components.append('webserver') %}
{% endif %}
{{ components }}
- name: Include provider-specific tasks
include_tasks: "{{ provider }}_phishing.yml"
when: deployment_components | length > 0
- name: Ensure logs directory exists
file:
path: "../../logs"
state: directory
mode: '0755'
delegate_to: localhost
- name: Save deployment information
template:
src: phishing_deployment_info.j2
dest: "{{ playbook_dir }}/logs/phishing_deployment_{{ deployment_id }}.json"
delegate_to: localhost
- name: Display success message
debug:
msg: |
✅ Phishing infrastructure deployment completed
Deployment ID: {{ deployment_id }}
Components deployed: {{ deployment_components | join(', ') }}
Check logs/phishing_deployment_{{ deployment_id }}.json for details
+69 -14
View File
@@ -35,22 +35,77 @@
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
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
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
set_fact:
redirector_ip: "{{ redirector_instance.instance.ipv4[0] }}"
redirector_instance_id: "{{ redirector_instance.instance.id }}"
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
@@ -0,0 +1,10 @@
{
"deployment_id": "{{ deployment_id }}",
"deployment_type": "{{ deployment_type }}",
"provider": "{{ provider }}",
"domain": "{{ phishing_domain | default(domain) }}",
"timestamp": "{{ ansible_date_time.iso8601 }}",
"components": {{ deployment_components | to_json }},
"results": {{ phishing_deployment_results | default({}) | to_json }},
"status": "completed"
}
+1
View File
@@ -0,0 +1 @@
# Provider utils package
+75
View File
@@ -0,0 +1,75 @@
#!/usr/bin/env python3
"""
AWS provider utilities for C2ingRed deployment system
"""
import random
import logging
from ..utils.common import COLORS, load_vars_file, confirm_action
def get_aws_credentials(provider_vars=None):
"""Get AWS credentials from user or vars file"""
if not provider_vars:
provider_vars = load_vars_file('aws')
default_aws_key = provider_vars.get('aws_access_key', '')
default_aws_secret = provider_vars.get('aws_secret_key', '')
print(f"\n{COLORS['BLUE']}AWS Configuration{COLORS['RESET']}")
aws_key = input(f"AWS Access Key [{'*****' if default_aws_key else 'leave blank to use AWS CLI profile'}]: ") or default_aws_key
aws_secret = input(f"AWS Secret Key [{'*****' if default_aws_secret else 'leave blank to use AWS CLI profile'}]: ") or default_aws_secret
return {
'aws_access_key': aws_key,
'aws_secret_key': aws_secret
}
def select_aws_region(provider_vars=None, component=None):
"""Let the user select an AWS region"""
if not provider_vars:
provider_vars = load_vars_file('aws')
regions = provider_vars.get('aws_region_choices', [])
component_str = f" for {component}" if component else ""
if not regions:
print(f"{COLORS['YELLOW']}No regions found for AWS, using us-east-1{COLORS['RESET']}")
return "us-east-1"
print(f"\nAvailable AWS regions{component_str}:")
for i, region in enumerate(regions, 1):
print(f" {i}. {region}")
region_input = input(f"\nSelect region{component_str} (number or leave blank for random): ")
if not region_input:
return random.choice(regions)
try:
region_choice = int(region_input)
if 1 <= region_choice <= len(regions):
return regions[region_choice - 1]
else:
print(f"{COLORS['RED']}Invalid choice, using random region{COLORS['RESET']}")
return random.choice(regions)
except ValueError:
print(f"{COLORS['RED']}Invalid input, using random region{COLORS['RESET']}")
return random.choice(regions)
def gather_aws_config():
"""Gather all AWS-specific configuration"""
provider_vars = load_vars_file('aws')
config = {}
# Get credentials
aws_creds = get_aws_credentials(provider_vars)
config.update(aws_creds)
# Get region
config['aws_region'] = select_aws_region(provider_vars)
# Additional AWS-specific settings
config['aws_instance_type'] = provider_vars.get('aws_instance_type', 't3.micro')
config['aws_volume_size'] = provider_vars.get('aws_volume_size', 20)
return config
+24
View File
@@ -0,0 +1,24 @@
---
# Common Gophish server configuration tasks
- name: Configure Gophish servers
debug:
msg: |
Configuring Gophish servers for deployment {{ deployment_id }}
Admin port: {{ gophish_admin_port | default('8090') }}
Domain: {{ phishing_domain | default(domain) }}
- name: Install Gophish
debug:
msg: "Would install and configure Gophish on target hosts"
delegate_to: "{{ item }}"
loop: "{{ groups['phishing_gophish'] | default([]) }}"
when: groups['phishing_gophish'] is defined
- name: Configure Gophish templates
debug:
msg: |
Would configure Gophish with:
- Email template: {{ email_template | default('office365_login') }}
- Campaign: {{ campaign_name | default('test-campaign') }}
- Sender: {{ sender_name | default('IT Support') }}
+23
View File
@@ -0,0 +1,23 @@
---
# Common MTA front server configuration tasks
- name: Configure MTA front servers
debug:
msg: |
Configuring MTA front servers for deployment {{ deployment_id }}
MTA hostname: {{ mta_hostname | default('mail.' + (phishing_domain | default(domain))) }}
SMTP auth user: {{ smtp_auth_user | default('admin') }}
- name: Install MTA software
debug:
msg: "Would install and configure MTA (Postfix/Exim) on target hosts"
delegate_to: "{{ item }}"
loop: "{{ groups['phishing_mta_front'] | default([]) }}"
when: groups['phishing_mta_front'] is defined
- name: Configure DKIM/SPF
debug:
msg: |
Would configure DKIM/SPF records for:
- Domain: {{ phishing_domain | default(domain) }}
- MTA hostname: {{ mta_hostname | default('mail.' + (phishing_domain | default(domain))) }}
+23
View File
@@ -0,0 +1,23 @@
---
# Common redirector configuration tasks
- name: Configure redirector servers
debug:
msg: |
Configuring redirector servers for deployment {{ deployment_id }}
Backend host: {{ backend_host | default('N/A') }}
Redirector type: {{ redirector_type | default('http') }}
- name: Install redirector software
debug:
msg: "Would install and configure Apache/Nginx redirectors on target hosts"
delegate_to: "{{ item }}"
loop: "{{ groups['phishing_redirector'] | default([]) }}"
when: groups['phishing_redirector'] is defined
- name: Configure SSL certificates
debug:
msg: |
Would configure SSL certificates for:
- Domain: {{ phishing_domain | default(domain) }}
- Let's Encrypt email: {{ letsencrypt_email | default('admin@' + (phishing_domain | default(domain))) }}
+22
View File
@@ -0,0 +1,22 @@
---
# Common web server configuration tasks
- name: Configure web servers
debug:
msg: |
Configuring web servers for deployment {{ deployment_id }}
Phishing hostname: {{ phishing_hostname | default('portal.' + (phishing_domain | default(domain))) }}
- name: Install web server software
debug:
msg: "Would install and configure Apache/Nginx web servers on target hosts"
delegate_to: "{{ item }}"
loop: "{{ groups['phishing_webserver'] | default([]) }}"
when: groups['phishing_webserver'] is defined
- name: Deploy phishing pages
debug:
msg: |
Would deploy phishing pages:
- Template: {{ email_template | default('office365_login') }}
- Domain: {{ phishing_domain | default(domain) }}
+51
View File
@@ -0,0 +1,51 @@
#!/usr/bin/env python3
"""
FlokiNET provider utilities for C2ingRed deployment system
"""
import logging
from ..utils.common import COLORS, load_vars_file, validate_ip_address
def get_flokinet_credentials(provider_vars=None):
"""Get FlokiNET server IPs from user or vars file"""
if not provider_vars:
provider_vars = load_vars_file('flokinet')
default_redirector_ip = provider_vars.get('redirector_ip', '')
default_c2_ip = provider_vars.get('c2_ip', '')
print(f"\n{COLORS['BLUE']}FlokiNET Configuration{COLORS['RESET']}")
print(f"{COLORS['YELLOW']}Note: FlokiNET requires pre-provisioned servers{COLORS['RESET']}")
redirector_ip = input(f"FlokiNET Redirector IP Address [default: {default_redirector_ip}]: ") or default_redirector_ip
c2_ip = input(f"FlokiNET C2 Server IP Address [default: {default_c2_ip}]: ") or default_c2_ip
# Validate IP addresses
if redirector_ip and not validate_ip_address(redirector_ip):
print(f"{COLORS['RED']}Invalid redirector IP address{COLORS['RESET']}")
return None
if c2_ip and not validate_ip_address(c2_ip):
print(f"{COLORS['RED']}Invalid C2 server IP address{COLORS['RESET']}")
return None
return {
'flokinet_redirector_ip': redirector_ip,
'flokinet_c2_ip': c2_ip
}
def gather_flokinet_config():
"""Gather all FlokiNET-specific configuration"""
provider_vars = load_vars_file('flokinet')
config = {}
# Get server IPs
flokinet_ips = get_flokinet_credentials(provider_vars)
if not flokinet_ips:
return None
config.update(flokinet_ips)
# FlokiNET-specific settings
config['ssh_user'] = 'root' # FlokiNET typically uses root
return config
+76
View File
@@ -0,0 +1,76 @@
#!/usr/bin/env python3
"""
Linode provider utilities for C2ingRed deployment system
"""
import random
import logging
from ..utils.common import COLORS, load_vars_file
def get_linode_credentials(provider_vars=None):
"""Get Linode API token from user or vars file"""
if not provider_vars:
provider_vars = load_vars_file('linode')
default_token = provider_vars.get('linode_token', '')
print(f"\n{COLORS['BLUE']}Linode Configuration{COLORS['RESET']}")
token = input(f"Linode API Token [{'*****' if default_token else 'required'}]: ") or default_token
if not token:
print(f"{COLORS['RED']}Linode API token is required{COLORS['RESET']}")
return None
return {'linode_token': token}
def select_linode_region(provider_vars=None, component=None):
"""Let the user select a Linode region"""
if not provider_vars:
provider_vars = load_vars_file('linode')
regions = provider_vars.get('region_choices', [])
component_str = f" for {component}" if component else ""
if not regions:
print(f"{COLORS['YELLOW']}No regions found for Linode, using us-east{COLORS['RESET']}")
return "us-east"
print(f"\nAvailable Linode regions{component_str}:")
for i, region in enumerate(regions, 1):
print(f" {i}. {region}")
region_input = input(f"\nSelect region{component_str} (number or leave blank for random): ")
if not region_input:
return random.choice(regions)
try:
region_choice = int(region_input)
if 1 <= region_choice <= len(regions):
return regions[region_choice - 1]
else:
print(f"{COLORS['RED']}Invalid choice, using random region{COLORS['RESET']}")
return random.choice(regions)
except ValueError:
print(f"{COLORS['RED']}Invalid input, using random region{COLORS['RESET']}")
return random.choice(regions)
def gather_linode_config():
"""Gather all Linode-specific configuration"""
provider_vars = load_vars_file('linode')
config = {}
# Get credentials
linode_creds = get_linode_credentials(provider_vars)
if not linode_creds:
return None
config.update(linode_creds)
# Get region
config['linode_region'] = select_linode_region(provider_vars)
# Additional Linode-specific settings
config['linode_instance_type'] = provider_vars.get('linode_instance_type', 'g6-nanode-1')
config['linode_image'] = provider_vars.get('linode_image', 'linode/kali')
return config
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env python3
"""
Provider selection and configuration utilities
"""
from ..utils.common import COLORS, PROVIDERS
from .aws_utils import gather_aws_config
from .linode_utils import gather_linode_config
from .flokinet_utils import gather_flokinet_config
def select_provider():
"""Let the user select a cloud provider"""
print(f"\n{COLORS['BLUE']}Available cloud providers:{COLORS['RESET']}")
for i, provider in enumerate(PROVIDERS, 1):
print(f" {i}. {provider.capitalize()}")
while True:
try:
provider_choice = input(f"\nSelect a provider (1-{len(PROVIDERS)} or 99 to cancel): ")
if provider_choice == "99":
return None
provider_choice = int(provider_choice)
if 1 <= provider_choice <= len(PROVIDERS):
return PROVIDERS[provider_choice - 1]
else:
print(f"{COLORS['RED']}Please enter a number between 1 and {len(PROVIDERS)}{COLORS['RESET']}")
except ValueError:
print(f"{COLORS['RED']}Please enter a valid number{COLORS['RESET']}")
def gather_provider_config(provider):
"""Gather configuration for the specified provider"""
if provider == "aws":
return gather_aws_config()
elif provider == "linode":
return gather_linode_config()
elif provider == "flokinet":
return gather_flokinet_config()
else:
print(f"{COLORS['RED']}Unknown provider: {provider}{COLORS['RESET']}")
return None