Windows: redirect to `*.ipfs.localhost` fails in non-browser contexts
-
Repro steps
- Clone https://github.com/Rinse12/reproduce_kubo_windows_redirect_DNS_bug
- Run
npm install - Run
npm run repro:windowsfrom an Administrator-enabled shell on Windows; the script boots a temporary repo, then probes gateway redirects for/ipfs/<cid>(CIDv0 + CIDv1) and/ipns/<key>.
-
What happens
- The script initializes a fresh repository, pins sample content, and publishes an IPNS record using the HTTP RPC API.
- It then fetches three gateway URLs:
-
http://localhost:48180/ipfs/<cid-v0> -
http://localhost:48180/ipfs/<cid-v1> -
http://localhost:48180/ipns/<key>
-
- Each fetch receives an HTTP redirect to the corresponding subdomain (
<cid>.ipfs.localhost,<key>.ipns.localhost). Windows tries to resolve these hostnames through DNS, fails, and causesfetchto reject withTypeError: fetch failed. The script reports that the redirect-induced DNS failure occurred for all three cases.
-
Expected
- The redirected hostname should resolve locally (as it does on Linux/macOS) so that the gateway response is delivered without DNS errors.
-
Observed output excerpt
Using temporary IPFS_PATH: C:\Users\Administrator\AppData\Local\Temp\kubo-windows-redirect-repro-XXXXXX ... Generated IPNS key via RPC: k51qzi5uqu5dlmspjqtzeq0ejze6jbheg8ewrbr7bh6sd9a4u71qucvelqrp67 Published IPNS record (allowOffline). Issuing fetch (CIDv0 gateway redirect): http://localhost:48180/ipfs/QmW8zGQpaiM2fcLGAZs4s33C9ooDtzHCLhYoLJC65YzHuQ ✅ CIDv0 gateway redirect: Successfully reproduced the redirect-induced DNS failure. fetch() followed the gateway redirect to http://bafybeidt4cryxmpqcyuqqxed6dsru2wqbtdse6c5nmtgzykiftm6glu6g4.ipfs.localhost:48180/ and Windows DNS could not resolve the ipfs.localhost subdomain of localhost. Issuing fetch (CIDv1 gateway redirect): http://localhost:48180/ipfs/bafybeidt4cryxmpqcyuqqxed6dsru2wqbtdse6c5nmtgzykiftm6glu6g4 ✅ CIDv1 gateway redirect: Successfully reproduced the redirect-induced DNS failure. fetch() followed the gateway redirect to http://bafybeidt4cryxmpqcyuqqxed6dsru2wqbtdse6c5nmtgzykiftm6glu6g4.ipfs.localhost:48180/ and Windows DNS could not resolve the ipfs.localhost subdomain of localhost. Issuing fetch (IPNS gateway redirect): http://localhost:48180/ipns/k51qzi5uqu5dlmspjqtzeq0ejze6jbheg8ewrbr7bh6sd9a4u71qucvelqrp67 ✅ IPNS gateway redirect: Successfully reproduced the redirect-induced DNS failure. fetch() followed the gateway redirect to http://k51qzi5uqu5dlmspjqtzeq0ejze6jbheg8ewrbr7bh6sd9a4u71qucvelqrp67.ipns.localhost:48180/ and Windows DNS could not resolve the ipns.localhost subdomain of localhost. -
Additional notes
- Running the identical script on Linux succeeds with HTTP 200, so the behavior is OS-specific.
- The issue prevents programmatic use of the Windows gateway for IPNS names because the automatic redirect resolves to a hostname Windows cannot reach.
@Rinse12 thank you for reporting, which version of Windows is this?
No problem in browsers
FWIW I was not able to reproduce manually in browser on Windows 10 Home 22H2 19045.6332 – opening http://bafybeigdyrzt5sfp7udm7hu76uh7y26nf3efuylqabf3oclgtqy55fbzdi.ipfs.localhost:8080 works fine in both Edge and Firefox.
We've worked over the years with Igalia to ensure web browsers like Firefox and Chrome implement subdomains support and https://datatracker.ietf.org/doc/html/draft-west-let-localhost-be-localhost correctly.
Non-browser?
Is your bug about non-browser resolution in contexts like default resolver on Windows and/or Nodejs? If so, we can't do anything about that – you need to fill issue with Microsoft or Nodejs, to correctly implement loopback subdomains 🤷
Note, we have similar problems on macOS: https://github.com/ipfs/in-web-browsers/issues/206 and these commercial entities have little incentive to fix bugs like this (just being realistic: if you want a fix, you need workaround, it won't be fixed any time soon)
Workaround A: use loopback IP which is in Path mode already
I think you are just trying to use subdomains where they bring no value.
[!IMPORTANT] 👉 You don't need subdomain gateway when working programmatically in non-browser contexts. You don't get any origin isolation outside of browser. So no value in using it, and you also get extra penalty of redirect.
Note that by default:
-
localhostis configured as subdomain gateway -
127.0.0.1is configred as a path gateway
Just use the already existing path gateway on 127.0.0.1, and avoid using DNS name.
Workaround B: use Gateway port as HTTP_PROXY
There is a workaround you can try make HTTP requests in proxy mode. Kubo's gateway can act as HTTP proxy. And you can use it as a proxy for making requests to itself. This way you skip DNS resolver from operating system, and the cid.ipfs.localhost will be resolved by Kubo itself, and work even on platforms with janky DNS.
This works fine, and this is how ipfs-companion supported subdomains in Firefox before
Lmk if A or B helps (then we can close this, as there is nothing to do in Kubo), or if I misunderstood this issue (then please elaborate).
which version of Windows is this?
Windows Server 2022 Standard Evaluation, although we reproduced the same error in Github CI image windows-latest.
No problem in browsers
I haven't tested in browsers, but curl seems resolve subdomains with no problem as well. I assume browsers won't have a problem either. So far this seems like a windows native resolver or nodejs problem.
I think you are just trying to use subdomains where they bring no value.
That's true, although the kubo config I'm using is the default one and I didn't change any config. I think kubo should have different default config for Windows where there's no subdomain redirection. I guess that's the only change I think Kubo should make
Just use the already existing path gateway on 127.0.0.1, and avoid using DNS name.
Thank you that works perfectly.
I think so far our options in plebbit-js and our desktop apps are to either:
- Have plebbit-js parse kubo RPC API url and replace
localhostwith127.0.0.1(can't think of any potential pitfalls here, but if you know of any lmk) - OR set kubo config within all our desktop apps to disable redirecting (leaning towards this one)
use the already existing path gateway on 127.0.0.1, and avoid using DNS name. Thank you that works perfectly.
Nice! Since this is not about browser context, I'm leaning towards closing as resolved, but see the idea below for improving UX.
I think kubo should have different default config for Windows where there's no subdomain redirection.
I'm afraid this is not acceptable: blindly removing subdomain gateway redirect would break existing browser users AND create huge security footgun for new ones.
Perhaps to improve UX, and avoid developers like you being confused when they use localhost instead of 127.0.0.1, we could detect the request comes from non-browser client, and skip redirect?
Unsure if there is a robust way of detecting browser other than looking at User-Agent HTTP header, and expecting it to start with Mozilla. The idea of introducing hacks like that that may break in the future when browsers deprecate a header makes me uneasy.
Thoughts? Ideas?
Have plebbit-js parse kubo RPC API url and replace localhost with 127.0.0.1
Wait, you mean Gateway? Kubo RPC at :5001/api/v0 does not need subdomains, it already has unique origin due to different port than Gateway.
The default listeners for Addresses.API and Addresses.Gateway produced by ipfs init have 127.0.0.1. This means if you have localhost there, it is something you've set in your code / orchestration.
Maybe taking step back.. I am bit worried that we are missing some context here – are you using gateway for rendering web apps, or just for fetching assets and rendering them in something under your control?
RPC and Gateway are separate ports with different security constraints:
- RPC (
:5001) is POST-only admin access to your Kubo node (internal admin interface foripfsCLI and/api/v0HTTP RPC) - Gateway (`:8080) is implementation-agnostic way of retrieving and rendering deserialized data in a way that respects HTTP caching and works well in web browsers (content types etc)
-
127.0.0.1is a path gateway, turn-key for non-browser contexts that still benefit from HTTP caching, content-types and few other headers being set. -
localhostis subdomain for loading isolated websites in web browsers- Subdomain Gateway is important security feature. Loading web apps with Path gateway in browser context is a very very bad idea (you dont want plebbit's private keys, user secrets, or wallets to share the same cookies and storage with third-party JS).
-
Unsure if there is a robust way of detecting browser other than looking at User-Agent HTTP header, and expecting it to start with Mozilla. The idea of introducing hacks like that that may break in the future when browsers deprecate a header makes me uneasy.
Agreed, it seems unclean but I'm unsure what's the best way forward for kubo with this issue.
For us, we will just set all our desktop apps like Seedit, and plebbit-cli to disable redirecting by default.
If you're running a desktop app in general you would be relying on the Kubo RPC API directly, not gateway. We're gonna disable it to make sure devs in the future don't get confused when they get an ambiguous "fetch failed" error like I did.
Wait, you mean Gateway?
Yes, sorry I misspoke. I meant gateway url, if a user/dev instantinates plebbit-js with {ipfsGatewayUrls: ["http://localhost:12345"]} then we would replace it with {ipfsGatewayUrls: "http://127.0.0.1"}, although I'm leaning towards disabling redirecting altogether by default.
Maybe taking step back.. I am bit worried that we are missing some context here – are you using gateway for rendering web apps, or just for fetching assets and rendering them in something under your control?
Desktop apps embed these things:
- Kubo node
- Plebbit RPC server (Websocket)
- The RPC server connects to kubo with RPC API and pulls the data from IPFS, or pubsub
- Frontend code that pulls data from Plebbit RPC, or publish/subscribe etc
If you use a desktop app like a regular user you won't need to interact with kubo at all, but my concern is with devs who may want to fetch something directly against kubo's gateway and then get a confusing "fetch failed" error, as I did.
are you using gateway for rendering web apps, or just for fetching assets and rendering them in something under your control?
The web apps' frontend are embedded within the desktop app, so kubo is not used for loading web assets, however it's used to fetch the content to be displayed. The web apps never embed any content and all content to be populated are fetched through kubo.
Thank you for explanation, very useful. I've filled an upstream issue:
- https://github.com/ipfs/boxo/issues/1054
An ask from my end is to not ask your users to "remove localhost". Just fix localhost → 127.0.0.1 on the fly to avoid unnecessary redirects. Even on linux they make no sense for your use case. We already do that optimization in places like Companion, WebUI to ensure users get subdomain or path gateway where it makes sense.
Once https://github.com/ipfs/boxo/issues/1054 ships in the future this fix will no longer be necessary.
Unrelated, but can we reopen this issue? The bug seems to persist on my end