Got attack box and c2-redirector working
This commit is contained in:
@@ -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
@@ -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:
|
||||
|
||||
@@ -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 %}
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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"
|
||||
}
|
||||
Reference in New Issue
Block a user