diff --git a/Linode/c2.yml b/Linode/c2.yml index 5a53103..28f8d34 100644 --- a/Linode/c2.yml +++ b/Linode/c2.yml @@ -28,13 +28,14 @@ access_token: "{{ linode_token }}" label: "{{ c2_name }}" type: "{{ plan }}" - region: "{{ linode_region }}" - image: "{{ image }}" + region: "{{ selected_region }}" + # Use Kali for C2 by default + image: "{{ c2_image | default('linode/kali') }}" root_pass: "{{ lookup('password', '/dev/null length=16') }}" authorized_keys: - "{{ lookup('file', ssh_key_path) }}" state: present - register: c2_instance + register: linode_instance - name: Set c2_ip for later use set_fact: diff --git a/Linode/redirector.yml b/Linode/redirector.yml index e61746b..43be217 100644 --- a/Linode/redirector.yml +++ b/Linode/redirector.yml @@ -8,16 +8,9 @@ vars_files: - vars.yaml vars: - # Default values for required variables - linode_region: "{{ linode_region | default(region_choices | random) }}" - plan: "{{ plan | default('g6-nanode-1') }}" - image: "{{ image | default('linode/kali') }}" - - # Generate random instance name if not provided - redirector_name: "{{ redirector_name | default('srv-' + 9999999999 | random | to_uuid | hash('md5') | truncate(8, True, '')) }}" - - # Generate random shell handler port if not provided - shell_handler_port: "{{ shell_handler_port | default(4000 + 60000 | random) }}" + # Handle both region and selected_region for backward compatibility + selected_region: "{{ selected_region | default(region) | default(linode_region) | default(region_choices | random) }}" + redirector_image: "{{ redirector_image | default('linode/debian12') }}" tasks: - name: Validate required Linode token @@ -31,13 +24,13 @@ access_token: "{{ linode_token }}" label: "{{ redirector_name }}" type: "{{ plan }}" - region: "{{ linode_region }}" - image: "{{ image }}" + region: "{{ selected_region }}" + image: "{{ redirector_image }}" root_pass: "{{ lookup('password', '/dev/null length=16') }}" authorized_keys: - "{{ lookup('file', ssh_key_path) }}" state: present - register: redirector_instance + register: linode_instance - name: Set redirector_ip for later use set_fact: diff --git a/deploy.py b/deploy.py index edae349..52dfdee 100644 --- a/deploy.py +++ b/deploy.py @@ -485,9 +485,11 @@ def create_inventory_file(config, deployment_type): if config.get('ssh_port'): inventory_content.append(f"ansible_port={config['ssh_port']}") - # Use the Python from the virtual environment - venv_python = sys.executable - inventory_content.append(f"ansible_python_interpreter={venv_python}") + # Make sure we DON'T use the local Python interpreter path for remote hosts + if deployment_type == "local": + # Only set Python interpreter for localhost + venv_python = sys.executable + inventory_content.append(f"ansible_python_interpreter={venv_python}") # Add specific host sections based on deployment type if deployment_type == "local": @@ -519,6 +521,14 @@ def run_ansible_playbook(playbook, inventory, config, debug=False): # 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))} + # Handle the region parameter correctly + if 'region' in extra_vars: + # Set selected_region to match what the playbook expects + extra_vars['selected_region'] = extra_vars['region'] + elif 'linode_region' in extra_vars: + # Map linode_region to selected_region for compatibility + extra_vars['selected_region'] = extra_vars['linode_region'] + # Explicitly set hard-coded user values rather than using templated defaults if 'ssh_user' in extra_vars: extra_vars.pop('ssh_user') @@ -527,6 +537,9 @@ def run_ansible_playbook(playbook, inventory, config, debug=False): else: extra_vars['ssh_user'] = 'kali' + # Add ansible_python_interpreter for remote hosts correctly + extra_vars['ansible_python_interpreter'] = '/usr/bin/python3' + extra_vars_json = json.dumps(extra_vars) # Build command @@ -604,7 +617,7 @@ def deploy_infrastructure(config): redirector_config['plan'] = 'g6-nanode-1' # Smallest viable Linode plan # Use the correct case for provider directory - provider_dir = "Linode" + provider_dir = PROVIDER_DIRS[provider] playbook = f"{provider_dir}/redirector.yml" inventory_path = create_inventory_file(redirector_config, "local") @@ -631,7 +644,7 @@ def deploy_infrastructure(config): # Restore original plan for C2 config['plan'] = original_plan - provider_dir = "Linode" + provider_dir = PROVIDER_DIRS[provider] playbook = f"{provider_dir}/c2.yml" inventory_path = create_inventory_file(config, "local") @@ -654,7 +667,7 @@ def deploy_infrastructure(config): return False else: # For AWS and other providers, follow the same pattern but with their directory names - provider_dir = "AWS" if provider == "aws" else provider.capitalize() + provider_dir = PROVIDER_DIRS[provider] # Redirector deployment if not config.get('c2_only'): @@ -888,13 +901,36 @@ def ssh_to_instance(config): logging.info("SSH connection interrupted by user") return True -def cleanup_resources(config): +def cleanup_resources(config, interactive=True): """Clean up resources if deployment fails""" provider = config.get('provider') logging.info(f"Cleaning up {provider} resources...") # Use the correct case for provider directory - provider_dir = "AWS" if provider == "aws" else provider.capitalize() + provider_dir = PROVIDER_DIRS.get(provider, provider.upper()) + + # If interactive, ask for confirmation before cleaning up + if interactive: + print("\n============================================================") + print("Deployment failed or was interrupted. Resources to clean up:") + redirector_name = config.get('redirector_name', 'None') + c2_name = config.get('c2_name', 'None') + print(f" - Redirector: {redirector_name}") + print(f" - C2 Server: {c2_name}") + print("============================================================") + + try: + user_choice = input("\nDo you want to clean up these resources? (y/n): ").lower() + if user_choice != 'y': + logging.info("Cleanup cancelled by user") + print("\nCleanup cancelled. Resources remain active.") + print("You can clean them up later by running with --teardown") + return False + except KeyboardInterrupt: + # Handle if the user presses Ctrl+C during input + print("\nCleanup cancelled. Resources remain active.") + print("You can clean them up later by running with --teardown") + return False # Use Ansible for cleanup with confirmation set to false extra_vars = { @@ -945,6 +981,8 @@ def cleanup_resources(config): os.remove(f"{ssh_key}.pub") except Exception as e: logging.error(f"Failed to remove SSH key: {e}") + + return True def check_dependencies(): """Check if required dependencies are installed""" @@ -1146,6 +1184,7 @@ C2itAll - Red Team Infrastructure Setup config['region_choices'] = vars_data.get('region_choices', []) config['plan'] = args.size or vars_data.get('plan', 'g6-standard-2') config['image'] = vars_data.get('image', 'linode/kali') + config['redirector_image'] = vars_data.get('redirector_image', 'linode/debian11') # FlokiNET settings elif args.provider == "flokinet": @@ -1256,7 +1295,7 @@ C2itAll - Red Team Infrastructure Setup success = deploy_tracker(config) if not success: logging.error("Tracker deployment failed!") - cleanup_resources(config) + cleanup_resources(config, interactive=True) return logging.info("Tracker deployment completed successfully!") @@ -1278,16 +1317,26 @@ C2itAll - Red Team Infrastructure Setup ssh_to_instance(config) else: logging.error("Deployment failed!") - cleanup_resources(config) + cleanup_resources(config, interactive=True) except KeyboardInterrupt: + print("\n\nDeployment interrupted by user") logging.info("Deployment interrupted by user") - cleanup_resources(config) + try: + cleanup_resources(config, interactive=True) + except KeyboardInterrupt: + print("\nCleanup interrupted. Resources may still exist.") + logging.warning("Cleanup interrupted by user. Resources may still exist.") except Exception as e: logging.error(f"Deployment failed with error: {e}") if config.get('debug'): import traceback + traceback.print_exc() logging.debug(traceback.format_exc()) - cleanup_resources(config) + try: + cleanup_resources(config, interactive=True) + except KeyboardInterrupt: + print("\nCleanup interrupted. Resources may still exist.") + logging.warning("Cleanup interrupted by user. Resources may still exist.") if __name__ == "__main__": main() \ No newline at end of file diff --git a/linode-images.json b/linode-images.json new file mode 100644 index 0000000..c3c3d0a --- /dev/null +++ b/linode-images.json @@ -0,0 +1 @@ +{"data": [{"id": "linode/almalinux8", "label": "AlmaLinux 8", "deprecated": false, "size": 4000, "created": "2021-05-18T14:28:38", "updated": "2024-07-02T19:04:04", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "AlmaLinux", "expiry": null, "eol": "2029-01-01T05:00:00", "regions": null, "status": "available", "capabilities": ["distributed-sites"]}, {"id": "linode/almalinux9", "label": "AlmaLinux 9", "deprecated": false, "size": 2500, "created": "2022-05-26T22:07:54", "updated": "2024-11-19T20:14:23", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "AlmaLinux", "expiry": null, "eol": "2032-05-31T04:00:00", "regions": null, "status": "available", "capabilities": ["cloud-init", "distributed-sites"]}, {"id": "linode/alpine3.18", "label": "Alpine 3.18", "deprecated": false, "size": 400, "created": "2023-05-31T16:44:36", "updated": "2025-04-09T16:00:00", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Alpine", "expiry": null, "eol": "2025-05-09T04:00:00", "regions": null, "status": "available", "capabilities": []}, {"id": "linode/alpine3.19", "label": "Alpine 3.19", "deprecated": false, "size": 400, "created": "2023-12-08T15:59:28", "updated": "2025-04-09T16:00:00", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Alpine", "expiry": null, "eol": "2025-11-01T04:00:00", "regions": null, "status": "available", "capabilities": ["cloud-init"]}, {"id": "linode/alpine3.20", "label": "Alpine 3.20", "deprecated": false, "size": 400, "created": "2024-07-23T17:10:57", "updated": "2025-04-09T16:00:00", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Alpine", "expiry": null, "eol": "2026-04-01T04:00:00", "regions": null, "status": "available", "capabilities": ["cloud-init"]}, {"id": "linode/arch", "label": "Arch Linux", "deprecated": false, "size": 2500, "created": "2016-06-13T20:31:34", "updated": "2024-12-17T22:39:07", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Arch", "expiry": null, "eol": null, "regions": null, "status": "available", "capabilities": ["cloud-init"]}, {"id": "linode/centos-stream9", "label": "CentOS Stream 9", "deprecated": false, "size": 2400, "created": "2022-01-05T23:34:00", "updated": "2024-12-17T22:39:07", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "CentOS", "expiry": null, "eol": "2029-06-01T04:00:00", "regions": null, "status": "available", "capabilities": ["cloud-init", "distributed-sites"]}, {"id": "linode/debian11", "label": "Debian 11", "deprecated": false, "size": 1500, "created": "2021-08-14T22:44:02", "updated": "2025-03-25T16:00:00", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Debian", "expiry": null, "eol": "2026-06-30T04:00:00", "regions": null, "status": "available", "capabilities": ["cloud-init", "distributed-sites"]}, {"id": "linode/debian12", "label": "Debian 12", "deprecated": false, "size": 1800, "created": "2023-06-10T15:56:16", "updated": "2025-03-25T16:00:00", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Debian", "expiry": null, "eol": "2028-06-10T04:00:00", "regions": null, "status": "available", "capabilities": ["cloud-init", "distributed-sites"]}, {"id": "linode/fedora40", "label": "Fedora 40", "deprecated": false, "size": 2800, "created": "2024-04-23T15:31:55", "updated": "2024-07-23T20:30:21", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Fedora", "expiry": null, "eol": "2025-05-13T04:00:00", "regions": null, "status": "available", "capabilities": ["cloud-init", "distributed-sites"]}, {"id": "linode/fedora41", "label": "Fedora 41", "deprecated": false, "size": 2000, "created": "2024-10-29T15:36:20", "updated": "2024-10-29T16:08:03", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Fedora", "expiry": null, "eol": "2025-11-29T05:00:00", "regions": null, "status": "available", "capabilities": ["cloud-init"]}, {"id": "linode/gentoo", "label": "Gentoo", "deprecated": false, "size": 7000, "created": "2016-10-25T17:31:25", "updated": "2024-07-03T13:53:22", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Gentoo", "expiry": null, "eol": null, "regions": null, "status": "available", "capabilities": []}, {"id": "linode/kali", "label": "Kali Linux", "deprecated": false, "size": 1536, "created": "2022-02-28T17:08:42", "updated": "2025-04-09T16:00:00", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Kali", "expiry": null, "eol": null, "regions": null, "status": "available", "capabilities": ["cloud-init"]}, {"id": "linode/debian12-kube-v1.29.7", "label": "Kubernetes 1.29.7 on Debian 12", "deprecated": false, "size": 3500, "created": "2024-08-07T20:17:04", "updated": "2024-11-12T23:25:16", "description": null, "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Debian", "expiry": null, "eol": "2028-06-10T04:00:00", "regions": null, "status": "available", "capabilities": ["cloud-init"]}, {"id": "linode/debian12-kube-v1.30.3", "label": "Kubernetes 1.30.3 on Debian 12", "deprecated": false, "size": 3500, "created": "2024-08-07T20:17:04", "updated": "2024-11-12T23:25:24", "description": null, "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Debian", "expiry": null, "eol": "2028-06-10T04:00:00", "regions": null, "status": "available", "capabilities": ["cloud-init"]}, {"id": "linode/debian12-kube-v1.31.0", "label": "Kubernetes 1.31.0 on Debian 12", "deprecated": false, "size": 3500, "created": "2024-09-10T18:15:37", "updated": "2024-11-12T23:25:31", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Debian", "expiry": null, "eol": "2028-06-10T04:00:00", "regions": null, "status": "available", "capabilities": ["cloud-init"]}, {"id": "linode/debian12-kube-v1.32.1", "label": "Kubernetes 1.32.1 on Debian 12", "deprecated": false, "size": 3500, "created": "2025-01-28T18:32:48", "updated": "2025-01-28T18:32:48", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Debian", "expiry": null, "eol": "2028-06-10T04:00:00", "regions": null, "status": "available", "capabilities": ["cloud-init"]}, {"id": "linode/opensuse15.6", "label": "openSUSE Leap 15.6", "deprecated": false, "size": 1200, "created": "2024-06-12T15:59:49", "updated": "2024-07-02T19:04:04", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "openSUSE", "expiry": null, "eol": "2026-01-01T05:00:00", "regions": null, "status": "available", "capabilities": []}, {"id": "linode/rocky8", "label": "Rocky Linux 8", "deprecated": false, "size": 4000, "created": "2021-06-22T01:56:07", "updated": "2024-07-02T19:04:04", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Rocky", "expiry": null, "eol": "2029-05-31T04:00:00", "regions": null, "status": "available", "capabilities": ["distributed-sites"]}, {"id": "linode/rocky9", "label": "Rocky Linux 9", "deprecated": false, "size": 2500, "created": "2022-07-15T15:00:09", "updated": "2024-11-20T16:49:54", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Rocky", "expiry": null, "eol": "2032-05-31T04:00:00", "regions": null, "status": "available", "capabilities": ["cloud-init", "distributed-sites"]}, {"id": "linode/slackware15.0", "label": "Slackware 15.0", "deprecated": false, "size": 11600, "created": "2022-02-04T23:25:47", "updated": "2024-07-02T20:36:20", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Slackware", "expiry": null, "eol": null, "regions": null, "status": "available", "capabilities": []}, {"id": "linode/ubuntu20.04", "label": "Ubuntu 20.04 LTS", "deprecated": false, "size": 3500, "created": "2020-04-23T17:59:32", "updated": "2025-01-27T17:00:00", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Ubuntu", "expiry": null, "eol": "2025-05-29T04:00:00", "regions": null, "status": "available", "capabilities": ["cloud-init", "distributed-sites"]}, {"id": "linode/ubuntu22.04", "label": "Ubuntu 22.04 LTS", "deprecated": false, "size": 3500, "created": "2022-04-21T16:57:06", "updated": "2025-01-27T17:00:00", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Ubuntu", "expiry": null, "eol": "2027-06-01T04:00:00", "regions": null, "status": "available", "capabilities": ["cloud-init", "distributed-sites"]}, {"id": "linode/ubuntu24.04", "label": "Ubuntu 24.04 LTS", "deprecated": false, "size": 3500, "created": "2024-04-25T13:00:11", "updated": "2025-02-20T17:00:00", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Ubuntu", "expiry": null, "eol": "2029-05-31T04:00:00", "regions": null, "status": "available", "capabilities": ["cloud-init", "distributed-sites"]}, {"id": "linode/ubuntu24.10", "label": "Ubuntu 24.10", "deprecated": false, "size": 3500, "created": "2024-10-22T16:11:06", "updated": "2025-01-27T17:00:00", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Ubuntu", "expiry": null, "eol": "2025-07-10T04:00:00", "regions": null, "status": "available", "capabilities": ["cloud-init"]}, {"id": "linode/alpine3.17", "label": "Alpine 3.17", "deprecated": true, "size": 400, "created": "2022-11-22T19:20:51", "updated": "2025-04-09T16:00:00", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Alpine", "expiry": null, "eol": "2024-11-22T05:00:00", "regions": null, "status": "available", "capabilities": []}, {"id": "linode/fedora39", "label": "Fedora 39", "deprecated": true, "size": 2600, "created": "2023-11-07T17:51:27", "updated": "2024-07-02T19:04:04", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Fedora", "expiry": null, "eol": "2024-12-07T05:00:00", "regions": null, "status": "available", "capabilities": ["distributed-sites"]}, {"id": "linode/opensuse15.5", "label": "openSUSE Leap 15.5", "deprecated": true, "size": 1700, "created": "2023-06-07T17:13:25", "updated": "2024-07-02T19:04:04", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "openSUSE", "expiry": null, "eol": "2024-12-07T05:00:00", "regions": null, "status": "available", "capabilities": []}, {"id": "linode/ubuntu16.04lts", "label": "Ubuntu 16.04 LTS", "deprecated": true, "size": 2700, "created": "2016-04-22T18:11:29", "updated": "2024-07-01T21:19:59", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Ubuntu", "expiry": null, "eol": "2026-04-23T04:00:00", "regions": null, "status": "available", "capabilities": ["distributed-sites"]}, {"id": "linode/ubuntu18.04", "label": "Ubuntu 18.04 LTS", "deprecated": true, "size": 2700, "created": "2018-04-26T22:23:37", "updated": "2024-07-01T21:20:15", "description": "", "created_by": "linode", "type": "manual", "tags": [], "is_public": true, "vendor": "Ubuntu", "expiry": null, "eol": "2028-04-26T04:00:00", "regions": null, "status": "available", "capabilities": ["distributed-sites"]}], "page": 1, "pages": 1, "results": 30} \ No newline at end of file