Zone Apex and Webserver Redirect

Cloud Journey
8 min readSep 6, 2021

Overview

When you host your website in the cloud infrastructure or by third party, it comes with vendor specific DNS name, e.g *.amazonaws.com. You will typically want to create alias in your DNS zone, for example, alias www.xyz.com points to canonical name <sth.sth>.amazonaws.com.

Your customer might also expect to access your site using xyz.com.

With Amazon Route 53, this is possible, because Amazon Route 53 supports the alias record set. Alias record sets let you map your zone apex DNS name to the DNS name of some AWS services.

While not explicitly prohibited, with many DNS service providers, it isn’t possible to create a CNAME record for the zone apex, as it effectively rewrites all other DNS records for that same domain. RFC 1034 states that, “If a CNAME RR is present at a node, no other data should be present; this ensures that the data for a canonical name and its aliases cannot be different.”

In this blog post, we will explain why we can not create CNAME record in zone apex and explore webserver redirection as an alternative solution.

Why NO CNAME at Zone Apex

CNAME record meaning and interpretation is strictly defined in the DNS protocol. The original concept was to permit the addition of “also known as” names to a zone in DNS, which would then be redirected to the “official” (or “canonical”) name.

If we define CNAME at Zone Apex, SOA and NS record at zone apex will not be functioning any more, as well as all other record types in the zone.

We cannot change how the special CNAME record is used without changing all of the DNS server implementations in the world at the same time. Attempting to “relax” how CNAME is used in authoritative servers without simultaneously changing all DNS resolvers currently in operation would cause name resolution to break.

https://www.isc.org/blogs/cname-at-the-apex-of-a-zone/

Solution Diagram

One alternative is to set up a webserver for xyz.com that provides a web redirect to www.xyz.com

At Zone Apex, add A type record, point to AWS global accelerator static IPs, AWS internal ALB is the endpoint behind AWS global accelerator, and redirect rule is configured in the ALB. (xyz.com -> www.xyz.com)

For end to end test, we also configure AWS NLB and EC2 to host the website (www.xyz.com).

POC Setup

Please refer to my other article Configure Zone Apex and Webserver Redirect | by Cloud Journey | Sep, 2021 | Medium

POC Demonstration

Website Hosted in AWS NLB and EC2

Access Website Through CNAME

