Marc Cornellà
Posted on May 16, 2020
Yes, I used "considered harmful" in the title. Can I be a thought-leader now?
When you own a domain it is often desirable to use a subdomain to point to somewhere else. For example, you might want to use the cooler-looking blog.mcornella.com
domain to point to your dev.to profile.
This can be done easily with a URL redirect record, where you specify the subdomain (blog
) and the URL it should be redirected to (https://dev.to/mcornella
). Fortunately, most major domain name registrars offer this option on their DNS settings dashboard. For example, this is how it looks in the current Namecheap DNS dashboard:
How does this work?
Let's use curl
to see what happens under the hood:
$ curl -v blog.mcornella.com
* Trying 162.255.119.141:80...
* TCP_NODELAY set
* Connected to blog.mcornella.com (162.255.119.141) port 80 (#0)
> GET / HTTP/1.1
> Host: blog.mcornella.com
> User-Agent: curl/7.65.3
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 302 Found
< Server: nginx
< Date: Fri, 15 May 2020 14:49:06 GMT
< Content-Type: text/html; charset=utf-8
< Content-Length: 47
< Connection: keep-alive
< Location: https://dev.to/mcornella
< X-Served-By: Namecheap URL Forward
<
<a href='https://dev.to/mcornella'>Found</a>.
* Connection #0 to host blog.mcornella.com left intact
We can see that the cURL request hits a Namecheap server (that uses Nginx, but that's not important here). This server then serves the redirect to the URL we set up, using a Location:
header and an HTTP 302 status code.
What's more interesting is what we don't see. There are no TLS negotiation steps, and it's using port 80: this request is not using HTTPS.
Security
Let's say we want to point somewhere else where security is crucial. In my case, I use suport.mcornella.com
as a shortcut to the TeamViewer QuickSupport executable, so that my clients have it easier to download.
It's important that this is served using HTTPS all the way through, since it's something that users will end up running. Otherwise, an attacker could put themselves between the user and the Namecheap server, and modify the Location
header with another URL pointing to a malicious payload masquerading as the TeamViewer QuickSupport executable.
Can we still use the previous method to do the redirect using HTTPS? This is what cURL says:
$ curl -v https://blog.mcornella.com
* Trying 162.255.119.141:443...
* TCP_NODELAY set
* connect to 162.255.119.141 port 443 failed: Connection timed out
* Failed to connect to blog.mcornella.com port 443: Connection timed out
* Closing connection 0
curl: (7) Failed to connect to blog.mcornella.com port 443: Connection timed out
As we can see, the Namecheap servers don't support HTTPS to make the redirect. And why is that, you might ask. Well, to do that, their servers don't just serve requests for our domain, they serve many other domains. They'd have to respond to each subdomain request with a custom certificate, which is significantly harder to do at the scale Namecheap operates in. It isn't impossible though, especially with Let's Encrypt. Regardless, Namecheap doesn't support this at the moment, so let's see what alternatives we have.
Securing the redirect
What do we need then? We need a hosting solution with a way to redirect to another endpoint with an automatically-generated certificate. I'll cover 2 alternatives: Vercel (previously Zeit Now), and Netlify.
Vercel
For Vercel, you first need to have an account in vercel.com. You can sign up with your GitHub account, as well as using other methods.
Next, install the Vercel CLI with npm i -g vercel
. Then, login to Vercel from the CLI with vercel login
and follow the instructions.
Next, we need to create a folder in which we'll add a vercel.json
file, with the following content:
{
"redirects": [
{
"source": "/(.*)",
"destination": "https://download.teamviewer.com/download/TeamViewerQS.exe",
"permanent": true
}
]
}
Two things to note here:
- The
source
value (/(.*)
) will match any path of the subdomain, so hitting/
,/abc
, or/an/even/longer/path
will all redirect to the destination URL. - You should replace the value of
destination
with the URL you want to redirect to.
Once you have that, deploy the folder by running vercel --prod
inside the folder we just created. This will by default get you a server running on <site-name-with-dashes>.now.sh
, which is already ready to serve the redirects. How cool is that?
Finally, set up the custom domain in Vercel, and replace the URL redirect record
in Namecheap with a CNAME
record pointing to alias.zeit.co
(this is how it works up until now, follow the instructions in the linked Vercel docs if this doesn't work).
I've found that after doing the last step, this works pretty much right after the Vercel endpoint detects the custom domain change. Also, Vercel redirects HTTP requests to the appropriate HTTPS URL out of the box:
$ curl -v suport.mcornella.com
* Trying 35.180.16.12:80...
* TCP_NODELAY set
* Connected to suport.mcornella.com (35.180.16.12) port 80 (#0)
> GET / HTTP/1.1
> Host: suport.mcornella.com
> User-Agent: curl/7.65.3
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 308 Permanent Redirect
< Date: Fri, 15 May 2020 17:15:54 GMT
< Content-Type: text/plain
< Transfer-Encoding: chunked
< Connection: keep-alive
< Location: https://suport.mcornella.com/
< Refresh: 0;url=https://suport.mcornella.com/
< x-now-trace: cdg1
< server: now
< x-vercel-id: cdg1::rdj82-1589562954711-4fc270f67df9
< x-now-id: cdg1::rdj82-1589562954711-4fc270f67df9
<
Redirecting to https://suport.mcornella.com/ (308)
* Connection #0 to host suport.mcornella.com left intact
Netlify
The setup with Netlify is pretty much the same. You can also sign up with GitHub and using other methods.
To install the CLI, run npm i -g netlify-cli
. Then, login with netlify login
.
The redirect API of Netlify is also very similar. There are two options here to specify a redirect; I'll explain using a _redirects
file. Using the netlify.toml
file allows extra options, but we don't really need them here.
As before, create a folder where we'll put a file named _redirects
, with the following content:
/* https://download.teamviewer.com/download/TeamViewerQS.exe
The first part of the line is the original path to be matched (use /*
to match all requests), and the last part is the destination path or URL.
Then, deploy the site by running netlify deploy --prod
inside the folder we just created, making sure to specify .
as the publish directory (default value).
When the site has been created, add your custom domain by following the instructions in the site dashboard. It'll ask you to add a CNAME pointing to the site URL created (<site-name-with-dashes>.netlify.app
).
Finally, verify that both the HTTP and HTTPS requests work. In the case of Netlify, the HTTP requests aren't upgrading to HTTPS automatically, but the important thing is that HTTPS requests work just the same.
Conclusion
Creating a URL redirect served via HTTPS is very easy and it costs nothing, and while some domain name registrars haven't caught up yet with the times, using Vercel and Netlify are two very good options which I'm sure you'll enjoy.
Posted on May 16, 2020
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.