AWS Security Blog
How to control non-HTTP and non-HTTPS traffic to a DNS domain with AWS Network Firewall and AWS Lambda
December 7, 2022: We added a caveat to the solution, for those using a traffic steering mechanism, in this post.
Security and network administrators can control outbound access from a virtual private cloud (VPC) to specific destinations by using a service like AWS Network Firewall. You can use stateful rule groups to control outbound access to domains for HTTP and HTTPS by default in Network Firewall. In this post, we’ll walk you through how to accomplish this access control for non-HTTP and non-HTTPS traffic, such as SSH (Secure Shell). This solution is extensible to other protocols with static port assignments.
In the example scenario in this post, the network administrator needs to permit outbound SSH access on port 22/tcp to a third-party domain, example.org, from a group of Amazon Elastic Compute Cloud (Amazon EC2) instances that sits inside of a protected VPC that restricts outbound SSH traffic with Network Firewall. Non-HTTP traffic can’t currently be controlled with a domain rule in Network Firewall.
This solution allows administrators to control outbound access to a given domain in a granular way, by resolving the domain name inside of an AWS Lambda function, and updating a Network Firewall rule variable with the results of the DNS query. This solution further restricts specific non-HTTP and non-HTTPS traffic to those allowed domains to only what is explicitly specified by the administrator.
This solution does have one caveat. In the event that the domain you’re attempting to resolve uses round-robin DNS, weighted routing, or some other traffic steering mechanism, the DNS query results from the Lambda function may differ from the compute resource routing through the Network Firewall, causing unexpected results.
Figure 1 provides an overview of the solution and the resulting traffic flow.
The solution workflow is as follows:
- An Amazon EventBridge rule invokes the Lambda function every 10 minutes. You can modify this frequency to meet your needs. You should consider the time-to-live (TTL) record of the DNS record that you are configuring when choosing this interval.
- The Lambda function performs the DNS lookup for the provided domain, and updates a variable in an existing Network Firewall rule group. The rule group changes take a few seconds to fully apply to the nodes in your Network Firewall deployment.
- The newly created Network Firewall rule group is associated with the Network Firewall policy to control traffic.
- Traffic from the instances in your VPC flows through the Network Firewall endpoint, and if allowed, is routed through an internet gateway to the target server.
This solution has the following prerequisites:
- An AWS account. If you don’t have an AWS account, create and activate one.
- An existing VPC with default routing to an internet gateway through a network firewall that has a firewall policy attached to it. The example rule included in the solution’s AWS CloudFormation template expects the firewall policy to use the default action order for stateful rule groups. If you don’t have an existing network firewall associated with your VPC, see the AWS Network Firewall Developer Guide to get started. For a walkthrough of the Network Firewall configuration and rules engine, see the blog post Hands-on walkthrough of the AWS Network Firewall flexible rules engine – Part 1.
- A DNS domain that you provide, which allows traffic for the protocol and port (or ports) that you plan to allow traffic to. This DNS domain needs to resolve to an IPv4 address or set of addresses; IPv6 is not supported, at this point.
Deploy the solution
We’ve provided a CloudFormation template to deploy this solution, which is located in the GitHub repository that accompanies this blog post.
To deploy the solution
- Download the CloudFormation template from our GitHub repository.
- Sign in to your AWS account and select the AWS Region where your Network Firewall is deployed.
- Navigate to the CloudFormation service.
- Choose Stacks > Create Stack > With new resources (standard).
- In the Specify template section, choose Upload a template file.
- Choose Choose file, navigate to where you saved the CloudFormation template, and upload it. Then choose Next.
- Specify a stack name for your CloudFormation stack.
- In the Parameters section, for the Domain parameter, specify the name of the domain to which you will control access. The default value is set to example.org; however, note that the actual example.org doesn’t allow SSH traffic.
- The remaining parameters have defaults to allow outbound SSH traffic to the specified domain. Adjust the LambdaJobFrequency variable so that it corresponds with the TTL of the DNS record that it will resolve. This allows the Lambda function to keep the IP address of the DNS record up to date, in the event that it changes. After you’ve configured the parameters, choose Next.
- On the Configure stack options page, specify any further options needed or keep the default options, and then choose Next.
- On the Review page, review the stack and parameters and select the check box to acknowledge that this template will create IAM resources. Choose Create Stack.
- Check the stack creation status. Upon successful completion, the status shows CREATE_COMPLETE.
Test the solution
Before you test the newly created rule, make sure that the Lambda function has been invoked at least once from the EventBridge rule.
To verify the Lambda function results
- In the AWS Management Console, navigate to the Lambda function Network-Firewall-Resolver-Function, and on the Monitor tab, choose View logs in CloudWatch.
- Select the most recent log stream.
- Verify that that a log line contains the entry StatefulRuleGroup updated successfully.
- Associate the stateful rule group that was created by the stack, Lambda-Managed-Stateful-Rule with the existing Network Firewall policy that is attached to your VPC. To do this:
- Navigate to VPC > Network Firewall > Firewall Policies and select your existing firewall policy.
- In the Stateful rule groups section, for Actions, choose Add unmanaged stateful rule groups.
- Select the check box for Lambda-Managed-Stateful-Rule, and then choose Add stateful rule group.
- When the newly provisioned Lambda function runs successfully, it will resolve the IPv4 address for the domain (example.org) and associate the address with the stateful rule variable IP_NET. To validate that this has happened, do the following:
- Navigate to VPC > Network Firewall > Network Firewall rule groups.
- Choose the Lambda-Managed-Stateful-Rule rule group.
- Navigate to the rule variable section, and choose IP_NET. If the Lambda function successfully resolved the provided domain name, the variable will contain the IPv4 addresses for the domain you provided, as shown in Figure 6.
- Test the rule by attempting to connect to the domain that you specified in the CloudFormation template. Use an EC2 instance within the VPC that the network firewall rule is associated with, and attempt to establish an SSH connection to the domain that you specified. As shown by the SSH key negotiation in Figure 7, traffic is allowed through the network firewall, as intended.
You can also configure the rule to drop the SSH connection, rather than permit it. To do this:
- Navigate to VPC > Network Firewall > Network Firewall rule groups.
- Choose the Lambda-Managed-Stateful-Rule rule group. In the Rules section, choose Edit Rules.
- Modify the rule to take the Drop action, and save the rule group.
As shown by the lack of response from the host in Figure 8, the SSH connection cannot be established anymore.
Follow the steps in this section to remove the resources created by this solution.
To remove the resources
- Sign in to your AWS account where you deployed the CloudFormation stack and navigate to the Network Firewall console.
- In the Stateful rule groups section, select the check box for Lambda-Managed-Stateful-Rule. For Actions, choose Disassociate from policy.
- Navigate to the CloudFormation console, select the stack that you created, and then choose Delete. Upon successful deletion, the resources created by the stack will be deleted.
In this post, we’ve demonstrated how security and network administrators have the ability to permit or restrict non-HTTP and non-HTTPS traffic to a given domain by using Network Firewall. With this solution, administrators can enforce granular port- and protocol-level control to third-party domains. To learn more about rule group configuration in AWS Network Firewall, see Managing your own rule groups in the Developer Guide.
If you have feedback about this post, submit comments in the Comments section below. If you have questions about this post, contact AWS Support. You can also start a new thread on AWS Network Firewall re:Post to get answers from the community.
Want more AWS Security news? Follow us on Twitter.