Using F5 Application Security and DOS Solutions with AWS Global Accelerator - Part 2 Building a Lab
Alright! You have spent time understanding the information in part 1 of the series and you are ready to build your test bed. Here is a diagram of what we will build.
We will use the F5 CloudFormation v2 templates to deploy our VPC, AutoScale BIG-IPs and our example application. After we have deployed our basic environment we will then deploy AWS Global Accelerator, it's associated components and we will finish our deployment by using the AWS provided example of using Lambda to populate the Global Accelerator target groups. My examples will use the AWS CLI for these actions but for those that are more WebUI inclined that is an option.
In this lab we will use the following:
1. F5 Autoscale Quickstart Cloud Fomration Template
2. F5 BIG-IP BEST 25MB from AWS Marketplace
Before proceeding you will need to subscribe to the BIG-IP offer in the AWS marketplace.
What We Will Build
We will build a topology that supports the following traffic flow:
- Clients traffic is attracted to the closest AWS POP and traverses the AWS Backbone to the deployed region
- BIG-IP, acting as an EC2 target to Global Accelerator, will intercept the traffic process the security policy and send the traffic to an application instance
- Instance responds to the BIG-IP
- BIG-IP responds to the Client IP address
- Traffic egress the Global Accelerator infrastructure out of the POP that it entered
Accessing AWS
For our examples we will need a system with the AWS CLI installed. You can use your local system or you can use the AWS CloudShell instance from the AWS console.
Deploying BIG-IP, VPC and an Application
The F5 AutoScale template includes an option to deploy an example application, VPC, BIG-IP AutoScale group and an object called the Disaggregater (DAG). In F5 deployments in the public cloud a DAG can be an Elastic IP (EIP), or Elastic Load Balancer (ELB) this objects function to attract traffic from the Internet via a public IP address and distribute it to one or more instances deployed in AWS. When a user wants to use an AutoScale function the most commonly selected option in AWS is the Network Load Balancer (NLB) variant from the ELB family. We will use the AWS Global Accelerator as our DAG when we deploy the template we will set the DAG option to false.
Prior to deploying our CloudFormation stack please ensure that you have generated an AWS Key Pair, subscribed to the BIG-IP offering, and documented the public IP address from your location. Your BIG-IP instances will be monitored by AWS for use as Global Accelerator targets. If you do not use 0.0.0.0/0 for "ParameterKey=restrictedSrcAddressApp,ParameterValue=<0.0.0.0/0 or MY IP> \" you will need to edit the AWS security group to allow traffic from Route53 health checks.
aws cloudformation create-stack --region <REGION> --stack-name <MY NAME> \
--template-url https://f5-cft-v2.s3.amazonaws.com/f5-aws-cloudformation-v2/v2.6.0.0/examples/autoscale/payg/autoscale.yaml \
--parameters ParameterKey=sshKey,ParameterValue=<KEY PAIR> \
ParameterKey=restrictedSrcAddressMgmt,ParameterValue=<MY IP> \
ParameterKey=restrictedSrcAddressApp,ParameterValue=<0.0.0.0/0 or MY IP> \
ParameterKey=uniqueString,ParameterValue=<MY UNIQUE STRING> \
ParameterKey=provisionExternalBigipLoadBalancer,ParameterValue=false \
ParameterKey=notificationEmail,ParameterValue=<MY EMAIL> \
--capabilities CAPABILITY_NAMED_IAM
Creating an AWS Global Accelerator
Now we will deploy our Global Accelerator. Many of the Global Accelerator API calls need to be sent to us-west-2 region and some of the CLI examples may requrie that argument even if you are deploying into another region.
In this step we will create an AWS Global Accelerator deployment. The end result of this will be that we will have two IPv4 and / or two IPv6 addresses that will be presented to the Internet via the 110+ POPs. Each IP is aligned to an AWS fault domain and unlike ELB addresses these are static for the life of your Global Accelerator deployment.
aws globalaccelerator create-accelerator --name <my-test-waf-global-accelerator> --ip-address-type IPV4 --enabled --region us-west-2
When you command completes you will see information about the created object including it's ARN. Please make a note of it. You can also log all of the output via standard Linux redirect such as > or >> filename.txt (I recommend doing this)
Creating Listeners for your Global Accelerator
A listener is a combination of IP Address(es) associated with your Global Accelerator , Port and Protocol (TCP or UDP). We will need to create listener on our Global Accelerator that will allows us to process and forward the traffic that is attracted to the IP addresses.
In the command below we ill create a listener that uses SOURCE IP affinity to the targets (our security layer) and will map ports 80 to 80 and 443 to 443 attracting traffic for TCP. These listeners will be created globally in the 110+ POPs.
aws globalaccelerator create-listener --accelerator-arn <ACCELERATOR ARN> --client-affinity SOURCE_IP --port-ranges FromPort=80,ToPort=80 FromPort=443,ToPort=443 --protocol TCP --region us-west-2
Creating Endpoints for your Global Accelerator
Now we will create our endpoints for the Global Accelerator. Endpoints are the targets (in our case EC2 instances performing the security function) of traffic that is attracted onto the network. In the following command you will see two regions. The first is the region we are creating the endpoint group in. The second is the region (us-west-2) that hosts the Global Accelerator API, and is only requried if you are not running the CLI from a us-west-2 cloudshell (our you default region is not us-west-2).
aws globalaccelerator create-endpoint-group --listener-arn <LISTENER ARN> --endpoint-group-region <REGION> --region us-west-2
Global Accelerator supports endpoint groups in multiple regions allowing you to steer traffic to the closest region that has resources to serve the application. For example let's say your application has users in the US, EU, and APCJ. A single Global Accelerator deployment could leverage AWS regions in all of them ensuring that users have the best experience possible. To add endpoint groups you simple repeat the process.
At this point we are not yet ready to test traffic. We have an IP address(s) for our Global Accelerator, Listners, and one or more endpoint groups. We will now need to populate an endpoint group to respond to our HTTP requests.
Populating Endpoint Groups
If you remember Part 1 there was a brief discussion about Global Accelerator and AutoScale. TL;DR is Global Accelerator does not have native integration with AutoScale and human intervention may be required. We will not use the antipattern of humans doing work that does not add value. Enter AWS Lambda and EC2 lifecycle hooks. Once we deploy this you will be able to spend your time doing more important work.
You can get the CloudFormation Template (CFT) for this solution from the AWS blog or the attached file (due to file type limits copy the text in the PDF to a .yaml file). Either way I recommend that you read the blog to understand how it works. The template file will need to be on the system you are running the CLI commands from.
Step 1 - Get our BIG-IP AutoScale group name
aws autoscaling describe-auto-scaling-groups --region <REGION> | grep bigip
"AutoScalingGroupName": "mywaf-bigip-autoscaling-group",
Step 2 - Deploy the template
aws cloudformation create-stack --stack-name GlobalAcceleratorAndAutoScaling --template-body file://asg_aga.yaml --parameters ParameterKey=EndpointGroupARN,ParameterValue= <OUR-ENDPOINT-GROUP-ARN> ParameterKey=AutoscalingGroupName,ParameterValue=<bigip-autoscaling-group-name> --region <REGION> --capabilities CAPABILITY_IAM
Once the template completes we will need to generate AutoScale events since the population of the endpoints requires EC2 lifecycle events. (remember --region us-west-2 is only required if your default region is not us-west-2 or if you cloudshell instance is not in us-west-2)
aws autoscaling update-auto-scaling-group \
--auto-scaling-group-name <ASG-Group-Name> \
--min-size 0 --desired-capacity 0
aws autoscaling update-auto-scaling-group \
--auto-scaling-group-name <ASG-Group-Name> \
--min-size 1 --desired-capacity 1
aws globalaccelerator describe-endpoint-group \
--endpoint-group-arn <YourEndpointGroupARN> \
--region us-west-2
At this point you should have an endpoint group that is populated by one or more instances of BIG-IP. Here is the output of the last command above
aws globalaccelerator describe-endpoint-group --endpoint-group-arn arn:aws:globalaccelerator::711213608975:accelerator/e6eb780d-90d1-48d8-a85c-f6f8899e3e10/listener/c35f4fbb/endpoint-group/80fcf0d7d002
{
"EndpointGroup": {
"EndpointGroupArn": "arn:aws:globalaccelerator::711213608975:accelerator/e6eb780d-90d1-48d8-a85c-f6f8899e3e10/listener/c35f4fbb/endpoint-group/80fcf0d7d002",
"EndpointGroupRegion": "us-east-1",
"EndpointDescriptions": [
{
"EndpointId": "i-0881a10b4512cf96b",
"Weight": 128,
"HealthState": "HEALTHY",
"ClientIPPreservationEnabled": true
}
],
"TrafficDialPercentage": 100.0,
"HealthCheckPort": 80,
"HealthCheckProtocol": "TCP",
"HealthCheckIntervalSeconds": 30,
"ThresholdCount": 3
}
}
Testing your Global Accelerator
Now we need the IP addresses of your global accelerator, the listeners and endpoint groups we can start testing our application.
Getting the Accelerator IPs from the AWS CLI
aws globalaccelerator list-accelerators --region us-west-2
…
"AcceleratorArn": "<ARN>",
"IpFamily": "IPv4",
"IpAddresses": [
"IP",
"IP"
Example of a request rejected by BIG-IP Advanced WAF:
curl -vvv -X DELETE http://<IP>
* Trying IP:80...
…
* Closing connection 0
<html><head><title>Request Rejected</title></head><body>The requested URL was rejected. Please consult with your administrator.<br><br>Your support ID is: <F5_generated_support_id><br><br><a href='javascript:history.back();'>[Go Back]</a></body></html>%
Example of a request allowed by BIG-IP Advanced WAF:
curl -vvv http://<IP>
* Trying IP:80...
…
BIGipServer~Tenant_1~Shared~shared_pool=3171024906.20480.0000; path=/; Httponly
< Set-Cookie: <cookie_value>; Path=/
<
* Connection #0 to host IP left intact
<!DOCTYPE html><html><head><title>Demo App (default)</title><link
Wrapping Up
Today we covered how to setup the topology and test traffic. In part 3 we will cover the following:
1. Infrastructure as code - publishing new security policies
2. Logging and Visibility
3. Differences between our lab and a production deployment