├── .gitignore ├── README.md └── redirectors ├── _template ├── README.md ├── ansible │ ├── ansible.cfg │ ├── main.yml │ └── roles │ │ └── redirect_method │ │ ├── handlers │ │ └── main.yml │ │ └── tasks │ │ └── main.yml └── terraform │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ ├── ssh_keys │ └── .gitkeep │ ├── template.tfvars │ └── variables.tf ├── apache ├── README.md ├── ansible │ ├── ansible.cfg │ ├── main.yml │ └── roles │ │ └── redirect_apache │ │ ├── defaults │ │ └── main.yml │ │ ├── handlers │ │ └── main.yml │ │ ├── tasks │ │ └── main.yml │ │ └── templates │ │ └── vhost.conf.j2 └── terraform │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ ├── redirector.tf │ ├── ssh_keys │ └── .gitkeep │ ├── template.tfvars │ └── variables.tf ├── aws-cloudfront ├── README.md └── terraform │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ ├── template.tfvars │ └── variables.tf ├── aws-lambda └── README.md ├── azure-cdn ├── README.md └── terraform │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ ├── template.tfvars │ └── variables.tf ├── azure-functions └── README.md ├── cloudflare-cdn └── README.md ├── cloudflare-workers ├── README.md └── terraform │ ├── main.tf │ ├── providers.tf │ ├── script.tpl │ ├── template.tfvars │ └── variables.tf ├── go-proxy └── README.md ├── google-cloud-functions └── README.md ├── haproxy ├── README.md ├── ansible │ ├── ansible.cfg │ ├── main.yml │ └── roles │ │ └── redirect_haproxy │ │ ├── defaults │ │ └── main.yml │ │ ├── handlers │ │ └── main.yml │ │ ├── tasks │ │ └── main.yml │ │ └── templates │ │ └── haproxy.conf.j2 └── terraform │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ ├── redirector.tf │ ├── ssh_keys │ └── .gitkeep │ ├── template.tfvars │ └── variables.tf ├── iptables ├── README.md ├── ansible │ ├── ansible.cfg │ ├── main.yml │ └── roles │ │ └── redirect_method │ │ └── tasks │ │ └── main.yml └── terraform │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ ├── redirector.tf │ ├── ssh_keys │ └── .gitkeep │ ├── template.tfvars │ └── variables.tf ├── nginx ├── README.md ├── ansible │ ├── ansible.cfg │ ├── main.yml │ └── roles │ │ └── redirect_nginx │ │ ├── defaults │ │ └── main.yml │ │ ├── handlers │ │ └── main.yml │ │ ├── tasks │ │ └── main.yml │ │ └── templates │ │ └── nginx.conf.j2 └── terraform │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ ├── redirector.tf │ ├── ssh_keys │ └── .gitkeep │ ├── template.tfvars │ └── variables.tf ├── socat ├── README.md ├── ansible │ ├── ansible.cfg │ ├── main.yml │ └── roles │ │ └── redirect_socat │ │ ├── handlers │ │ └── main.yml │ │ └── tasks │ │ └── main.yml └── terraform │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ ├── redirector.tf │ ├── ssh_keys │ └── .gitkeep │ ├── template.tfvars │ └── variables.tf ├── ssh ├── README.md ├── ansible │ ├── main.yml │ └── roles │ │ └── redirect_ssh │ │ ├── handlers │ │ └── main.yml │ │ └── tasks │ │ └── main.yml └── terraform │ ├── main.tf │ ├── outputs.tf │ ├── providers.tf │ ├── redirector.tf │ ├── ssh_keys │ └── .gitkeep │ ├── template.tfvars │ └── variables.tf └── traefik ├── README.md ├── ansible ├── ansible.cfg ├── main.yml └── roles │ └── redirect_traefik │ ├── defaults │ └── main.yml │ ├── handlers │ └── main.yml │ ├── tasks │ └── main.yml │ └── templates │ ├── provider.toml.j2 │ ├── traefik.service.j2 │ └── traefik.toml.j2 └── terraform ├── main.tf ├── outputs.tf ├── providers.tf ├── redirector.tf ├── ssh_keys └── .gitkeep ├── template.tfvars └── variables.tf /.gitignore: -------------------------------------------------------------------------------- 1 | # Environments 2 | .env 3 | .venv 4 | env/ 5 | venv/ 6 | ENV/ 7 | env.bak/ 8 | venv.bak/ 9 | 10 | # Local .terraform directories 11 | **/.terraform/* 12 | 13 | # .tfstate files 14 | *.tfstate 15 | *.tfstate.* 16 | 17 | # .tfvars files 18 | *.tfvars 19 | !template.tfvars 20 | 21 | env 22 | .vs/ 23 | .vscode/ 24 | **/ssh_keys/* 25 | !.gitkeep -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # C&C Redirectors Library 2 | 3 | Library of **command and control traffic redirectors**, used in redteam engagements. 4 | 5 | This project aim to gather methods to redirect traffic (HTTP/S, DNS) to another server. This capability is usefull to hide a server IP and bring flexibility. If the redirector is identified and blocked by defenders, a new one can be setup more easily than a full C&C server. 6 | 7 | Having multiple methods enable the redteam to gain flexibility, adapt to different situation and better emulate real adversary. 8 | 9 | Each documented redirection method is in a dedicated directory. 10 | 11 | ## Categories 12 | 13 | Redirectors has following attributes: 14 | 15 | | Attribute | Description | Possible values | 16 | | -------------- | ------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------- | 17 | | Type | Is it a smart or dumb redirector ? Is it able to apply conditionnal filtering/redirection rules ? | `smart`, `dumb` | 18 | | Subtype | Give more details on the redirector | `command line`, `web server`, `function`, `service to configure`, etc. | 19 | | Automated | Is the deployement process automated ? | `yes`, `no` | 20 | | Keep Origin IP | Does the redirecter keep in any way the client IP and is able to tranfer it to the C2 ? | `yes`, `no` | 21 | | Decrypt | Does the redirector needs to decrypt the trafic and thus exposing data to the provider ? | `yes`, `no` | 22 | 23 | ## Automation 24 | 25 | Automated solution make use of `terraform` and `ansible` when needed and possible. 26 | 27 | Ansible config suppose you use `root` or a user able to become `root`. 28 | 29 | ### Terraform 30 | 31 | To deploy a redirector, `cd` in the `terraform` directory corresponding to the desire method and then: 32 | 33 | ```bash 34 | terraform init 35 | cp templates.tfvars my_redirector.tfvars 36 | 37 | # Edit my_redirector.tfvars 38 | 39 | terraform apply --var-file my_redirector.tfvars 40 | ``` 41 | 42 | Automation is done (when it is) to host the redirector on **AWS** (for redirector type such as `web server` or `command line`). 43 | 44 | ## 💰 Pricing 💰 45 | 46 | One of the goal of this project is to find cheap solutions. Feel free to propose any improvment to reduce the cost of a solution. Average cost of solutions are around 5$/month. Nonetheless, as price may vary no cost estimation is done per solution. 47 | 48 | :warning: Be carefull with solution with a "pay per request" pricing. As you may use your redirector heavily at some point (ex. Cobalt Strike in interactive mode), cost can rise rapidly. 49 | 50 | Tips : Doing 4 requests per second, during a month will result in 10 368 000 request per month. 51 | 52 | If you don't need much, you may even stay under the "Free Tier" or "developper" offers threshold and not pay anything. 53 | 54 | ## Comments 55 | 56 | Some global recommendations/comments: 57 | 58 | - As you may notice, cloud instance choosen in automation are the smallest ones. You only need to redirect HTTP/S requests. If you find cheapest/smallest solutions, feel free to open an issue. 59 | 60 | ## Status 61 | 62 | | Method | Documented | Ansible | Terraform | 63 | | ------------------------ | ------------------ | ------------------ | ------------------ | 64 | | `socat` | :white_check_mark: | :white_check_mark: | :white_check_mark: | 65 | | `ssh` | :white_check_mark: | :white_check_mark: | :white_check_mark: | 66 | | `iptables` | :white_check_mark: | :white_check_mark: | :white_check_mark: | 67 | | `apache` | :white_check_mark: | :white_check_mark: | :white_check_mark: | 68 | | `nginx` | :white_check_mark: | :white_check_mark: | :white_check_mark: | 69 | | `haproxy` | :white_check_mark: | :white_check_mark: | :white_check_mark: | 70 | | `traefik` | :white_check_mark: | :white_check_mark: | :white_check_mark: | 71 | | `cloudflare-workers` | :white_check_mark: | N/A | :white_check_mark: | 72 | | `azure-cdn` | :white_check_mark: | N/A | :white_check_mark: | 73 | | `aws-cloudfront` | :white_check_mark: | N/A | :white_check_mark: | 74 | | `azure-functions` | :x: | N/A | :x: | 75 | | `cloudflare-cdn` | :x: | N/A | :x: | 76 | | `azure-functions` | :x: | N/A | :x: | 77 | | `google-cloud-functions` | :x: | N/A | :x: | 78 | | `aws-lambda` | :x: | N/A | :x: | 79 | | `go-proxy` | :x: | :x: | :x: | 80 | 81 | ## Ideas / Possible candidates for integration 82 | 83 | Here is the following ideas/candidates I have not yet explore: 84 | 85 | - Netlify CDN 86 | - [tinyproxy](https://github.com/tinyproxy/tinyproxy) 87 | - [mitmproxy](https://mitmproxy.org/) 88 | 89 | ## Resources 90 | 91 | - [HTTPS Payload and C2 Redirectors](https://posts.specterops.io/https-payload-and-c2-redirectors-ff8eb6f87742) 92 | -------------------------------------------------------------------------------- /redirectors/_template/README.md: -------------------------------------------------------------------------------- 1 | # CHANGEME 2 | 3 | | Type | Subtype | Automated | Keep Origin IP | Decrypt | 4 | | ------ | -------------- | --------- | -------------- | ------- | 5 | | `dumb` | `command line` | `no` | `no` | `no` | 6 | 7 | ## How to 8 | 9 | ### Install 10 | 11 | ```bash 12 | 13 | ``` 14 | 15 | ### Launch 16 | 17 | Launch the following command: 18 | 19 | ```bash 20 | 21 | ``` 22 | 23 | ## Comments 24 | 25 | ## Resources 26 | -------------------------------------------------------------------------------- /redirectors/_template/ansible/ansible.cfg: -------------------------------------------------------------------------------- 1 | [ssh_connection] 2 | ssh_args = -o ControlMaster=auto -o ControlPersist=60s 3 | pipelining = true -------------------------------------------------------------------------------- /redirectors/_template/ansible/main.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | roles: 3 | - redirect_ 4 | become: yes -------------------------------------------------------------------------------- /redirectors/_template/ansible/roles/redirect_method/handlers/main.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upils/redirect-lib/76334c3764ca57e3120bacd30d20703d8ca5f437/redirectors/_template/ansible/roles/redirect_method/handlers/main.yml -------------------------------------------------------------------------------- /redirectors/_template/ansible/roles/redirect_method/tasks/main.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upils/redirect-lib/76334c3764ca57e3120bacd30d20703d8ca5f437/redirectors/_template/ansible/roles/redirect_method/tasks/main.yml -------------------------------------------------------------------------------- /redirectors/_template/terraform/main.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upils/redirect-lib/76334c3764ca57e3120bacd30d20703d8ca5f437/redirectors/_template/terraform/main.tf -------------------------------------------------------------------------------- /redirectors/_template/terraform/outputs.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upils/redirect-lib/76334c3764ca57e3120bacd30d20703d8ca5f437/redirectors/_template/terraform/outputs.tf -------------------------------------------------------------------------------- /redirectors/_template/terraform/providers.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upils/redirect-lib/76334c3764ca57e3120bacd30d20703d8ca5f437/redirectors/_template/terraform/providers.tf -------------------------------------------------------------------------------- /redirectors/_template/terraform/ssh_keys/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upils/redirect-lib/76334c3764ca57e3120bacd30d20703d8ca5f437/redirectors/_template/terraform/ssh_keys/.gitkeep -------------------------------------------------------------------------------- /redirectors/_template/terraform/template.tfvars: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upils/redirect-lib/76334c3764ca57e3120bacd30d20703d8ca5f437/redirectors/_template/terraform/template.tfvars -------------------------------------------------------------------------------- /redirectors/_template/terraform/variables.tf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upils/redirect-lib/76334c3764ca57e3120bacd30d20703d8ca5f437/redirectors/_template/terraform/variables.tf -------------------------------------------------------------------------------- /redirectors/apache/README.md: -------------------------------------------------------------------------------- 1 | # Apache 2 | 3 | | Type | Subtype | Automated | Keep Origin IP | Decrypt | 4 | | ------- | ------------ | --------- | ----------------------------- | ------- | 5 | | `smart` | `web server` | `yes` | `yes` (if proxyprotocol used) | `yes` | 6 | 7 | ## How to 8 | 9 | ## Install 10 | 11 | 1. `apache2` is available in package repository, so for example on ubuntu/debian: 12 | 13 | ```bash 14 | sudo apt install apache2 15 | ``` 16 | 17 | 2. Enable needed modules: 18 | 19 | ```bash 20 | sudo a2enmod rewrite proxy proxy_http remoteip ssl headers http2 21 | ``` 22 | 23 | 3. Disable `deflate` module: 24 | 25 | ```bash 26 | sudo a2dismod -f deflate 27 | ``` 28 | 29 | 4. Then copy the template file from `./ansible/roles/redirect_apache2/templates/vhost.conf.j2`, rename it `redirector.conf`, and copy it in `/etc/apache2/sites-enabled/` 30 | 5. Remove any other file in this directory 31 | 6. Replace `{{ vars }}` by your values in this file. 32 | 7. Harden the default apache2 conf by setting `ServerTokens Prod` and `ServerSignature Off` in `/etc/apache2/conf-enabled/security.conf` 33 | 34 | ### Launch 35 | 36 | If `apache2` was installed using the package manager, a service is keeping it running. So you can reload it: 37 | 38 | ```bash 39 | systemctl reload apache2.service 40 | ``` 41 | 42 | ## Comments 43 | 44 | - The given configuration file is only redirecting everything to the C2, without any filtering. Some tweaking is needed to make this method "smart". 45 | 46 | ## Resources 47 | 48 | - [Automatically Generate Rulesets for Apache mod_rewrite or Nginx for Intelligent HTTP C2 Redirection](https://github.com/threatexpress/cs2modrewrite) 49 | -------------------------------------------------------------------------------- /redirectors/apache/ansible/ansible.cfg: -------------------------------------------------------------------------------- 1 | [ssh_connection] 2 | ssh_args = -o ControlMaster=auto -o ControlPersist=60s 3 | pipelining = true -------------------------------------------------------------------------------- /redirectors/apache/ansible/main.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | roles: 3 | - redirect_ 4 | become: yes -------------------------------------------------------------------------------- /redirectors/apache/ansible/roles/redirect_apache/defaults/main.yml: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/upils/redirect-lib/76334c3764ca57e3120bacd30d20703d8ca5f437/redirectors/apache/ansible/roles/redirect_apache/defaults/main.yml -------------------------------------------------------------------------------- /redirectors/apache/ansible/roles/redirect_apache/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: reload apache2 2 | systemd: 3 | name: apache2 4 | state: reloaded 5 | enabled: yes 6 | daemon_reload: yes 7 | -------------------------------------------------------------------------------- /redirectors/apache/ansible/roles/redirect_apache/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Ensure apache2 is installed 2 | apt: 3 | name: apache2 4 | state: present 5 | 6 | - name: Enable rewrite apache2 module 7 | apache2_module: 8 | state: present 9 | name: rewrite 10 | 11 | - name: Enable proxy apache2 module 12 | apache2_module: 13 | state: present 14 | name: proxy 15 | 16 | - name: Enable proxy_http apache2 module 17 | apache2_module: 18 | state: present 19 | name: proxy_http 20 | 21 | - name: Enable remoteip apache2 module 22 | apache2_module: 23 | state: present 24 | name: remoteip 25 | 26 | - name: Enable ssl apache2 module 27 | apache2_module: 28 | state: present 29 | name: ssl 30 | 31 | - name: Enable headers apache2 module 32 | apache2_module: 33 | state: present 34 | name: headers 35 | 36 | - name: Enable http2 apache2 module 37 | apache2_module: 38 | state: present 39 | name: http2 40 | 41 | - name: Disable default modules for Debian 42 | apache2_module: 43 | state: absent 44 | name: autoindex 45 | force: True 46 | 47 | - name: Disable deflate module 48 | apache2_module: 49 | state: absent 50 | name: deflate 51 | force: True 52 | 53 | - name: Set ServerSignature Off for apache2 54 | lineinfile: 55 | path: /etc/apache2/conf-enabled/security.conf 56 | regexp: 'ServerSignature On' 57 | line: ServerSignature Off 58 | notify: reload apache2 59 | 60 | - name: Set ServerTokens Prod for apache2 61 | lineinfile: 62 | path: /etc/apache2/conf-enabled/security.conf 63 | regexp: 'ServerTokens OS' 64 | line: ServerTokens Prod 65 | notify: reload apache2 66 | 67 | - name: Clean default vhosts 68 | file: 69 | state: absent 70 | path: "/etc/apache2/sites-enabled/" 71 | 72 | - name: Copy apache2 conf 73 | template: 74 | src: "{{ apache2_conf_template }}.j2" 75 | dest: "/etc/apache2/sites-enabled/redirector.conf" 76 | owner: root 77 | group: root 78 | mode: 0744 79 | notify: reload apache2 80 | -------------------------------------------------------------------------------- /redirectors/apache/ansible/roles/redirect_apache/templates/vhost.conf.j2: -------------------------------------------------------------------------------- 1 | 2 | ServerName {{ hostname_clean_conf }} 3 | ServerAlias {{ hostname }} 4 | DocumentRoot /var/www/${domain_clean_path}/ 5 | 6 | SSLEngine on 7 | # Disable Cert checking, useful if you're using a self-signed cert 8 | SSLProxyEngine on 9 | SSLProxyCheckPeerCN Off 10 | SSLProxyCheckPeerName Off 11 | SSLProxyCheckPeerExpire Off 12 | ProxyPreserveHost On 13 | 14 | remoteipproxyprotocol on 15 | remoteipproxyprotocolexceptions 127.0.0.1 16 | remoteipheader x-forwarded-for 17 | remoteipproxiesheader x-forwarded-by 18 | 19 | RewriteRule ^.*$ "%%{REQUEST_SCHEME}://{{ c2_ip }}%%{REQUEST_URI}" [P,L] 20 | 21 | 22 | Options Indexes FollowSymLinks ExecCGI MultiViews 23 | MultiviewsMatch Handlers 24 | AllowOverride All 25 | Require all granted 26 | 27 | 28 | ErrorLog $${APACHE_LOG_DIR}/redirector_error.log 29 | CustomLog $${APACHE_LOG_DIR}/redirector_access.log "%t client:%a redir:%%{c}h domain:%%{Host}i \"%r\" %>s %b \"%%{Referer}i\" \"%%{User-agent}i\"" 30 | 31 | -------------------------------------------------------------------------------- /redirectors/apache/terraform/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.12.20" 3 | 4 | required_providers { 5 | local = "~> 1.4.0" 6 | aws = "~> 2.55.0" 7 | tls = "~> 2.1.1" 8 | } 9 | } 10 | 11 | resource "tls_private_key" "ssh" { 12 | algorithm = "RSA" 13 | rsa_bits = 4096 14 | } 15 | 16 | resource "local_file" "ssh_private_key_pem" { 17 | sensitive_content = tls_private_key.ssh.private_key_pem 18 | filename = "./ssh_keys/${var.redirector_name}" 19 | file_permission = "0600" 20 | } 21 | 22 | resource "local_file" "ssh_public_key_pem" { 23 | content = tls_private_key.ssh.public_key_openssh 24 | filename = "./ssh_keys/${var.redirector_name}.pub" 25 | file_permission = "0600" 26 | } 27 | -------------------------------------------------------------------------------- /redirectors/apache/terraform/outputs.tf: -------------------------------------------------------------------------------- 1 | output "aws_redirector_ip" { 2 | value = aws_instance.redirector.public_ip 3 | } 4 | 5 | output "to_ssh" { 6 | value = "ssh -i ${local_file.ssh_private_key_pem.filename} ubuntu@${aws_instance.redirector.public_ip}" 7 | } 8 | -------------------------------------------------------------------------------- /redirectors/apache/terraform/providers.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | AWS_ACCESS_KEY_ID = lookup(var.credentials, "AWS_ACCESS_KEY_ID", "INVALID") 3 | AWS_SECRET_ACCESS_KEY = lookup(var.credentials, "AWS_SECRET_ACCESS_KEY", "INVALID") 4 | AWS_DEFAULT_REGION = lookup(var.credentials, "AWS_DEFAULT_REGION", "eu-central-1") 5 | } 6 | 7 | provider "aws" { 8 | region = local.AWS_DEFAULT_REGION 9 | secret_key = local.AWS_SECRET_ACCESS_KEY 10 | access_key = local.AWS_ACCESS_KEY_ID 11 | skip_credentials_validation = true 12 | skip_requesting_account_id = true 13 | } 14 | 15 | provider "local" {} 16 | provider "tls" {} 17 | -------------------------------------------------------------------------------- /redirectors/apache/terraform/redirector.tf: -------------------------------------------------------------------------------- 1 | resource "aws_security_group" "allow_all" { 2 | name = "allow_all_${var.redirector_name}" 3 | description = "Allow all traffic" 4 | 5 | egress { 6 | from_port = 0 7 | to_port = 0 8 | protocol = "-1" 9 | cidr_blocks = ["0.0.0.0/0"] 10 | } 11 | 12 | ingress { 13 | from_port = 0 14 | to_port = 0 15 | protocol = "-1" 16 | cidr_blocks = ["0.0.0.0/0"] 17 | } 18 | } 19 | 20 | resource "aws_key_pair" "master" { 21 | key_name = var.redirector_name 22 | public_key = tls_private_key.ssh.public_key_openssh 23 | } 24 | 25 | data "aws_ami" "ubuntu" { 26 | most_recent = true 27 | 28 | filter { 29 | name = "name" 30 | values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"] 31 | } 32 | 33 | filter { 34 | name = "virtualization-type" 35 | values = ["hvm"] 36 | } 37 | 38 | owners = ["099720109477"] # Canonical 39 | } 40 | 41 | resource "aws_instance" "redirector" { 42 | tags = { 43 | Name = var.redirector_name 44 | } 45 | 46 | ami = data.aws_ami.ubuntu.id 47 | instance_type = "t2.micro" 48 | 49 | key_name = aws_key_pair.master.key_name 50 | associate_public_ip_address = true 51 | security_groups = [aws_security_group.allow_all.name] 52 | 53 | // To force waiting for the instance to be up. Cleanest way for now (https://github.com/hashicorp/terraform/issues/2811) 54 | provisioner "remote-exec" { 55 | inline = ["echo 'Instance ready!'"] 56 | 57 | connection { 58 | host = aws_instance.redirector.public_ip 59 | type = "ssh" 60 | user = "ubuntu" 61 | private_key = tls_private_key.ssh.private_key_pem 62 | } 63 | } 64 | 65 | provisioner "local-exec" { 66 | command = < { 50 | event.respondWith(handleRequest(event.request)) 51 | }) 52 | -------------------------------------------------------------------------------- /redirectors/cloudflare-workers/terraform/template.tfvars: -------------------------------------------------------------------------------- 1 | redirector_name = "redirector" 2 | c2_ip = "127.0.0.1" 3 | c2_port = "443" 4 | domain = "extample.com" 5 | zone_id = "CHANGE_ME" 6 | credentials = { 7 | "CLOUDFLARE_API_KEY" = "" 8 | "CLOUDFLARE_EMAIL" = "" 9 | "CLOUDFLARE_ZONE_ID" = "" 10 | } 11 | -------------------------------------------------------------------------------- /redirectors/cloudflare-workers/terraform/variables.tf: -------------------------------------------------------------------------------- 1 | variable "redirector_name" {} 2 | variable "c2_port" {} 3 | variable "c2_ip" {} 4 | 5 | variable "domain" {} 6 | 7 | variable "zone_id" {} 8 | variable "credentials" {} 9 | -------------------------------------------------------------------------------- /redirectors/go-proxy/README.md: -------------------------------------------------------------------------------- 1 | # Golang Proxy 2 | 3 | | Type | Subtype | Automated | Keep Origin IP | Decrypt | 4 | | ------- | ------------ | --------- | -------------- | ------- | 5 | | `smart` | `web server` | `no` | `yes` | `no` | 6 | 7 | ## How to 8 | 9 | ## Comments 10 | 11 | ## Resources 12 | 13 | - [pires/go-proxyproto](https://github.com/pires/go-proxyproto) 14 | - [armon/go-proxyproto](https://github.com/armon/go-proxyproto) 15 | - [racker/go-proxy-protocol](https://github.com/racker/go-proxy-protocol) 16 | - [inkel/viaproxy](https://github.com/inkel/viaproxy) 17 | - [HTTP(S) Proxy in Golang in less than 100 lines of code](https://medium.com/@mlowicki/http-s-proxy-in-golang-in-less-than-100-lines-of-code-6a51c2f2c38c) 18 | -------------------------------------------------------------------------------- /redirectors/google-cloud-functions/README.md: -------------------------------------------------------------------------------- 1 | # Google Cloud Functions 2 | 3 | | Type | Subtype | Automated | Keep Origin IP | Decrypt | 4 | | ------- | ---------- | --------- | ------------------------------- | ------- | 5 | | `smart` | `function` | `no` | `yes` (if X-Forwarded-For used) | `yes` | 6 | 7 | ## How to 8 | 9 | ## Comments 10 | 11 | ## Resources 12 | -------------------------------------------------------------------------------- /redirectors/haproxy/README.md: -------------------------------------------------------------------------------- 1 | # HAproxy 2 | 3 | | Type | Subtype | Automated | Keep Origin IP | Decrypt | 4 | | ------- | ------------ | --------- | ----------------------------- | ------- | 5 | | `smart` | `web server` | `no` | `yes` (if proxyprotocol used) | `yes` | 6 | 7 | ## How to 8 | 9 | ### Installation 10 | 11 | 1. `haproxy` is available in package repository, so for example on ubuntu/debian: 12 | 13 | ```bash 14 | sudo apt install haproxy 15 | ``` 16 | 17 | 2. Then copy the template file from `./ansible/roles/redirect_haproxy/templates/haproxy.conf.j2`, rename it `haproxy.cfg`, and copy it in `/etc/haproxy/` 18 | 3. Replace `{{ vars }}` by your values in this file. 19 | 20 | ### Launch 21 | 22 | If `haproxy` was installed using the package manager, a service is keeping it running. So you can reload it: 23 | 24 | ```bash 25 | systemctl reload haproxy.service 26 | ``` 27 | 28 | ## Comments 29 | 30 | - The given configuration file is only redirecting everything to the C2, without any filtering. Some tweaking is needed to make this method "smart". 31 | 32 | ## Resources 33 | 34 | - [haproxy.cfg adapted from outflanknl/RedELK project](https://github.com/outflanknl/RedELK/blob/master/example-data-and-configs/HAProxy/haproxy.cfg) 35 | - [d3vzer0/cnc-relay](https://github.com/d3vzer0/cnc-relay/blob/master/relay/haproxy/haproxy.cfg) 36 | -------------------------------------------------------------------------------- /redirectors/haproxy/ansible/ansible.cfg: -------------------------------------------------------------------------------- 1 | [ssh_connection] 2 | ssh_args = -o ControlMaster=auto -o ControlPersist=60s 3 | pipelining = true -------------------------------------------------------------------------------- /redirectors/haproxy/ansible/main.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | roles: 3 | - redirect_haproxy 4 | become: yes 5 | -------------------------------------------------------------------------------- /redirectors/haproxy/ansible/roles/redirect_haproxy/defaults/main.yml: -------------------------------------------------------------------------------- 1 | c2_ip: 127.0.0.1 2 | c2_port_http: 80 3 | c2_port_https: 443 4 | listenning_port_http: 80 5 | listenning_port_https: 443 6 | haproxy_conf_template: haproxy.conf.j2 7 | haproxy_config_file: /etc/haproxy/haproxy.cfg 8 | -------------------------------------------------------------------------------- /redirectors/haproxy/ansible/roles/redirect_haproxy/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: reload haproxy 2 | systemd: 3 | name: haproxy 4 | state: reloaded 5 | enabled: yes 6 | daemon_reload: yes 7 | -------------------------------------------------------------------------------- /redirectors/haproxy/ansible/roles/redirect_haproxy/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Ensure haproxy is installed 2 | apt: 3 | name: haproxy 4 | state: present 5 | 6 | - name: Copy haproxy conf 7 | template: 8 | src: "{{ haproxy_conf_template }}.j2" 9 | dest: "{{ haproxy_config_file }}" 10 | owner: root 11 | group: root 12 | mode: 0744 13 | notify: reload haproxy 14 | 15 | - name: Ensure haproxy is started and enabled on boot 16 | service: 17 | name: haproxy 18 | state: started 19 | enabled: yes 20 | -------------------------------------------------------------------------------- /redirectors/haproxy/ansible/roles/redirect_haproxy/templates/haproxy.conf.j2: -------------------------------------------------------------------------------- 1 | global 2 | log 127.0.0.1 local2 debug 3 | maxconn 2000 4 | user haproxy 5 | group haproxy 6 | 7 | defaults 8 | log global 9 | mode http 10 | #option httplog 11 | option dontlognull 12 | retries 3 13 | option redispatch 14 | timeout connect 5000 15 | timeout client 10000 16 | timeout server 10000 17 | # exact log-format setup is important for RedELK! 18 | log-format "GMT:%T frontend:%f/%H/%fi:%fp backend:%b client:%ci:%cp xforwardedfor:%[capture.req.hdr(3)] headers:%hr statuscode:%ST request:%r" 19 | 20 | # frontend name can be whatever you like 21 | #frontend www-https 22 | # option http-buffer-request 23 | # declare capture request len 40000 24 | # capture request header User-Agent len 512 25 | # capture request header Host len 512 26 | # capture request header X-Forwarded-For len 512 27 | # capture request header X-Forwarded-Proto len 512 28 | # capture request header X-Host len 512 29 | # capture request header Forwarded len 512 30 | # capture request header Via len 512 31 | # log /dev/log local2 debug 32 | # bind :::{{ listenning_port_https }} v4v6 ssl crt /etc/letsencrypt/live/haproxy.pem 33 | # reqadd X-Forwarded-Proto:\ https 34 | # acl path_cs path -m beg /dpixel 35 | # acl path_cs path -m beg /submit.php 36 | # acl path_cs path -m beg /TRAINING-BEACON 37 | # acl path_cs path_reg ^/[0-z][0-z][0-z][0-z]$ 38 | # use_backend c2-https if path_cs 39 | # default_backend decoy-www 40 | # timeout client 1m 41 | 42 | # frontend name can be whatever you like 43 | frontend www-http 44 | mode http 45 | option http-buffer-request 46 | declare capture request len 40000 47 | capture request header User-Agent len 512 48 | capture request header Host len 512 49 | capture request header X-Forwarded-For len 512 50 | capture request header X-Forwarded-Proto len 512 51 | capture request header X-Host len 512 52 | capture request header Forwarded len 512 53 | capture request header Via len 512 54 | log /dev/log local2 debug 55 | bind :::{{ listenning_port_http }} v4v6 56 | reqadd X-Forwarded-Proto:\ http 57 | acl path_cs path -m beg /dpixel 58 | acl path_cs path -m beg /submit.php 59 | acl path_cs path -m beg /TRAINING-BEACON 60 | acl path_cs path_reg ^/[0-z][0-z][0-z][0-z]$ 61 | use_backend c2-http if path_cs 62 | default_backend decoy-www 63 | timeout client 1m 64 | 65 | # backend name should start with decoy or with c2 66 | backend decoy-staticerror 67 | mode http 68 | http-request set-header Host 127.0.0.1 69 | server 127.0.0.1 127.0.0.1:8070 70 | 71 | # backend name should start with decoy or with c2 72 | backend c2-https 73 | # Insert X-Forwarded-For header to have Cobalt Strike display the proper IP address of target. Uncomment if you want this funcitonality 74 | # Remark: when using Domain Fronting/CDNs, this needs to be commented out as Cobalt Strike does not understand a double inserted X-Forwarded-For header: it will display the IP of the CDN endpoint 75 | #option forwardfor 76 | server teamserver {{ c2_ip }}:{{ c2_port_https }} check ssl verify none 77 | 78 | # backend name should start with decoy or with c2 79 | backend c2-http 80 | #option forwardfor 81 | server teamserver {{ c2_ip }}:{{ c2_port_http }} 82 | -------------------------------------------------------------------------------- /redirectors/haproxy/terraform/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.12.20" 3 | 4 | required_providers { 5 | local = "~> 1.4.0" 6 | aws = "~> 2.55.0" 7 | tls = "~> 2.1.1" 8 | } 9 | } 10 | 11 | resource "tls_private_key" "ssh" { 12 | algorithm = "RSA" 13 | rsa_bits = 4096 14 | } 15 | 16 | resource "local_file" "ssh_private_key_pem" { 17 | sensitive_content = tls_private_key.ssh.private_key_pem 18 | filename = "./ssh_keys/${var.redirector_name}" 19 | file_permission = "0600" 20 | } 21 | 22 | resource "local_file" "ssh_public_key_pem" { 23 | content = tls_private_key.ssh.public_key_openssh 24 | filename = "./ssh_keys/${var.redirector_name}.pub" 25 | file_permission = "0600" 26 | } 27 | -------------------------------------------------------------------------------- /redirectors/haproxy/terraform/outputs.tf: -------------------------------------------------------------------------------- 1 | output "aws_redirector_ip" { 2 | value = aws_instance.redirector.public_ip 3 | } 4 | 5 | output "to_ssh" { 6 | value = "ssh -i ${local_file.ssh_private_key_pem.filename} ubuntu@${aws_instance.redirector.public_ip}" 7 | } 8 | -------------------------------------------------------------------------------- /redirectors/haproxy/terraform/providers.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | AWS_ACCESS_KEY_ID = lookup(var.credentials, "AWS_ACCESS_KEY_ID", "INVALID") 3 | AWS_SECRET_ACCESS_KEY = lookup(var.credentials, "AWS_SECRET_ACCESS_KEY", "INVALID") 4 | AWS_DEFAULT_REGION = lookup(var.credentials, "AWS_DEFAULT_REGION", "eu-central-1") 5 | } 6 | 7 | provider "aws" { 8 | region = local.AWS_DEFAULT_REGION 9 | secret_key = local.AWS_SECRET_ACCESS_KEY 10 | access_key = local.AWS_ACCESS_KEY_ID 11 | skip_credentials_validation = true 12 | skip_requesting_account_id = true 13 | } 14 | 15 | provider "local" {} 16 | provider "tls" {} 17 | -------------------------------------------------------------------------------- /redirectors/haproxy/terraform/redirector.tf: -------------------------------------------------------------------------------- 1 | resource "aws_security_group" "allow_all" { 2 | name = "allow_all_${var.redirector_name}" 3 | description = "Allow all traffic" 4 | 5 | egress { 6 | from_port = 0 7 | to_port = 0 8 | protocol = "-1" 9 | cidr_blocks = ["0.0.0.0/0"] 10 | } 11 | 12 | ingress { 13 | from_port = 0 14 | to_port = 0 15 | protocol = "-1" 16 | cidr_blocks = ["0.0.0.0/0"] 17 | } 18 | } 19 | 20 | resource "aws_key_pair" "master" { 21 | key_name = var.redirector_name 22 | public_key = tls_private_key.ssh.public_key_openssh 23 | } 24 | 25 | data "aws_ami" "ubuntu" { 26 | most_recent = true 27 | 28 | filter { 29 | name = "name" 30 | values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"] 31 | } 32 | 33 | filter { 34 | name = "virtualization-type" 35 | values = ["hvm"] 36 | } 37 | 38 | owners = ["099720109477"] # Canonical 39 | } 40 | 41 | resource "aws_instance" "redirector" { 42 | tags = { 43 | Name = var.redirector_name 44 | } 45 | 46 | ami = data.aws_ami.ubuntu.id 47 | instance_type = "t2.micro" 48 | 49 | key_name = aws_key_pair.master.key_name 50 | associate_public_ip_address = true 51 | security_groups = [aws_security_group.allow_all.name] 52 | 53 | // To force waiting for the instance to be up. Cleanest way for now (https://github.com/hashicorp/terraform/issues/2811) 54 | provisioner "remote-exec" { 55 | inline = ["echo 'Instance ready!'"] 56 | 57 | connection { 58 | host = aws_instance.redirector.public_ip 59 | type = "ssh" 60 | user = "ubuntu" 61 | private_key = tls_private_key.ssh.private_key_pem 62 | } 63 | } 64 | 65 | provisioner "local-exec" { 66 | command = < 12 | iptables -t nat -A POSTROUTING -j MASQUERADE 13 | iptables -I FORWARD -j ACCEPT 14 | iptables -P FORWARD ACCEPT 15 | sysctl net.ipv4.ip_forward=1 16 | ``` 17 | 18 | :warning: Do not forget to make it persistent. Two of the possible solutions: 19 | 20 | ```bash 21 | # install iptables-persistent 22 | sudo apt-get install iptables-persistent 23 | 24 | # Save the rules 25 | sudo iptables-save > /etc/iptables/rules.v4 26 | ``` 27 | 28 | Or, for recent Ubuntu versions: 29 | 30 | ```bash 31 | # install iptables-persistent 32 | sudo apt-get install iptables-persistent 33 | 34 | # Save the rules 35 | sudo netfilter-persistent save 36 | ``` 37 | 38 | ## Comments 39 | 40 | N/A 41 | 42 | ## Resources 43 | 44 | N/A 45 | -------------------------------------------------------------------------------- /redirectors/iptables/ansible/ansible.cfg: -------------------------------------------------------------------------------- 1 | [ssh_connection] 2 | ssh_args = -o ControlMaster=auto -o ControlPersist=60s 3 | pipelining = true -------------------------------------------------------------------------------- /redirectors/iptables/ansible/main.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | roles: 3 | - redirect_iptables 4 | become: yes 5 | vars: 6 | listenning_port: 443 7 | c2_port: 443 8 | c2_ip: "127.0.0.1" -------------------------------------------------------------------------------- /redirectors/iptables/ansible/roles/redirect_method/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Ensure iptables-persistent is installed 2 | apt: 3 | name: iptables-persistent 4 | state: present 5 | 6 | - name: iptables -I INPUT -p tcp -m tcp --dport {{ listenning_port }} -j ACCEPT 7 | iptables: 8 | action: insert 9 | chain: INPUT 10 | protocol: tcp 11 | destination_port: {{ listenning_port }} 12 | match: tcp 13 | jump: ACCEPT 14 | 15 | - name: iptables -t nat -A PREROUTING -p tcp --dport {{ c2_port }} -j DNAT --to-destination {{ c2_ip }} 16 | iptables: 17 | table: nat 18 | action: append 19 | chain: PREROUTING 20 | protocol: tcp 21 | destination_port: {{ c2_port }} 22 | jump: DNAT 23 | to_destination: {{ c2_ip }} 24 | 25 | - name: iptables -t nat -A POSTROUTING -j MASQUERADE 26 | iptables: 27 | table: nat 28 | action: append 29 | chain: POSTROUTING 30 | jump: MASQUERADE 31 | 32 | - name: iptables -I FORWARD -j ACCEPT 33 | iptables: 34 | action: insert 35 | chain: FORWARD 36 | jump: ACCEPT 37 | 38 | - name: iptables -P FORWARD ACCEPT 39 | iptables: 40 | chain: FORWARD 41 | policy: ACCEPT 42 | 43 | - name: Allow ip forward 44 | sysctl: 45 | name: net.ipv4.ip_forward 46 | value: '1' 47 | sysctl_set: yes 48 | state: present 49 | 50 | - name : Save rules to survive reboot 51 | command: netfilter-persistent save 52 | 53 | -------------------------------------------------------------------------------- /redirectors/iptables/terraform/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.12.20" 3 | 4 | required_providers { 5 | local = "~> 1.4.0" 6 | aws = "~> 2.55.0" 7 | tls = "~> 2.1.1" 8 | } 9 | } 10 | 11 | resource "tls_private_key" "ssh" { 12 | algorithm = "RSA" 13 | rsa_bits = 4096 14 | } 15 | 16 | resource "local_file" "ssh_private_key_pem" { 17 | sensitive_content = tls_private_key.ssh.private_key_pem 18 | filename = "./ssh_keys/${var.redirector_name}" 19 | file_permission = "0600" 20 | } 21 | 22 | resource "local_file" "ssh_public_key_pem" { 23 | content = tls_private_key.ssh.public_key_openssh 24 | filename = "./ssh_keys/${var.redirector_name}.pub" 25 | file_permission = "0600" 26 | } 27 | -------------------------------------------------------------------------------- /redirectors/iptables/terraform/outputs.tf: -------------------------------------------------------------------------------- 1 | output "redirector_ip" { 2 | value = aws_instance.redirector.public_ip 3 | } 4 | 5 | output "to_connect_with_ssh" { 6 | value = "ssh -i ${local_file.ssh_private_key_pem.filename} ubuntu@${aws_instance.redirector.public_ip}" 7 | } 8 | -------------------------------------------------------------------------------- /redirectors/iptables/terraform/providers.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | AWS_ACCESS_KEY_ID = lookup(var.credentials, "AWS_ACCESS_KEY_ID", "INVALID") 3 | AWS_SECRET_ACCESS_KEY = lookup(var.credentials, "AWS_SECRET_ACCESS_KEY", "INVALID") 4 | AWS_DEFAULT_REGION = lookup(var.credentials, "AWS_DEFAULT_REGION", "eu-central-1") 5 | } 6 | 7 | provider "aws" { 8 | region = local.AWS_DEFAULT_REGION 9 | secret_key = local.AWS_SECRET_ACCESS_KEY 10 | access_key = local.AWS_ACCESS_KEY_ID 11 | skip_credentials_validation = true 12 | skip_requesting_account_id = true 13 | } 14 | 15 | provider "local" {} 16 | provider "tls" {} 17 | -------------------------------------------------------------------------------- /redirectors/iptables/terraform/redirector.tf: -------------------------------------------------------------------------------- 1 | resource "aws_security_group" "allow_all" { 2 | name = "allow_all_${var.redirector_name}" 3 | description = "Allow all traffic" 4 | 5 | egress { 6 | from_port = 0 7 | to_port = 0 8 | protocol = "-1" 9 | cidr_blocks = ["0.0.0.0/0"] 10 | } 11 | 12 | ingress { 13 | from_port = 0 14 | to_port = 0 15 | protocol = "-1" 16 | cidr_blocks = ["0.0.0.0/0"] 17 | } 18 | } 19 | 20 | resource "aws_key_pair" "master" { 21 | key_name = var.redirector_name 22 | public_key = tls_private_key.ssh.public_key_openssh 23 | } 24 | 25 | data "aws_ami" "ubuntu" { 26 | most_recent = true 27 | 28 | filter { 29 | name = "name" 30 | values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"] 31 | } 32 | 33 | filter { 34 | name = "virtualization-type" 35 | values = ["hvm"] 36 | } 37 | 38 | owners = ["099720109477"] # Canonical 39 | } 40 | 41 | resource "aws_instance" "redirector" { 42 | tags = { 43 | Name = var.redirector_name 44 | } 45 | 46 | ami = data.aws_ami.ubuntu.id 47 | instance_type = "t2.micro" 48 | 49 | key_name = aws_key_pair.master.key_name 50 | associate_public_ip_address = true 51 | security_groups = [aws_security_group.allow_all.name] 52 | 53 | // To force waiting for the instance to be up. Cleanest way for now (https://github.com/hashicorp/terraform/issues/2811) 54 | provisioner "remote-exec" { 55 | inline = ["echo 'Instance ready!'"] 56 | 57 | connection { 58 | host = aws_instance.redirector.public_ip 59 | type = "ssh" 60 | user = "ubuntu" 61 | private_key = tls_private_key.ssh.private_key_pem 62 | } 63 | } 64 | 65 | provisioner "local-exec" { 66 | command = <:443 21 | ``` 22 | 23 | To make it persistent (survive reboot), you can add a cron job: 24 | 25 | ```bash 26 | cron -e 27 | @reboot socat TCP4-LISTEN:443,fork TCP4::443 & 28 | ``` 29 | 30 | ## Comments 31 | 32 | - There is no daemon mode builtin, thus the need of a `screen`/`tmux` 33 | - :warning: It can getting slow with time or large amounts of traffic 34 | 35 | ## Resources 36 | 37 | Red Team - Development and operations, by Joe Vest & James Tubberville 38 | -------------------------------------------------------------------------------- /redirectors/socat/ansible/ansible.cfg: -------------------------------------------------------------------------------- 1 | [ssh_connection] 2 | ssh_args = -o ControlMaster=auto -o ControlPersist=60s 3 | pipelining = true -------------------------------------------------------------------------------- /redirectors/socat/ansible/main.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | roles: 3 | - redirect_socat 4 | become: yes 5 | vars: 6 | listenning_port: 443 7 | c2_port: 443 8 | c2_ip: "127.0.0.1" 9 | -------------------------------------------------------------------------------- /redirectors/socat/ansible/roles/redirect_socat/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: reboot 2 | reboot: -------------------------------------------------------------------------------- /redirectors/socat/ansible/roles/redirect_socat/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Ensure socat is installed 2 | apt: 3 | name: socat 4 | state: present 5 | 6 | - name: Get socat version 7 | command: socat -V 8 | register: socat_version_result 9 | 10 | - name: Ensure log file exists 11 | file: 12 | path: /var/log/socat.log 13 | state: touch 14 | mode: '0644' 15 | 16 | - name: Set cronjob to launch socat at reboot 17 | cron: 18 | name: "Redirector" 19 | special_time: reboot 20 | job: "socat -lf /var/log/socat.log TCP4-LISTEN:{{ listenning_port }},fork TCP4:{{ c2_ip }}:{{ c2_ip }} &" 21 | notify: reboot 22 | 23 | 24 | - name : Check if socat is running 25 | command: ps aux | awk '{print $11}' | grep -e "^socat" 26 | register: socat_running 27 | ignore_errors: True 28 | 29 | - name: Launch socat if not already running 30 | shell: socat -lf /var/log/socat.log TCP4-LISTEN:{{ listenning_port }},fork TCP4:{{ c2_ip }}:{{ c2_ip 2>&1 & 31 | when: socat_running is failed 32 | -------------------------------------------------------------------------------- /redirectors/socat/terraform/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.12.20" 3 | 4 | required_providers { 5 | local = "~> 1.4.0" 6 | aws = "~> 2.55.0" 7 | tls = "~> 2.1.1" 8 | } 9 | } 10 | 11 | resource "tls_private_key" "ssh" { 12 | algorithm = "RSA" 13 | rsa_bits = 4096 14 | } 15 | 16 | resource "local_file" "ssh_private_key_pem" { 17 | sensitive_content = tls_private_key.ssh.private_key_pem 18 | filename = "./ssh_keys/${var.redirector_name}" 19 | file_permission = "0600" 20 | } 21 | 22 | resource "local_file" "ssh_public_key_pem" { 23 | content = tls_private_key.ssh.public_key_openssh 24 | filename = "./ssh_keys/${var.redirector_name}.pub" 25 | file_permission = "0600" 26 | } 27 | -------------------------------------------------------------------------------- /redirectors/socat/terraform/outputs.tf: -------------------------------------------------------------------------------- 1 | output "aws_redirector_ip" { 2 | value = aws_instance.redirector.public_ip 3 | } 4 | 5 | output "to_ssh" { 6 | value = "ssh -i ${local_file.ssh_private_key_pem.filename} ubuntu@${aws_instance.redirector.public_ip}" 7 | } 8 | -------------------------------------------------------------------------------- /redirectors/socat/terraform/providers.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | AWS_ACCESS_KEY_ID = lookup(var.credentials, "AWS_ACCESS_KEY_ID", "INVALID") 3 | AWS_SECRET_ACCESS_KEY = lookup(var.credentials, "AWS_SECRET_ACCESS_KEY", "INVALID") 4 | AWS_DEFAULT_REGION = lookup(var.credentials, "AWS_DEFAULT_REGION", "eu-central-1") 5 | } 6 | 7 | provider "aws" { 8 | region = local.AWS_DEFAULT_REGION 9 | secret_key = local.AWS_SECRET_ACCESS_KEY 10 | access_key = local.AWS_ACCESS_KEY_ID 11 | skip_credentials_validation = true 12 | skip_requesting_account_id = true 13 | } 14 | 15 | provider "local" {} 16 | provider "tls" {} 17 | -------------------------------------------------------------------------------- /redirectors/socat/terraform/redirector.tf: -------------------------------------------------------------------------------- 1 | resource "aws_security_group" "allow_all" { 2 | name = "allow_all_${var.redirector_name}" 3 | description = "Allow all traffic" 4 | 5 | egress { 6 | from_port = 0 7 | to_port = 0 8 | protocol = "-1" 9 | cidr_blocks = ["0.0.0.0/0"] 10 | } 11 | 12 | ingress { 13 | from_port = 0 14 | to_port = 0 15 | protocol = "-1" 16 | cidr_blocks = ["0.0.0.0/0"] 17 | } 18 | } 19 | 20 | resource "aws_key_pair" "master" { 21 | key_name = var.redirector_name 22 | public_key = tls_private_key.ssh.public_key_openssh 23 | } 24 | 25 | data "aws_ami" "ubuntu" { 26 | most_recent = true 27 | 28 | filter { 29 | name = "name" 30 | values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"] 31 | } 32 | 33 | filter { 34 | name = "virtualization-type" 35 | values = ["hvm"] 36 | } 37 | 38 | owners = ["099720109477"] # Canonical 39 | } 40 | 41 | resource "aws_instance" "redirector" { 42 | tags = { 43 | Name = var.redirector_name 44 | } 45 | 46 | ami = data.aws_ami.ubuntu.id 47 | instance_type = "t2.micro" 48 | 49 | key_name = aws_key_pair.master.key_name 50 | associate_public_ip_address = true 51 | security_groups = [aws_security_group.allow_all.name] 52 | 53 | // To force waiting for the instance to be up. Cleanest way for now (https://github.com/hashicorp/terraform/issues/2811) 54 | provisioner "remote-exec" { 55 | inline = ["echo 'Instance ready!'"] 56 | 57 | connection { 58 | host = aws_instance.redirector.public_ip 59 | type = "ssh" 60 | user = "ubuntu" 61 | private_key = tls_private_key.ssh.private_key_pem 62 | } 63 | } 64 | 65 | provisioner "local-exec" { 66 | command = <@ -R *:443:localhost:443 27 | ``` 28 | 29 | ## Comments 30 | 31 | - To redirect another port in the same SSH session, add another `-R *::localhost:` block to the command line. 32 | 33 | ## Resources 34 | 35 | - [Reverse SSH Redirectors](https://blog.smallsec.ca/2018/06/16/reverse-ssh-redirectors/) -------------------------------------------------------------------------------- /redirectors/ssh/ansible/main.yml: -------------------------------------------------------------------------------- 1 | - hosts: all 2 | roles: 3 | - redirect_ssh 4 | become: yes -------------------------------------------------------------------------------- /redirectors/ssh/ansible/roles/redirect_ssh/handlers/main.yml: -------------------------------------------------------------------------------- 1 | - name: reload ssh 2 | become: yes 3 | service: 4 | name: sshd 5 | state: reloaded -------------------------------------------------------------------------------- /redirectors/ssh/ansible/roles/redirect_ssh/tasks/main.yml: -------------------------------------------------------------------------------- 1 | - name: Ensure anyone can connect to forwarded ports 2 | lineinfile: 3 | path: /etc/ssh/sshd_config 4 | regexp: '^# GatewayPorts' 5 | line: GatewayPorts yes 6 | notify: reload ssh 7 | 8 | - name: Allow both local and remote (to external machines) port forwards 9 | lineinfile: 10 | path: /etc/ssh/sshd_config 11 | regexp: '^# AllowTcpForwarding' 12 | line: AllowTcpForwarding yes 13 | notify: reload ssh -------------------------------------------------------------------------------- /redirectors/ssh/terraform/main.tf: -------------------------------------------------------------------------------- 1 | terraform { 2 | required_version = ">= 0.12.20" 3 | 4 | required_providers { 5 | local = "~> 1.4.0" 6 | aws = "~> 2.55.0" 7 | tls = "~> 2.1.1" 8 | } 9 | } 10 | 11 | resource "tls_private_key" "ssh" { 12 | algorithm = "RSA" 13 | rsa_bits = 4096 14 | } 15 | 16 | resource "local_file" "ssh_private_key_pem" { 17 | sensitive_content = tls_private_key.ssh.private_key_pem 18 | filename = "./ssh_keys/${var.redirector_name}" 19 | file_permission = "0600" 20 | } 21 | 22 | resource "local_file" "ssh_public_key_pem" { 23 | content = tls_private_key.ssh.public_key_openssh 24 | filename = "./ssh_keys/${var.redirector_name}.pub" 25 | file_permission = "0600" 26 | } 27 | -------------------------------------------------------------------------------- /redirectors/ssh/terraform/outputs.tf: -------------------------------------------------------------------------------- 1 | output "redirector_ip" { 2 | value = aws_instance.redirector.public_ip 3 | } 4 | 5 | output "to_connect_with_ssh" { 6 | value = "ssh -i ${local_file.ssh_private_key_pem.filename} ubuntu@${aws_instance.redirector.public_ip}" 7 | } 8 | 9 | output "to_redirect" { 10 | value = "You still have to connect with SSH on the instance with arguments specified in the READMD.md to create the redirection." 11 | } 12 | -------------------------------------------------------------------------------- /redirectors/ssh/terraform/providers.tf: -------------------------------------------------------------------------------- 1 | locals { 2 | AWS_ACCESS_KEY_ID = lookup(var.credentials, "AWS_ACCESS_KEY_ID", "INVALID") 3 | AWS_SECRET_ACCESS_KEY = lookup(var.credentials, "AWS_SECRET_ACCESS_KEY", "INVALID") 4 | AWS_DEFAULT_REGION = lookup(var.credentials, "AWS_DEFAULT_REGION", "eu-central-1") 5 | } 6 | 7 | provider "aws" { 8 | region = local.AWS_DEFAULT_REGION 9 | secret_key = local.AWS_SECRET_ACCESS_KEY 10 | access_key = local.AWS_ACCESS_KEY_ID 11 | skip_credentials_validation = true 12 | skip_requesting_account_id = true 13 | } 14 | 15 | provider "local" {} 16 | provider "tls" {} 17 | -------------------------------------------------------------------------------- /redirectors/ssh/terraform/redirector.tf: -------------------------------------------------------------------------------- 1 | resource "aws_security_group" "allow_all" { 2 | name = "allow_all_${var.redirector_name}" 3 | description = "Allow all traffic" 4 | 5 | egress { 6 | from_port = 0 7 | to_port = 0 8 | protocol = "-1" 9 | cidr_blocks = ["0.0.0.0/0"] 10 | } 11 | 12 | ingress { 13 | from_port = 0 14 | to_port = 0 15 | protocol = "-1" 16 | cidr_blocks = ["0.0.0.0/0"] 17 | } 18 | } 19 | 20 | resource "aws_key_pair" "master" { 21 | key_name = var.redirector_name 22 | public_key = tls_private_key.ssh.public_key_openssh 23 | } 24 | 25 | data "aws_ami" "ubuntu" { 26 | most_recent = true 27 | 28 | filter { 29 | name = "name" 30 | values = ["ubuntu/images/hvm-ssd/ubuntu-bionic-18.04-amd64-server-*"] 31 | } 32 | 33 | filter { 34 | name = "virtualization-type" 35 | values = ["hvm"] 36 | } 37 | 38 | owners = ["099720109477"] # Canonical 39 | } 40 | 41 | resource "aws_instance" "redirector" { 42 | tags = { 43 | Name = var.redirector_name 44 | } 45 | 46 | ami = data.aws_ami.ubuntu.id 47 | instance_type = "t2.micro" 48 | 49 | key_name = aws_key_pair.master.key_name 50 | associate_public_ip_address = true 51 | security_groups = [aws_security_group.allow_all.name] 52 | 53 | // To force waiting for the instance to be up. Cleanest way for now (https://github.com/hashicorp/terraform/issues/2811) 54 | provisioner "remote-exec" { 55 | inline = ["echo 'Instance ready!'"] 56 | 57 | connection { 58 | host = aws_instance.redirector.public_ip 59 | type = "ssh" 60 | user = "ubuntu" 61 | private_key = tls_private_key.ssh.private_key_pem 62 | } 63 | } 64 | 65 | provisioner "local-exec" { 66 | command = <