little-bear-labs / ipfs-chromium

20 stars 1 forks source link

ENS support? #28

Closed livid closed 2 months ago

livid commented 1 year ago

Currently, the experimental build works great with IPNS address:

Screenshot 2023-06-01 at 6 46 13 PM

But when I tried to open an ENS address like ipns://vitalik.eth or ipns://planetable.eth, it shows this error:

Screenshot 2023-06-01 at 6 54 26 PM
John-LittleBearLabs commented 1 year ago

Indeed this was simply outside the scope of this initial push for proof-of-concept. We could consider putting it in doc/todo.md. I'll leave this issue open either way.

I'm guessing on your machine you'd normally resolve .eth with browser-level support and not a DNS server with .eth support? I have to wonder if the latter might already work.

In the POC since "vitalik.eth" doesn't parse as an IPNS CID/PeerId/key, it's going to treat it as DNSLink. The way this works currently is it's using Chromium's built-in DNS mechanisms, which normally has a chain of preferred methods with setup (etc., etc.) but we're asking for TXT records and only one mechanism actually supports that: the net::DNSClient class. That's pretty basic level DNS stuff, and you can quickly see what it should send back to my code (if everything's working properly) by doing a simple host -t TXT _dnslink.<host>

Unfortunately appending .link does not work, either.

$host -t TXT _dnslink.vitalik.eth.link
_dnslink.vitalik.eth.link is an alias for resolver.cloudflare-eth.com.

Since upstream Chromium doesn't support .eth , I don't believe, it might be worth having a parallel effort to upstream that, and then we could integrate with their work?

livid commented 1 year ago

go-ipfs (kubo) has built-in ENS support. The following would work:

https://ipfs.io/ipns/vitalik.eth/

Or if you have a go-ipfs daemon running on localhost:8080, this would work:

curl -H "Host: vitalik.eth" http://127.0.0.1:8080

Internally it uses DoH to resolve *.eth and only expects a TXT response for any DNSLink pointing to IPNS or CID.

https://github.com/ipfs/kubo/blob/master/docs/config.md#dnsresolvers

I am not familiar with the Chromium codebase. Is it possible to create such an override for *.eth to use an external DNS-over-HTTP for DNSLink? So they can be resolved to IPNS/CID that the current experimental build already supports.

John-LittleBearLabs commented 1 year ago

Thanks for that - didn't actually realize Kubo supported that. Do you know if anything like that is in a spec somewhere - I've been trying to stick to that as I want to be compatible with the other gateway implementations coming up.

That said, Kubo's gateway does not resolve .eth for me in a verifiable way at least not the same way it does for IPNS. Try your URL with the parameter ?format=ipns-record, and you get: illegal base32 data at input byte 6. So it looks like I can't get a verifiable signature, so I can't prove locally that the record seems correct. I suspect that's because it's really more of a DNSLink thing and not really IPNS, so it's not going to be verifiable in any case. Going through gateways does change the trust profile, though. I would have to drop the claim that it's a verifying client and tell people to either avoid this feature or configure only gateways they trust not to lie to them (currently they can't configure - that's a big TODO). Whereas today I'm essentially trusting their DNS configuration if they attempt a DNSLink address, but there was never any claim to the contrary (or really any way around it).

The restriction to Chromium's DNSClient is because I'm requesting TXT records using native mechanisms, and sadly/oddly not even the "system resolver" supports TXT. And DNSLink needs a TXT to work.

I assume this restriction is because TXT was never a priority for a browser, which is generally interested in host resolution to IPs. This shortcoming is not well-documented and it took me a while to figure out why was causing a failure for me - Chromium tries to match your system's resolution configuration (an honorable attempt, I would assume, to make sure hosts resolve the same in the browser as they do for other programs if they resolve at all), but when it ran into a configured method in the list that it didn't support it bailed and dropped the rest, so for me (on a pretty standard Fedora install), I didn't have DNSClient in the mix at all and couldn't get any TXT records.

In the first pass we do want to minimize changes to very low-level Chromium code (in //net for example). But this could be a motivating feature to justify why we'd want to allow TXT to hit CreateDohProbeRunner . But then it raises a new question. Are we going to add a DoH server for the user, to make sure they have one that can serve ENS? It would abandon the idea of trying to match other processes' ways of resolving things (probably even for non-ENS addresses, I know if my email client wasn't working but I could use webmail this is not something that would even occur to me to check). And if that's the case maybe it doesn't make sense to try to use Chromium's DNS at all - maybe we issue an HTTPS request to a eth.link or whatever...

No matter how we want to approach this, it's not a trivial change. And, depending on how the upstreaming conversation goes, the next step might be to re-implement these same features at a much lower layer in the Chromium architecture, which would completely change how I'd even be thinking about this (e.g. if the code is in //net one could easily be manually selecting DNS resolution mechanisms rather than designing a high-level request object). So I'm not going to try to slap something together in a few minutes of free time. I would be open to pull request from someone else, and as long as that doesn't happen I'll keep this in mind as the design & approach get shuffled around and if we get a second pass I'll check with others about the priority for ENS.

Thanks again for bringing this up and shedding some light on it. I hope you don't mind if I leave this issue open as a public reminder and as something that could be referenced if someone wanted to do a PR.

livid commented 1 year ago

Thank you so much for your analysis.

On a related note, Brave browser supported this in early 2021:

https://brave.com/ipfs-support/

Both Brave and Kubo are using Cloudflare's special purpose DoH server to resolve .eth and other blockchain domains.

For example:

curl -H 'content-type: application/dns-json' 'https://resolver.cloudflare-eth.com/dns-query?type=TXT&name=vitalik.eth'

Would get a response like this:

{"AD":true,"CD":false,"RA":true,"RD":true,"TC":false,"Status":0,"Question":[{"name":"vitalik.eth.","type":16}],"Answer":[{"name":"vitalik.eth","type":16,"TTL":3600,"data":"\"dnslink=/ipfs/bafybeieexfyfk3blzpi7g7j3aaogyvlg7qhopr7ru5x5v3nxrlx5zihnaa\""},{"name":"vitalik.eth","type":16,"TTL":3600,"data":"\"contenthash=0xe3010170122084b970556c2bcbd1f37d3b001c6c5566fc0ee7c7f1a76fdaedb78aefdca0ed00\""},{"name":"vitalik.eth","type":16,"TTL":3600,"data":"\"a=0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045\""}]}

For a long time, Cloudflare's DoH server was the only one that can support that, and it was not very stable:

https://github.com/ipfs/kubo/issues/8836

Then we have another ENS DoH server maintained by ETH.LIMO:

curl -H "Accpet: application/dns-json" "https://dns.eth.limo/dns-query?name=planetable.eth"

Response:

{"Status":"0","RD":false,"RA":false,"AD":false,"CD":false,"TC":false,"Question":[{"type":16,"name":"planetable.eth"}],"Answer":[{"type":16,"name":"planetable.eth","data":"dnslink=/ipns/k51qzi5uqu5dgv8kzl1anc0m74n6t9ffdjnypdh846ct5wgpljc7rulynxa74a/","ttl":600}]}

ETH.LIMO's DoH only responds TXT record if a Content Hash if set on an ENS domain:

https://app.ens.domains/planetable.eth

That is good enough to work with kubo's config to get ENS resolved.

These things are more or less first-of-its-kind since ENS is probably the only blockchain-powered domain name system that has a vibrant DWeb community now.

lidel commented 1 year ago

I think support for custom DNSLink resolvers is

The focus is IPFS and end-to-end verifiable (CID/IPNS) websites.

Some thoughts/historical context below.

Quick reminder ENS over DNS is not verifiable, requires trust in DNS resolver that did the ENS work

We have no ENS support in IPFS. There is no requirement for Ethereum blockchain client or libraries in IPFS. Human-readable names in IPFS are based on RFC1035-compliant DNS TXT records, as specified by DNSLink.
There is no vendor-lock in to any specific software, or blockchain.

Resolution of .eth in Kubo/Brave is based on third-party ENS2DNS resolvers, like https://github.com/wealdtech/coredns-ens. This means ENS verification happens on some third-party server, and unlike signed IPNS, the returned ENS+DNS response can't be verified on its own. This means you trust DNS resolver did not lie to you and gave you correct ENS value.

On existing ENS support in ecosystem

Why .eth is resolved by default in Brave

They already had support for ENS. ENS names in http:// URLs was in Brave before they added ipfs:// :)

Why .eth is resolved by default in Kubo

We've made a mistake in Kubo years ago and now have to support implicit resolver for .eth (ENS) and .crypto (Unstoppable Domains) to not break existing users. We did not add any other "alternatives to ICANN", such as Handshake, instead provide DNS.Resolvers config for users to choose and opt-in themselves. For implicit ENS resolver (Cloudflare), there is a way to override default resolver for these TLDs via config, so we respect user agency.

ENS+DNSLink is already supported by ipfs-chromium, as long your DNS resolver does

ipfs-chromium supports DNSLink, and if the system's DNS resolver supports ENS, it will work already. If you want to have ENS resolution that is verified end-to-end, you will run your on ENS resolver on the same machine, and use something like core-ens+full Ethereum blockchain node as your DNS resolver for .eth. zone.

Ways to improve UX of working with custom TLD resolvers

So the open topic here is if ipfs-chromium should hard-code DoH endpoint for specific TLD, to enable use cases like ENS or OpenNIC.

Hard-coding DNS resolver without the ability to disable/override defaults breaks user agency, not acceptable for web browser. If such a feature is ever added, there has to be a generic way to configure DNS resolver used by the browser, globally or per TLD, with more than one DoH endpoint to support resiliency and fallbacks, and this can't be specific to ENS.

My answer would be no, or at least low priority due to the feature creep, because you also need to: