- Knowledge Base
- Amazon Web Services
- Amazon Route 53
- Sender Policy Framework In Use
Ensure that your Amazon Route 53 hosted zone has a TXT record that implements the Sender Policy Framework (SPF) for the corresponding MX record available within the DNS zone. The Sender Policy Framework enables your registered domains to publicly state which mail servers are authorized to send emails on their behalf.
This rule can help you with the following compliance standards:
- NIST4
For further details on compliance standards supported by TrendAI Vision One™ Cloud Risk Management, see here.
Implementing Sender Policy Framework (SPF) for your Amazon Route 53 domain names will help you detect and stop email address spoofing in order to reduce spam and increase your domains trustworthiness.
Note: This rule assumes that your Amazon Route 53 hosted zones are using MX records for declaring the server(s) that should handle email delivery.
Audit
To determine if your Amazon Route 53 hosted zone contain a TXT DNS record with SPF information for the corresponding MX record, perform the following actions:
Using AWS Console
-
Sign in to the AWS Management Console.
-
Navigate to Amazon Route 53 console at https://console.aws.amazon.com/route53/.
-
In the main navigation panel, under Dashboard, click Hosted zones.
-
Click on the domain name of the Route 53 hosted zone that you want to examine.
-
In the Records section, select TXT from the Type dropdown menu to return all the TXT DNS records created for the selected hosted zone (domain). If this filtering process does not return any TXT records, the selected Amazon Route 53 domain does not use TXT DNS records to implement the Sender Policy Framework (SPF) for the corresponding MX records. If the filtering process returns one or more TXT records, check each record value listed in Value/Route traffic to column. If the record value does not contain v=spf1 (e.g. "v=spf1 ip4:192.168.0.5/16 -all"), the selected domain is not using the Sender Policy Framework (SPF) for the corresponding MX records.
-
Repeat steps no. 4 and 5 for each DNS hosted zone created with Amazon Route 53 service.
Using AWS CLI
-
Run list-hosted-zones command (OSX/Linux/UNIX) to list the ID of each Amazon Route 53 hosted zone created in your AWS cloud account:
aws route53 list-hosted-zones --query "HostedZones[*].Id"
-
The command output should return an array with the requested hosted zone IDs:
[ "/hostedzone/ABCD1234ABCD1234ABCD", "/hostedzone/ABCDABCDABCDABCDABCD" ]
-
Run list-resource-record-sets command (OSX/Linux/UNIX) using the ID of the Route 53 hosted zone that you want to examine as the identifier parameter and custom query filters to list the TXT DNS records created for the selected hosted zone (domain):
aws route53 list-resource-record-sets --hosted-zone-id "/hostedzone/ABCD1234ABCD1234ABCD" --query "ResourceRecordSets[?Type == 'TXT']"
-
The command output should return an array with all the TXT DNS record sets created for the specified Amazon Route 53 hosted zone:
-
If the array returned as output is empty, i.e. [], the selected domain name does not use TXT DNS records to implement Sender Policy Framework (SPF) for the corresponding MX records:
[]
-
If the command output returns an array with one or more TXT DNS records, as shown in the example below, check the value configured for the "Value"property (highlighted). If this value does not contain v=spf1 (for example, "v=spf1 ip4:192.168.0.5/16 -all"), the selected domain name is not using the Sender Policy Framework (SPF) for the corresponding MX records, therefore the Route 53 domain is not SPF-protected:
[ { "ResourceRecords": [ { "Value": "\"google-site-verification=1234-abcd-1234-abcd\"" } ], "Type": "TXT", "Name": "example.com.", "TTL": 300 } ] -
Repeat steps no. 3 and 4 for each DNS hosted zone created with Amazon Route 53 service within your AWS account.
Remediation / Resolution
To implement Sender Policy Framework (SPF) for all the corresponding MX records within your hosted zones using Amazon Route 53 TXT DNS records, perform the following operations:
Using AWS CloudFormation
-
CloudFormation template (JSON):
{ "AWSTemplateFormatVersion": "2010-09-09", "Resources": { "EC2Instance": { "Type": "AWS::EC2::Instance", "Properties": { "ImageId": "ami-0123456789abcdef0", "InstanceType": "c5.xlarge", "KeyName": "cc-ssh-key", "SubnetId": "subnet-0123456789abcdefa", "SecurityGroupIds": "sg-0123456789abcdef1" } }, "Route53HostedZone": { "Type": "AWS: : Route53: : HostedZone", "Properties": { "HostedZoneConfig": { "Comment": "Route53 public hosted zone for domain.com" }, "Name": "domain.com", "HostedZoneTags": [ { "Key": "Owner", "Value": "IT" } ] } }, "ARecord": { "Type": "AWS::Route53::RecordSet", "Properties": { "HostedZoneName": { "Ref": "Route53HostedZone" }, "Name": "www.domain.com", "Type": "A", "TTL": "300", "ResourceRecords": [ { "Fn::GetAtt": [ "EC2Instance", "PublicIp" ] } ] } }, "SPFRecord": { "Type": "AWS::Route53::RecordSet", "Properties": { "HostedZoneName": { "Ref": "Route53HostedZone" }, "Name": "www.domain.com", "Type": "TXT", "TTL": "3600", "ResourceRecords": [ "v=spf1 include:_spf.google.com ~all" ] } } } } -
CloudFormation template (YAML):
AWSTemplateFormatVersion: '2010-09-09' Resources: EC2Instance: Type: AWS::EC2::Instance Properties: ImageId: ami-0123456789abcdef0 InstanceType: c5.xlarge KeyName: cc-ssh-key SubnetId: subnet-0123456789abcdefa SecurityGroupIds: sg-0123456789abcdef1 Route53HostedZone: Type: 'AWS: : Route53: : HostedZone' Properties: HostedZoneConfig: Comment: Route53 public hosted zone for domain.com Name: domain.com HostedZoneTags: - Key: Owner Value: IT ARecord: Type: AWS::Route53::RecordSet Properties: HostedZoneName: !Ref 'Route53HostedZone' Name: www.domain.com Type: A TTL: '3600' ResourceRecords: - !GetAtt 'EC2Instance.PublicIp' SPFRecord: Type: AWS::Route53::RecordSet Properties: HostedZoneName: !Ref 'Route53HostedZone' Name: www.domain.com Type: TXT TTL: '3600' ResourceRecords: - v=spf1 include:_spf.google.com ~all
Using Terraform (AWS Provider)
-
Terraform configuration file (.tf):
terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 4.0" } } required_version = ">= 0.14.9" } provider "aws" { profile = "default" region = "us-east-1" } resource "aws_instance" "ec2-instance" { ami = "ami-0123456789abcdef0" instance_type = "c5.xlarge" key_name = "cc-ssh-key" subnet_id = "subnet-0123456789abcdefa" vpc_security_group_ids = ["sg-0123456789abcdef1"] } resource "aws_eip" "elastic-ip" { instance = aws_instance.ec2-instance.id domain = "vpc" } resource "aws_route53_zone" "route53-hosted-zone" { name = "domain.com" comment = "Route53 public hosted zone for domain.com" tags = { Owner = "IT" } } resource "aws_route53_record" "a-record" { zone_id = aws_route53_zone.route53-hosted-zone.zone_id name = "www.domain.com" type = "A" ttl = "300" records = [aws_eip.elastic-ip.public_ip] } resource "aws_route53_record" "spf-record" { zone_id = aws_route53_zone.route53-hosted-zone.zone_id name = "www.domain.com" type = "TXT" ttl = "3600" records = [ "v=spf1 include:_spf.google.com ~all" ] }
Using AWS Console
-
Sign in to the AWS Management Console.
-
Navigate to Amazon Route 53 console at https://console.aws.amazon.com/route53/.
-
In the main navigation panel, under Dashboard, click Hosted zones.
-
Click on the domain name of the hosted zone that you want to reconfigure.
-
In the Records section, choose Create recordto initiate the TXT DNS record setup process, then perform the following actions:
- For Record name, leave the field blank to route traffic for the name of the domain.
- For Record type, select TXT – Used to verify email senders and for application-specific values.
- For Value, enter the required SPF value, for example "v=spf1 include:_spf.google.com ~all". If you don't use Google mail servers, replace include:_spf.google.com with your mail server hostame/IPv4 address, e.g. "v=spf1 ip4:192.168.0.5/16 -all".
- For TTL (seconds), enter a value of 3600 as Time to Live (TTL) value (i.e. the amount of time, in seconds, that you want DNS recursive resolvers to cache information about this record).
- For Routing policy dropdown list, choose Simple routing. The routing policy lets you choose how Amazon Route 53 routes traffic to your resources.
- Choose Create records to create a new TXT DNS record that implements the Sender Policy Framework (SPF) for the corresponding MX record.
-
Repeat steps no. 4 and 5 to implement the Sender Policy Framework (SPF) for each Amazon Route 53 domain name with corresponding MX records.
Using AWS CLI
-
To define the required SPF TXT-based record set and add it to your DNS hosted zone, you must create an Amazon Route 53 change file, declare the new DNS record set, and save the record definition to a JSON file named spf-txt-record-set.json. The following example describes a TXT record definition that implements the Sender Policy Framework (SPF) for a domain name called example.com, using Google mail servers as servers that are allowed to send mail for the specified domain:
{ "Comment": "SPF TXT-based record set for example.com domain", "Changes": [ { "Action": "CREATE", "ResourceRecordSet": { "Name": "example.com.", "Type": "TXT", "TTL": 3600, "ResourceRecords": [ { "Value": "\"v=spf1 include:_spf.google.com ~all\"" } ] } } ] } -
Run change-resource-record-sets command (OSX/Linux/UNIX) using the ID of the DNS hosted zone that you want to reconfigure as the identifier parameter and the Amazon Route 53 change file defined at the previous step (i.e. spf-txt-record-set.json) to add the new TXT DNS record that implement the Sender Policy Framework (SPF) to the selected hosted zone:
aws route53 change-resource-record-sets --hosted-zone-id "/hostedzone/ABCD1234ABCD1234ABCD" --change-batch file://spf-txt-record-set.json
-
The command output should return the metadata for the new DNS record set (including the ID of the change file used – highlighted):
{ "ChangeInfo": { "Status": "PENDING", "Comment": "SPF TXT-based record set for example.com domain", "SubmittedAt": "2020-08-11T15:00:00.000Z", "Id": "/change/ABCDABCDABCDABCDABCD" } } -
Run get-change command (OSX/Linux/UNIX) using the ID of the Route 53 change file returned at the previous step as the identifier parameter, to describe the status of the newly created record set:
aws route53 get-change --id "/change/ABCDABCDABCDABCDABCD"
-
The command output should return the current status of the DNS record batch request. The current status should be INSYNC, which indicates that the change was fully propagated to all Amazon Route 53 DNS server nodes:
{ "ChangeInfo": { "Status": "INSYNC", "Comment": "SPF TXT-based record set for example.com domain", "SubmittedAt": "2021-08-12T15:00:00.000Z", "Id": "/change/ABCDABCDABCDABCDABCD" } } -
Repeat steps no. 1 – 5 to implement the Sender Policy Framework (SPF) for each Amazon Route 53 domain name with corresponding MX records.
References
- AWS Documentation
- Amazon Route 53 FAQs
- What is Amazon Route 53?
- Working with public hosted zones
- Working with records
- Creating records by using the Amazon Route 53 console
- Supported DNS record types
- AWS Command Line Interface (CLI) Documentation
- route53
- list-hosted-zones
- list-resource-record-sets
- change-resource-record-sets
- get-change