Change What localhost Resolves to in Windows for Testing IE/Edge on Parallels or VirtualBox VM
Not long ago I started at a new company, and the first project I worked on was configured to run (and has config that expects to be) on http://localhost:8888. So far so not very unusual. Everything was hunky-dory until I needed to test on IE11. At that point, because I work primarily on a Mac, I needed to get my Windows Parallels (or VirtualBox) VM to resolve localhost
to something other than the loopback adapter (::1 for IPv6 or 127.0.0.1 for IPv4).
For any power user or certainly any dev, we know the easy way to add custom name resolution is to put an entry into our hosts
file, which on Windows is under cd \Windows\System32\drivers\etc
. Maybe you even read this article telling you exactly how to do this for VirtualBox. Just notepad hosts
in that directory, add an entry like 192.168.1.23 localhost
, save, and voila! It works!
OR NOT. After copious googling and trying lots of things that don’t work (like disabling IPv6, for instance), I learned that sometime in Windows Vista, Windows added a default resolution for localhost into the actual DNS resolver on Windows. If you have an unmodified hosts file, it tells you this right in it:
# localhost name resolution is handled within DNS itself.
# 127.0.0.1 localhost
# ::1 localhost
Great. Save people the trouble of adding those entries, but you should be able to just add an entry anyways to override that, right? Sure. That works!
OR NOT. The problem is that at some point between Windows Vista and Windows 8.1 (I’ve been able to narrow it down only that far), there has been a Windows update that prevents changing what localhost resolves to. I was only able to narrow that down because I have a colleague with an old Windows 8 image for which this works, but if you try either the Win8.1 or Win10 images from Microsoft’s free images expressly for this kind of testing, it will not work. Nor did my custom install of Win10 on Parallels.
The Solution
As of writing, you can grab the IE11 on Win7 image from there, and at least it will still allow you to override localhost resolution in the hosts file. So if you really must use localhost
and only that, this is a viable option, at least as long/until the same patch makes its way into Windows 7. I was curious to see if an update to Win7 would break it, but as of publishing this, I fully updated the Win7 image (to Version 6.1.7601 Service Pack 1 Build 7601), and it still let me change localhost. YMMV. I mainly wanted to do this so that IE11 would be as fully patched as it could be to better reflect “the wild.”
Other Possibly Better Options
These may also work..
Don’t Use localhost
The obvious and arguably “right” way to solve this problem is to update your app to not require running on localhost
for local development/testing. Many apps work fine out of the box this way — you can just type in the IP address, and it works, or you can add a custom URL like localmac.example.test
to your hosts file if you want something not reliant on your IP directly.
Side Note: If you grew into the habit of using .dev
as a TLD for your test URLs, you should no longer do that. I learned this the hard way at a prior company. As of some Chrome version, Google takes that TLD over — they own it and force it to HTTPS. So you should use .test
to save yourself some headache.
The side benefit of this approach is it can make testing from other devices easier, as well.
Use a Forward Proxy in IIS
In my meanderings while working on this problem, I came across this answer that explains how to set up the local IIS on the VM to proxy to your VM’s host. It’s based on this article, in case the post goes away for some reason. A couple additional pointers:
- You want to configure ARR and URL Rewrite with the server node for your machine selected. I accidentally tried configuring on the Default Web Site, and it wasn’t working.
- Be careful about the rewrite URL. I had a small typo in it, and was going crazy trying to figure out why it wasn’t working. (In my case, was missing the
:
between the host and port.)
My Recommendation
My recommendation is to just not use localhost. In my case, I was trying to “fit in” and not change the project/require extra different config, since other colleagues were saying “works on mine.” But it’s just a PITA, and given that clearly Windows (and other random posters on various StackOverflow comments) think that changing localhost
resolution is a Bad Idea, I think the better solution is to avoid requiring a specific name during testing, or to use something not localhost.
Bonus: We happened to be using a version of create-react-app on this project, which uses react-scripts
. That includes the ability to surface environment variables to your React app, and it supports dotenv
and dotenv-expand
, which gives you lots of nifty built in options for standard environment config, along with the ability to override locally without impacting your fellow colleagues.
UPDATE (16 Oct 2018): A long-time colleague of mine, Ken Schaefer, suggests that probably the reason the Windows behavior changed was due to RFC6761, particularly Section 6.3. It basically says that localhost
should always resolve to the loopback adapter. And of course there are potential security vulnerabilities if it does not. Oddly enough, this is one case where Windows is being more restrictive than macOS. And if I didn’t have the special case I do, it wouldn’t matter at all. All the more reason to go with the recommended route above, I’d say.