C:\Users\rquan>nslookup www.rquan.workNon-authoritative answer:
Name: nlbsite-94dbb43e06908040.elb.us-east-1.amazonaws.com
Address: 34.238.x.x
Aliases: www.rquan.work
C:\Users\rquan>curl -vI http://www.rquan.work
* Rebuilt URL to: http://www.rquan.work/
* Trying 34.238.x.x...
* TCP_NODELAY set
* Connected to www.rquan.work (34.238.x.x) port 80 (#0)
> HEAD / HTTP/1.1
> Host: www.rquan.work
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 200 OK

Access Website Without www Prefix

Zone Apex A type record, target is AWS global accelerator static IPs.

C:\Users\rquan>nslookup> server 8.8.8.8
Default Server: dns.google
Address: 8.8.8.8
> rquan.work
Server: dns.google
Address: 8.8.8.8
Non-authoritative answer:
Name: rquan.work
Addresses: 52.223.x.x
35.71.x.x
> set type=ptr> 52.223.x.x
Server: dns.google
Address: 8.8.8.8
Non-authoritative answer:
x.x.223.52.in-addr.arpa name = a57b87154f84c465c.awsglobalaccelerator.com
> 35.71.x.x
Server: dns.google
Address: 8.8.8.8
Non-authoritative answer:
x.x1.71.35.in-addr.arpa name = a57b87154f84c465c.awsglobalaccelerator.com

From browser open http://rquan.work/, it’s resolved to global accelerator IP, then redirect to http://www.rquan.work/ by global accelerator’s ALB endpoint. The ELB and EC2 which hosts www.rquan.work respond with the web page.

Resiliency

AWS Global Accelerator Static IPs

Global Accelerator provides you with a set of two static IP addresses that are anycast from the AWS edge network.

A network zone services the static IP addresses for your accelerator from a unique IP subnet. Similar to an AWS Availability Zone, a network zone is an isolated unit with its own set of physical infrastructure. When you configure an accelerator, by default, Global Accelerator allocates two IPv4 addresses for it. If one IP address from a network zone becomes unavailable due to IP address blocking by certain client networks, or network disruptions, then client applications can retry on the healthy static IP address from the other isolated network zone.

Here shows the client use both static IPs to connect to AWS global accelerator.

Use 35.71.x.x static IP

# -L option means 'Follow redirects'
C:\Users\rquan>curl -IvL http://rquan.work
* Rebuilt URL to: http://rquan.work/
* Trying 35.71.x.x…
* TCP_NODELAY set
* Connected to rquan.work (35.71.x.x) port 80 (#0)
> HEAD / HTTP/1.1
> Host: rquan.work
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
HTTP/1.1 301 Moved Permanently
< Server: awselb/2.0
Server: awselb/2.0
< Date: Mon, 06 Sep 2021 01:54:46 GMT
Date: Mon, 06 Sep 2021 01:54:46 GMT
< Content-Type: text/html
Content-Type: text/html
< Content-Length: 134
Content-Length: 134
< Connection: keep-alive
Connection: keep-alive
< Location: http://www.rquan.work:80/
Location: http://www.rquan.work:80/
<
* Connection #0 to host rquan.work left intact
* Issue another request to this URL: ‘http://www.rquan.work:80/'
* Trying 34.238.x.x…
* TCP_NODELAY set
* Connected to www.rquan.work (34.238.x.x) port 80 (#1)
> HEAD / HTTP/1.1
> Host: www.rquan.work
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 200 OK

Flush DNS cache, now the client picks other static IP.

C:\Users\rquan>ipconfig /flushdnsWindows IP ConfigurationSuccessfully flushed the DNS Resolver Cache.C:\Users\rquan>curl -IvL http://rquan.work
* Rebuilt URL to: http://rquan.work/
* Trying 52.223.x.x…
* TCP_NODELAY set
* Connected to rquan.work (52.223.x.x) port 80 (#0)
> HEAD / HTTP/1.1
> Host: rquan.work
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
HTTP/1.1 301 Moved Permanently
< Server: awselb/2.0
Server: awselb/2.0
< Date: Mon, 06 Sep 2021 01:58:31 GMT
Date: Mon, 06 Sep 2021 01:58:31 GMT
< Content-Type: text/html
Content-Type: text/html
< Content-Length: 134
Content-Length: 134
< Connection: keep-alive
Connection: keep-alive
< Location: http://www.rquan.work:80/
Location: http://www.rquan.work:80/
<
* Connection #0 to host rquan.work left intact
* Issue another request to this URL: ‘http://www.rquan.work:80/'

Global Accelerator Endpoint Group Region Redundancy

Each endpoint group is associated with a specific AWS Region. Endpoint groups include one or more endpoints in the Region. With a standard accelerator, you can increase or reduce the percentage of traffic that would be otherwise directed to an endpoint group by adjusting a setting called a traffic dial. The traffic dial lets you easily do performance testing or blue/green deployment testing, for example, for new releases across different AWS Regions.

You set traffic dial to 100% when you want an endpoint group to handle all user requests from the optimal region.

You set traffic dial to 0% when you don’t want an endpoint group to handle any user requests.

Here shows even though one region endpoint is not taking the traffic, the other region ALB works, and global accelerator responded to user request.

$ curl -vvvvLI -H 'Host: rquan.work' http://a57b87154f84c465c.awsglobalaccelerator.com*   Trying 35.71.x.x...
* TCP_NODELAY set
* Expire in 149943 ms for 3 (transfer 0x6548d0)
* Expire in 200 ms for 4 (transfer 0x6548d0)
* Connected to a57b87154f84c465c.awsglobalaccelerator.com (35.71.x.x) port 80 (#0)
> HEAD / HTTP/1.1
> Host: rquan.work
> User-Agent: curl/7.64.0
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: awselb/2.0
< Date: Mon, 06 Sep 2021 01:44:37 GMT
< Content-Type: text/html
< Content-Length: 134
< Connection: keep-alive
< Location: http://www.rquan.work:80/
<
0 134 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
* Connection #0 to host a57b87154f84c465c.awsglobalaccelerator.com left intact
* Issue another request to this URL: 'http://www.rquan.work:80/'
* Expire in 200 ms for 1 (transfer 0x6548d0)
* Trying 34.238.x.x...
* TCP_NODELAY set
* Expire in 200 ms for 4 (transfer 0x6548d0)
* Connected to www.rquan.work (34.238.94.57) port 80 (#1)
> HEAD / HTTP/1.1
> Host: www.rquan.work
> User-Agent: curl/7.64.0
> Accept: */*

Retry From Web Client

When one of the global accelerator static IP is not responding, the client (curl or browser) try the next IP from the list.

To simulate the failure, I configure zone apex A record to a fake IP target 10.0.191.201.

C:\Users\rquan>curl -vvvvL http://rquan.work
* Rebuilt URL to: http://rquan.work/
* Trying 10.0.191.201...
* TCP_NODELAY set
* connect to 10.0.191.201 port 80 failed: Timed out
* Trying 15.197.x.x...
* TCP_NODELAY set
* Connected to rquan.work (15.197.x.x) port 80 (#0)
> GET / HTTP/1.1
> Host: rquan.work
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Server: awselb/2.0
< Date: Mon, 06 Sep 2021 20:50:32 GMT
< Content-Type: text/html
< Content-Length: 134
< Connection: keep-alive
< Location: http://www.rquan.work:80/
<
* Ignoring the response-body
* Connection #0 to host rquan.work left intact
* Issue another request to this URL: 'http://www.rquan.work:80/'
* Trying 3.138.x.x...
* TCP_NODELAY set
* Connected to www.rquan.work (3.138.x.x) port 80 (#1)
> GET / HTTP/1.1
> Host: www.rquan.work
> User-Agent: curl/7.55.1
> Accept: */*
>

<
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Test Page for the Apache HTTP Server</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css">
/*<![CDATA[*/

Azure Equivalent

Azure Front Door is a global, scalable entry-point that uses the Microsoft global edge network to create fast, secure, and widely scalable web applications. It’s integrated with Azure WAF, and support URL redirect, but it does not guarantee static IP.

MS Doc says “Kindly do not take any direct dependencies on the IP.”

When send http request to front door IP address, got 400 bad request response, while it works when use DNS name.

Use FQDN

curl -vvvvL http://rqtest.azurefd.net* Connected to rqtest.azurefd.net (2620:1ec:bdf::57) port 80 (#0)> GET / HTTP/1.1
> Host: rqtest.azurefd.net
> User-Agent: curl/7.64.0
> Accept: */*
>< HTTP/1.1 302 Found< Location: http://www.rquan.work/< X-Azure-Ref: 0tcE2YQAAAAAadApOlONnQ5KdYFCvIi1vQVRBRURHRTEyMTQAYzgzOGY2OTctYWE4NS00NDkwLWJjNWMtNjcwMTA5MzM3Njdk
< Date: Tue, 07 Sep 2021 01:34:44 GMT
< Content-Length: 0
<
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Connection #0 to host rqtest.azurefd.net left intact
* Issue another request to this URL: 'http://www.rquan.work/'

Use IPv6

$ nslookup rqtest.azurefd.net
Name: part-0013.t-0009.t-msedge.net
Addresses: 2620:1ec:bdf::41
2620:1ec:46::41
13.107.213.41
13.107.246.41
Aliases: rqtest.azurefd.net
star-azurefd-prod.trafficmanager.net
dual.part-0013.t-0009.t-msedge.net
C:\Users\rquan>curl -vv http://[2620:1ec:bdf::41]
* Rebuilt URL to: http://[2620:1ec:bdf::41]/
* Trying 2620:1ec:bdf::41...
* TCP_NODELAY set
* Connected to 2620:1ec:bdf::41 (2620:1ec:bdf::41) port 80 (#0)
> GET / HTTP/1.1
> Host: [2620:1ec:bdf::41]
> User-Agent: curl/7.55.1
> Accept: */*
>
< HTTP/1.1 400 Bad Request
< Transfer-Encoding: chunked
< X-MSEdge-Ref: 0H8U2YQAAAAA1VYXwcFdSSKEBfBMdc4ELQVRBRURHRTEyMTAARWRnZQ==
< Date: Tue, 07 Sep 2021 01:49:19 GMT
<
<h2>Our services aren't available right now</h2><p>We're working to restore all services as soon as possible. Please check back soon.</p>0H8U2YQAAAAA1VYXwcFdSSKEBfBMdc4ELQVRBRURHRTEyMTAARWRnZQ==* Connection #0 to host 2620:1ec:bdf::41 left intact

For more detail on Azure configuration, please refer to my other article Configure Zone Apex and Webserver Redirect | by Cloud Journey | Sep, 2021 | Medium

--

--

Cloud Journey

All blogs are strictly personal and do not reflect the views of my employer. https://github.com/Ronnie-personal