Wednesday, April 17, 2019

Deploy Cisco ASAv in AWS for Infrastructure VPN with TONS of pictures

The AWS Virtual Private Gateway (VGW) is flexible, and integral to many of the AWS-native network backbone features exposed to users. However, it has some significant throughput drawbacks - in testing, we only see about about 640Mbps, or about 80MBps. And beyond that, flows seem to be limited to 400Mbps each, so utilizing the full 640Mbps requires multi-threading on the part of the application. The documentation claims the VGWs are capable of pushing 1.25Gbps, but we have yet to see close to that in our day to day testing.

To be fair to AWS, they do offer a pretty significant asterisk on the 1.25Gbps throughput claim.


If you're paying for a 10Gbps Direct Connect (DX), you're probably not too happy about being limited to 6.4% of the speed you thought you were getting. Or even 12.5%, if you get closer to the theoretical 1.25Gbps speed Amazon claims the VGW can push.

The real answer here is to use a Private Virtual InterFace (PVIF). But PVIFs have security drawbacks - they have none. The AWS security model is based around endpoint security ONLY - Network ACLs (NACLs) and Security Groups (SGs) are all that you get. Other features are coming online over time, but there are many reasons network interconnect filtering might be required. Here are a few examples, by no means an exhaustive list

  • You need high bandwidth, requiring a PVIF - no interconnect filtering for you
  • You're connecting to another cloud via a VPN - no interconnect filtering for you
  • You're connecting to a partner's AWS VPC, via VPN or VPC peering - no interconnect filtering for you
You're noticing the trend here. The AWS-native toolkit isn't great here, so partners have stepped up, Cisco among them. The Cisco ASAv is a virtual machine that emulates the feature-set of the eponymous Cisco ASA series. Right now the highest throughput supported in AWS (or any other cloud) is 2Gbps with an ASAv30. It's still only 20% of the 10Gbps DX your company is springing for, but it's closer, and the security gains from deploying it are oceans away from the nothing-nada-none interconnect security on the AWS-native options. 



The Cisco ASAv50, which would help us utilize 100% of the 10Gbps DX at our hypothetical company, isn't yet available on the public cloud. True to form, the AWS Marketplace entry for the ASAv shows 2Gbps throughput as the highest yet available. Fingers crossed it becomes available over time.

None, enough prologue. Let's build this thing. First, go the AWS Markplace page for the ASAv and subscribe. There are two options:

  • Pay-as-you-go: You're charged in an ec2-like way for per-minute. The reviews on this version aren't great, mostly from folks misunderstanding billing, or maybe from Cisco over-billing. Regardless, I don't recommend this one. 
  • BYOL: Bring Your Own License. The ASAv doesn't actually REQUIRE a license. However, you'll be locked in at 100Kbps throughput until you purchase a license from a VAR, register it with Cisco, and get it install - Cisco Smart licenses only. 
Pick your poison, then hit "Continue to Subscribe". It'll take a few minutes, then you'll get an email that shows you are now subscribed. You DON'T need to continue to Configuration - it's actually easier if you don't. 



Now, let's get this really moving. Log into the AWS console --> ec2, and then click "Launch Instance" in the top right.

Search for ASAv, and find the BYOL device and hit "Select" next to it to start configuring the device.



Take note of the next screen, particularly the right side that shows rates for the different ec2 instance types. These costs vary by region (and possibly by contracted rate with AWS?), so yours might be slightly different.


Now compare the rates and sizings with the AWS Marketplace entry for the ASAv - it shows the suggested sizings for the different ASAv types and throughputs.

For me in this region, it's clear that the c4.xlarge is my best bet to get 2Gbps (ASAv30) with the cheapest rate. So let's do it. Hit "continue" on the ec2 deployment wizard, check the box and continue on to "Next: Configure Instance Details".


Here you get to decide where to put your ASAv device. Which is an interesting question, because this is a transitive device, not very common in cloud-land. The first interface built on an ASAv is called the "mgmt0/0" interface when you log into the ASA. Cisco recommends you use this as an actual management interface, but I like to use it as an internal interface, so let's put the device into a "private" subnet. Private doesn't mean much here - just that it is reachable from the inside of your network so you can route traffic through it.


Remember to also hit the "Enable termination protection" option to prevent someone from accidentally terminating this instance and deleting all your hard work.

Scroll down, and let's add our second interface to the ASAv. This one will be called "Gigabit0/0" locally on the ASAv. I like to put this in the "public" zone, and use it for inbound traffic. That requires some very specific network items, such as:

  • This interface has to be in a subnet with a default route through an Internet GateWay (IGW)
  • The NACL on the subnet has to permit inbound traffic on VPN ports: 
    • udp/500: ISAKMP
    • udp/4500: ESP, used for nat-traversal, highly relevant in the AWS environment where all hosts have private IPs and are behind 1:1 NAT to their Elastic IPs (EIPs)
Let's add an interface to our ec2 instance and put it in the "public" subnet. 



Now, it seems like you're done with this page, but this is where you'll find the first gotcha of this deployment. When the Cisco ASAv comes up, its configuration will be blank, which prevents anyone to connect to it over the network. There is no console to connect in cloud-land, so we need a way to give the device its initial configuration to permit us to connect to it. Cisco has an example of what they call a "0-day Configuration" posted on their docs page. It'll get the job done, but let's modify it for our use-case. I'll highlight the information that I modified:

hostname NewASAvThanksKyler
int gi 0/0
 nameif outside
 security-level 0
 ip address dhcp setroute
 no shut
interface management0/0
 management-only  <-- remove this line if you want to use it as your internal interface 
 nameif inside
 security-level 100
 ip address dhcp
 no shut
same-security-traffic permit inter-interface
same-security-traffic permit intra-interface
crypto key generate rsa modulus 2048
ssh 10.0.0.0 255.0.0.0 inside
ssh 10.0.0.0 255.0.0.0 outside    <-- Set this one to "ssh 0 0 outside" if you want to connect to it from the internet - say, if you aren't privately connected to this VPC. 
ssh timeout 30
ssh version 2
username admin password SuperSecretPassword privilege 15   <-- Set your own password
username admin attributes
service-type admin

Customize it however you like, then expand the "Advanced Details" panel at the bottom of the screen and paste in the configuration you just created. Leave the radio button on "As text". Then click "Next: Add Storage".


Click through the storage panel with no changes, which brings us to tags. Tags can be used for all sorts of organizational and billing purposes. Here, we'll just give our hosts a name. Either click "Add a Name tag" or just create a new tag with Key of "Name" and call it whatever you want. It makes sense to have the AWS name match the Cisco configuration name, something we didn't do here.


The next panel asks us for a SG to assign to our host. Every host in AWS has a SG that controls the ingress and egress of traffic to it. The default permits inbound tcp/22 (SSH) from the internet, which is a terrible, bad, awful idea. The host will be protected by an SSH key, but why permit any schmoe on the internet to connect to it? Update the rules shown below. You CAN put "0.0.0.0/0" on the tcp/500 and tcp/4500 rules, which would permit anyone on the internet to try and establish a VPN to your host, but I don't recommend it. No reason to expose your devices more than you need to, even when the device "Security" in the name.


Now you can review. Make sure everything looks like you expect. Then hit Launch! And we're off to the races! Oh wait, we're not. We need to select an SSH key to control access to the box. Either select an existing SSH key or build a new one. In either case, make sure you have the private key, then check the box and hit "Launch Instances".


The ASAv will build. It takes about 10 minutes to build and come up to where you can reach it, but that time will fly - there's a few more steps we have to take before this device is reachable. Let's add an EIP - a public Amazon-owned IP so this device can reach (and be reachable from) the internet. Before we go and grab the EIP, we need to learn where we're going to put it. Usually you'd associated an EIP with an ec2 instance, which is simple with an instance that has a single interface. However, we have a few, and could potentially have many more. So we need to learn exactly which Elastic Network Interface (ENI) we want to attach it to. In the ec2 panel, click on the interface, then go to Actions --> Networking --> Manage IP Addresses. We don't care about the actual IPs yet - what we're interested in the ENI of eth1, the SECOND interface on this device. Remember, the second interface is gi0/0, and the one we set in the "outside" zone in our Cisco config. Copy the ENI-XXX to your clipboard or write down the last few.


Now let's go get the real EIP. Go to the ec2 panel, then on the left side, under "Network & Security", click on Elastic IPs.


In the top left, click "Allocate new address", then "Amazon pool," then click Allocate to see your new IP. I'd recommend writing the IP down, especially if you have a bunch of other EIPs, so you don't get it mixed up. Click close, then click on the EIP in your list, Actions at the top, then Associate. Bam, your device is now on the internet.


Cisco AWS ec2 instances have a built-in security measure to prevent hosts from becoming transit devices and siphoning data from your network. That security measure is called the source/destination check, and makes sure that only traffic destined TO or sourced FROM an IP the host owns passes to or from the host. Which is exactly the rule we need to break for this ASAv to act as a transit device, so let's turn it off. On the ec2 panel, under Network & Security, click on Network Interfaces.

As an aside, if you need to find an IP in your org, regardless of what service is consuming it, that service has to create an ENI to slurp up traffic. So if you want to find out if an IP belongs to RDS, Batch, Directory Services, or a plane-jane ec2 instance, look for the ENI as a shortcut.

An easy way to find both ENIs assigned to our host is to search for the SG name that we created. Bam, found. We only need to disable this check on the "inside" interface of the ASAv, which will be the first interface we assign. You can find it by looking for "Primary Network Interface" in the description.


Click on the Primary network interface and click Actions --> Change Source/Dest. Check. Then turn it off and hit save.


Once the host boots, ssh to it using the SSH key you selected when building the host and you are in! If you get an error message from a mac or linux client when attempting to use the SSH key that the key is inaccessible even though you know it is, update the permissions to be more specific:
computer:~ kyler$ chmod 400 Downloads/KylerASAv.pem 

Now that the ASA is built, reachable, and all interfaces are in the right subnets, verify your internet access. If you can reach out, the ASAv is done. Now you just need to build some VPNs!

The one major next step is to update any routing tables in your VPC to point at the internal interface (ENI) of the ASAv so it can carry the traffic across. Find the ENI of the Primary network Interface just as above, then go the VPC panel in the AWS web console. Click on the route table you want to edit, then on "Routes," then on "Edit Routes". Add a new route to whatever the partner's network is that you want to route towards, then click in the "Target" field. You'll need to select "Network Interface," then you can paste int the entire ENI-XXX string where you want to send this traffic. Hit "Save routes" and your changes are live - you're sending your internal traffic to the internal ENI of the ASAv device.


Good luck out there! 
kyler

1 comment: