Showing posts with label vpc. Show all posts
Showing posts with label vpc. Show all posts

Sunday, February 23, 2020

IPv6 for Private AWS Subnets

Instead of setting up "private" subnets in AWS with the use of moderately-expensive AWS NAT Gateways, I've been experimenting with free Egress-Only Internet Gateways (EIGW). The downside with EIGW is that it's IPv6 only — so you can communicate to the outside world from instances in your private subnet only through IPv6.

In theory, that shouldn't be a problem — it's 2020 and IPv6 just works everywhere, right? Well, actually, in practice it does work pretty well — but there are still a few gotchas. Here are a few hurdles I had to work around when setting up a fleet of Ubuntu Linux EC2 instances with Ansible:

APT Repos

The base AMIs that Ubuntu provides are configured to use the Ubuntu APT repos hosted by AWS (like us-east-1.ec2.archive.ubuntu.com); however, these repos only support IPv4. So the first thing you need to do is change the repos listed in /etc/apt/sources.list to use external repos that support IPv6 (like us.archive.ubuntu.com, or other Ubuntu mirrors you might find).

And since you won't be able to use IPv4 to access the repos, you can speed up APT updates by configuring APT to try only IPv6. To do so, add a file in your /etc/apt/apt.conf.d/ directory (call it something like 99force-ipv6) with the following content:

Acquire::ForceIPv6 "true";

Also don't forget that if you do set up a restrictive Network ACL for your private subnet, you'll need to allow inbound TCP access to the standard Linux ethereal port range (32768-61000) from whatever APT repos you use.

NTP Pools

The NTP pools used by the base AMIs also don't support IPv6. I use the traditional NTP daemon provided by the Ubuntu ntp package, rather the default systemd-tymesyncd service. To configure the NTP daemon, I remove all the default pools from the /etc/ntp.conf file, and instead just use the 2.us.pool.ntp.org pool (the convention with NTP is that for domains that have numbered pools, like 0.us.pool.ntp.org, 1.us.pool.ntp.org, 2.us.pool.ntp.org, etc, the pool numbered 2 is the one that supports IPv6).

Specifically, this is how I configure the 2.us.pool.ntp.org pool in /etc/ntp.conf:

pool -6 2.us.pool.ntp.org iburst minpoll 10 maxpoll 12

The -6 flag means to use IPv6; the iburst part is supposed to help speed up initial synchronization; the minpoll 10 part means to poll no more often than every 2^10 seconds (around 17 minutes); and the maxpoll 12 part means to poll no less often than every 2^12 seconds (around 68 minutes).

Also, if you set up a restrictive Network ACL for your private subnet, you'll need to allow inbound access to UDP port 123.

AWS APIs

If you are planning to directly call AWS APIs (either through the various per-language SDKs, or the CLI), a huge gotcha is that very few AWS services as of yet provide IPv6 endpoints. This means that you won't be able to use most AWS services at all from within your private IPv6 subnet (with the exception of services that consist of instances that themselves reside within your VPCs, like RDS; rather than endpoints hosted outside of your VPCs, like DynamoDB).

The only major AWS service I've tried that does support IPv6 through its APIs is S3. When connecting to it via CLI, you can get it to use IPv6 by explicitly specifying the "dualstack" endpoint via command-line flag, like this:

aws --endpoint-url https://s3.dualstack.us-east-1.amazonaws.com --region us-east-1 s3 ls

Or, alternately, you can enable IPv6 usage via the AWS config file (~/.aws/config), like this:

[default] region = us-east-1 s3 = use_dualstack_endpoint = true addressing_style = virtual

Ansible Inventory

To access EC2 instances in a private subnet, typically you'd use a VPN running in a public subnet of the same (or bridged) VPC, with the VPN client set to route the VPC's private IPv4 block through the VPN. For IPv6, I also have my VPN set to route the VPC's IPv6 block through the VPN, too.

Using Ansible through a VPN with IPv4 is pretty much as simple as configuring Ansible's ec2.ini file to set its destination_variable and vpc_destination_variable settings to private_ip_address. But since I decided to disallow any IPv4 access to my private subnets (even from other subnets within the same VPC), I had to jump through a few extra hoops:

1. Custom Internal Domain Names

I use a custom internal domain name for all my servers (I'll use example.net as the custom domain in the following examples), and assign each server its own domain name (like db1.example.net or mail2.example.net, etc). When I launch a new EC2 server, I create a DNS AAAA record for it (via Route53), pointing the DNS record to the IPv6 address of the newly-launched server. In this way I can use the DNS name to refer to the same server throughout the its lifetime.

I also tag my EC2 instances as soon as I launch them with tags from which the DNS name can be constructed. For example, I'd assign the server with the DNS name of fe3.example.net a "node" tag of fe and a "number" tag of 3.

2. SSH Config

In my SSH config file (~/.ssh/config), I have an entry like the following, to make sure SSH (and Ansible) only tries to access my EC2 instances through IPv6:

Host *.example.net AddressFamily inet6
3. Ansible EC2 Config

With the above two elements in place, I can then enable the destination_format (and destination_format_tags) settings in the Ansible ec2.ini configuration file to direct Ansible to use DNS names instead of IP address for EC2 inventory. With the "node" and "number" tags described above, I can use the following configuration in my ec2.ini file:

destination_format = {0}{1}.example.net destination_format_tags = node,number

When the above is set up correctly, you can run the ec2.py script (eg as ./ec2.py), and see your DNS names in its output (like db1.example.net or mail2.example.net, etc), instead of IPv4 addresses. And when you run an ad-hoc Ansible module (like ansible fe3.example.com -i ec2.py -m setup) everything should "just work".

Sunday, February 14, 2010

IE VPCs on Ubuntu

I love the fact that Microsoft makes these Internet Explorer Application Compatibility VPC Images available, but I hate the fact that they're so darn hard to setup on linux. Plus the last few times they've rev'd the images, they've packaged them in a way where the licensing breaks if you don't run them in Microsoft's VPC software (obviously available for Windows only). And of course, each of the different VPCs (for ie6, ie7, and ie8) use the same disk uuid, which doesn't play nicely with VirtualBox. So this is what I end up doing:

Initial Setup

1) Download the latest VPCs.

2) Install unrar to extract the images:

sudo apt-get install unrar

3) Extract each image:

unrar e -o+ IE6-XP-SP3.exe

(I also move and rename them to something convenient, like ie6.vhd.)

4) Install VirtualBox:

sudo apt-get install virtualbox-ose virtualbox-guest-additions

Rinse and Repeat

After 3 days or reboots of the image, these VPC images will stop working in VirtualBox, so if you're not careful you'll have to repeat these steps fairly often (fortunately, VirtualBox's snapshotting capabilities can help here). Keep massaging the scalp until you've produced a thick, luxurious lather:

5) Clone the vhds, to give them universally unique uuids (apparently Microsoft doesn't quite get the meaning of uuid). Also, this'll give you a pristine image when you need to repeat the process:

VBoxManage clonehd ie6.vhd ie6cloned.vhd

6) Fire up the VirtualBox ui:

virtualbox

(I actually usually do this via the desktop menubar: Applications > Accessories > VirtualBox OSE.)

7) Add each of the vhds (you can also do this via VBoxManage commands, but I'm too lazy to figure them out):

  1. Click the New toolbar item. Click Next.
  2. Enter a name (like ie6) and click Next.
  3. Select the Base Memory Size (256 MB for ie6/7; 512 MB for ie8), click Next.
  4. Select Use existing hard disk, click the little Folder icon.
  5. Click the Add toolbar item.
  6. Browse to the (cloned) .vhd file, select it, and click Open.
  7. Select the vhd you just added, and click Select.
  8. Click Next, then click Finish.

8) Run each image (select the image, click the Start toolbar item).

9) After XP boots, click No to the Windows Product Activation prompt, then ignore all the other whiny messages (resist the temptation to freaking close them already!), and select the Devices > Install Guest Additions... menu item from the image's menubar (the linux window's menubar, not XP's — to get out of XP, press the right-control key). Click the Continue Anyway when Windows tells you that installing this software will usher in the End Times. Don't reboot when it finishes — fix a few other things first.

10) Because I use the Dvorak keyboard layout, the first thing I do in XP is change the keyboard layout, via the Start > Control Panel > Regional and Language Options control panel; flip to the Languages tab, click Details...; then click Add..., select Dvorak, click OK, make it the Default, OK, OK, OK already!

11) Next I get rid of XP's screensaver, via the Start > Control Panel > Display Properties control panel. Flip to the Screen Saver tab, and select (None) from the Screen saver drop down (and click OK when you're done with the display settings). Also choose a larger screen size (Settings tab) and try to find a desktop background that doesn't make you want to puke.

12) Still ignoring XP's whimperings, open a command prompt (Start > All Programs > Accessories > Command Prompt), and enter:

D:\VBoxWindowsAdditions-x86.exe /extract /D=C:\Drivers

13) Now find one of those Hardware Update Wizard dialogs that XP keeps popping up. If you couldn't take it and closed them all, open Start > Administrative Tools > Computer Management, then click Device Manager, then double-click Ethernet Controller, and finally click the Reinstall Driver... button. Follow these steps:

  1. Select the No, not this time radio-button, click Next.
  2. Select the Install from a list or specific location (Advanced) radio buton, click Next.
  3. Select the Search for the best driver in these locations radio-button, unselect the Search removable media check-box, select the Include this location in the search check-box, and type in C:\Drivers\x86\Network\AMD (or browse to it, if you're visually inclined).
  4. Click Next, click Finish.

Now we're finished with non-ie stuff! Ignore any other Hardware Wizards or other Forces of Darkness that XP sends your way.

14) For ie7, run the Install the IE Explorer 7 Readiness Toolkit item on your desktop.

15) Finally, run ie! You should see some crappy Microsoft home page — this means you've got the networking stuff hooked up right. Select Tools > Internet Options, and click the Use blank button so you never have to see this again. Then flip to the Advanced tab, and unselect the Disable script debugging (Internet Explorer) check-box, so the debugger will come up whenever you run across a javascript error.

OK, now reboot Windows. You've only got one more boot, so don't ever restart again! Once you boot up, save a snapshot with VirtualBox so you can always go back to this happy place.

See Also

Lots of other people have already gone down this road; especially helpful are: