Skip to content

schubergphilis/terraform-aws-mcaf-network-firewall

Repository files navigation

terraform-aws-mcaf-network-firewall

Terraform module to setup and manage a Network Firewall, it supports the following features:

  • Filter IP traffic, allow/deny network traffic based on IP source/destination, port and protocol (5-tuple).
  • Filter HTTP(S) traffic, allow/deny access to websites based on FQDN.
  • IDS/IPS, deny traffic based on AWS managed rulesets.

Filtering

Below are some characteristics of this firewall module:

  • The firewall operates with an implicit deny, meaning that all traffic will be dropped unless an IP or FQDN rule allows it.

Order of evaluation

In case you're using IP, FQDN and IDS/IPS rules together the default order of evaluation is as follows:

  • IDS/IPS rules
  • FQDN rules
  • IP rules

This can be changed by altering the ip_rule_group_priority, fqdn_rule_group_priority for IP and FQDN rules. And the various priority variables for the named IDS/IPS managed rule sets.

FQDN rules

The firewall can filter web traffic based on FQDN's. This is done by inspecting the TLS 'Server Name Indication (SNI)' extension in case of encrypted traffic and the HTTP 'HOST_HEADER' in case of unencrypted web traffic.

Matching

  • example.com only matches example.com
  • abc.example.com only matches abc.example.com
  • .example.com matches example.com and all subdomains of example.com, such as www.example.com, abc.example.com.
  fqdn_rules = {
    blocked_domains = {
      action    = "DROP"
      fqdns     = ["icanhazip.com", "parrot.live", "www.nu.nl"]
      source_ip = ["10.0.1.0/24", "10.0.2.0/24"]
      priority  = 1
    }

    allow_essential_sites = {
      action    = "PASS"
      fqdns     = ["parrot.live", "www.nu.nl"]
      source_ip = ["10.0.0.0/16"]
      priority  = 2
    }
  }

IP (5-tuple) rules

Filtering of IP traffic can be done by adding rules to the ip_rules variable. The order of the rules is determined by setting the priority variable in every rule.

  ip_rules = {
    google_dns = {
      action           = "PASS"
      destination_ip   = ["8.8.8.8", "8.8.4.4"]
      destination_port = ["53"]
      direction        = "FORWARD"
      priority         = 1
      protocol         = "UDP"
      source_ip        = ["ANY"]
      source_port      = ["ANY"]
    }

    ping_cloudflare_resolvers = {
      action           = "PASS"
      destination_ip   = ["1.1.1.1", "1.0.0.1"]
      destination_port = ["ANY"]
      direction        = "FORWARD"
      priority         = 2
      protocol         = "ICMP"
      source_ip        = ["10.0.1.0/24", "10.0.2.0/24"]
      source_port      = ["ANY"]
    }

    drop_malicious_destination = {
      action           = "DROP"
      destination_ip   = ["1.2.3.4"]
      destination_port = ["ANY"]
      direction        = "FORWARD"
      priority         = 3
      protocol         = "IP"
      source_ip        = ["ANY"]
      source_port      = ["ANY"]
    }

    allow_smtp = {
      action           = "PASS"
      destination_ip   = ["ANY"]
      destination_port = ["25"]
      direction        = "FORWARD"
      priority         = 4
      protocol         = "SMTP"
      source_ip        = ["10.0.1.10/32"]
      source_port      = ["ANY"]
    }
  }

IDS/IPS

AWS Network Firewall can be used with AWS managed rules for IDS/IPS functionality.

The managed_rule_groups variable contains the list of rule groups that can be enabled. Setting drop_mode = true switches the rule group from IDS mode (detection only) to IPS mode (prevention, dropping those packets).

  managed_rule_groups = {
    AbusedLegitBotNetCommandAndControlDomains = { enabled = true }
    MalwareDomains                            = { enabled = true, drop_mode = true }
    ThreatSignaturesBotnetWeb                 = { enabled = true }
  }

