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.
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.
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.
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.
example.com
only matchesexample.com
abc.example.com
only matchesabc.example.com
.example.com
matchesexample.com
and all subdomains ofexample.com
, such aswww.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
}
}
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"]
}
}
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 }
}
Name | Version |
---|---|
terraform | >= 1.3 |
aws | >= 5.10.0 |
Name | Version |
---|---|
aws | >= 5.10.0 |
No modules.
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 |
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({ |
{} |
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({ |
{} |
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({ |
{} |
no |
ip_rules_capacity | Capacity of the rule group | number |
1000 |
no |
managed_rule_groups | Map with AWS managed ruleset options | object({ |
{} |
no |
tags | Map of tags to set on Terraform created resources | map(string) |
{} |
no |
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. |