Requirements

Name Version
terraform >= 1.3
aws >= 5.10.0

Providers

Name Version
aws >= 5.10.0

Modules

No modules.

Resources

Name Type
aws_cloudwatch_log_group.default resource
aws_networkfirewall_firewall.default resource
aws_networkfirewall_firewall_policy.default resource
aws_networkfirewall_logging_configuration.default resource
aws_networkfirewall_rule_group.fqdn_rules resource
aws_networkfirewall_rule_group.ip_rules resource
aws_region.default data source

Inputs

Name Description Type Default Required
kms_key_arn The ARN of the KMS key used to encrypt the cloudwatch log group and network firewall string n/a yes
name Name of the firewall instance string n/a yes
subnet_id List of subnet IDs onto which the network firewall will be deployed list(string) n/a yes
vpc_id ID of the VPC the network firewall is deployed in string n/a yes
cloudwatch_logging_configuration Cloudwatch logs configuration
object({
alert_logs = optional(object({
enabled = optional(bool, true)
log_group_prefix = optional(string, "/platform/")
retention_in_days = optional(number, 90)
}), {})
flow_logs = optional(object({
enabled = optional(bool, true)
log_group_prefix = optional(string, "/platform/")
retention_in_days = optional(number, 90)
}), {})
})
{} no
delete_protection A boolean flag indicating whether it is possible to delete the firewall bool true no
description Description of the firewall instance string "AWS Network Firewall" no
fqdn_rule_group_priority Priority of the rule group number 30 no
fqdn_rules Map with L7 egress firewall rules
map(object({
action = string
fqdns = list(string)
priority = number
source_ip = list(string)
}))
{} no
fqdn_rules_capacity Capacity of the rule group number 1000 no
home_net List of CIDRs to override the HOME_NET variable with list(string) [] no
ip_rule_group_priority Priority of the rule group number 40 no
ip_rules Map with L4 firewall rules
map(object({
action = string
destination_ip = list(string)
destination_port = list(string)
direction = string
priority = number
protocol = string
source_ip = list(string)
source_port = list(string)
}))
{} no
ip_rules_capacity Capacity of the rule group number 1000 no
managed_rule_groups Map with AWS managed ruleset options
object({
AbusedLegitBotNetCommandAndControlDomains = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 1)
}), {})
AbusedLegitMalwareDomains = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 2)
}), {})
BotNetCommandAndControlDomains = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 3)
}), {})
MalwareDomains = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 4)
}), {})
ThreatSignaturesBotnet = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 5)
}), {})
ThreatSignaturesBotnetWeb = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 6)
}), {})
ThreatSignaturesBotnetWindows = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 7)
}), {})
ThreatSignaturesDoS = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 8)
}), {})
ThreatSignaturesEmergingEvents = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 9)
}), {})
ThreatSignaturesExploits = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 10)
}), {})
ThreatSignaturesFUP = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 11)
}), {})
ThreatSignaturesIOC = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 12)
}), {})
ThreatSignaturesMalwareCoinmining = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 13)
}), {})
ThreatSignaturesMalwareMobile = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 14)
}), {})
ThreatSignaturesMalware = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 16)
}), {})
ThreatSignaturesMalwareWeb = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 17)
}), {})
ThreatSignaturesPhishing = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 18)
}), {})
ThreatSignaturesScanners = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 19)
}), {})
ThreatSignaturesSuspect = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 20)
}), {})
ThreatSignaturesWebAttacks = optional(object({
enabled = optional(bool, false)
drop_mode = optional(bool, false)
priority = optional(number, 21)
}), {})
})
{} no
tags Map of tags to set on Terraform created resources map(string) {} no

Outputs

Name Description
cloudwatch_log_group_arn Map of CloudWatch log group type and arn when atleast one log type is enabled
cloudwatch_log_group_name Map of CloudWatch log group type and name when atleast one log type is enabled
firewall_status Information about the current status of the firewall.