Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Companion should auto resolve ENS names to IPFS #678

Closed
momack2 opened this issue Feb 9, 2019 · 9 comments · Fixed by #797
Closed

Companion should auto resolve ENS names to IPFS #678

momack2 opened this issue Feb 9, 2019 · 9 comments · Fixed by #797
Labels
exp/intermediate Prior experience is likely helpful help wanted Seeking public contribution on this issue kind/enhancement A net-new feature or improvement to an existing feature P2 Medium: Good to have, but can wait until someone steps up status/deferred Conscious decision to pause or backlog

Comments

@momack2
Copy link

momack2 commented Feb 9, 2019

People are using ENS names as a way to find content on IPFS (ex https://twitter.com/eduadiez/status/1093547099235516416). Let's make it even easier by enabling companion to resolve links like ipfs://foo.eth to the appropriate IPFS hash + content!

Would it potentially also be possible to check for any .eth links to see if they are hosted on IPFS and if so resolve through IPFS?

@lidel
Copy link
Member

lidel commented Feb 11, 2019

(sorry for any mistakes, went on a research spree and wanted to post this while I have entire context in my head)

tl;dr

I did an initial run over prior art for ENS support and identified some techiques and challenges. Notes below. Overall, it should be possible to do, but we may need to land some changes in go-ipfs or public gateway.

Unexpectedly, this research gave me an idea how to solve Origin problem for localhost gateway(!) – see ipfs/kubo#5982 ← i am really excited about this one!

(1) ENS lookup without running Ethereum client

The main challenge will be resolving ENS to IPFS CID from Ethereum transaction without running Ethereum client (and avoid shipping half of MetaMask or additional binary just to resolve ENS domains)

Most of the prior art ships ethereum client in some form:

Potential solutions:

  • (1A) Lookups via some HTTP API

    • One way to do it is to do lookups via remote HTTP API (similar to DNSLink detection with embedded js-ipfs). I did some research and it seems ethjs-ens supports doing lookups via third-party HTTP resolver (ethjs-provider-http). We could use well-known public one (eg. infura), or run our own endpoint.
    • a neat way to do this would be to reuse existing /api/v0/dns endpoint in go-ipfs (used for DNSLink lookups) and make it support .eth domains. This way we would have a reliable resolver at both localhost go-ipfs and public gateway for use by js-ipfs in browser context.
      • digression: to avoid shipping ethereum client with go-ipfs we could just hardcode 'trusted' endpoint for .eth lookups, but it smells a bit, if we go this route we probably should keep HTTP API lookup in ipfs-companion as sugested in (2B)
  • (1B) Delegate act of ENS resolution to remote resolver, then redirect to ENS-aware HTTP proxy or gateway

    • does not add any dependencies to ipfs-companion
    • see (2) below
  • (1C) ?

(2) Support foo.eth domains in browser

Prior art: ens-gateway-eth-domain extension seems to do interesting hacks to solve UX challenges:

  • registers a proxy for *.eth and points at unencrypted HTTP port [sic!] at some IP owned by some company (159.203.100.160:80)
    • if domain that was not used recently(?), remote server returns HTTP 404 for requested Host (screenshot)
    • extension detects 404 for *.eth and replaces the tab with HTML-based handler shipped with extension itself, in the background ENS resolution happens and user is then presented with blue button "Visit website" (screenshot)
  • foo.eth loaded from remote proxy works, hostname is in location bar, but transport layer is unencrypted (screenshot)

Known Limitations:

  • .eth is not a valid/known tld, so foo.eth is not supported in location bar, needs to be http://foo.eth
  • remote proxy is unable to provide certificate for a domain with bogus TLD, so transport is unencrypted HTTP (not an issue is HTTP proxy runs on localhost)

Potential solutions (given lessons learned from above prior art):

  • (Solution 2A) redirect *.eth to go-ipfs being ENS-aware HTTP proxy
    • this could be HTTP port of go-ipfs running on localhost or separate, simple service at some remote IP provided by PL (used as a fallback when companion runs with embedded js-ipfs)
    • (preferaly localhost port, to avoid unencrypted HTTP over public internet)
    • "ENS-aware HTTP proxy" would work like this:
      • read Host HTTP Header
        • if ENS is in cache, return immediately
        • if ENS is not in cache, return some 'wait' code (eg. 305 Use Proxy) and perform ENS loookup (similar to existing DNS lookup for /api/v0/dns) in the background, as suggested in (1A)
          • ipfs-companion detects 'wait' HTTP code and displays loading screen + retries in background via HEAD request until gets response other than 'wait'
      • if ENS points at IPFS, return HTTP 200 with payload like a regular gateway
      • if ENS points at non-IPFS content, return some other code + (TBD)
    • Alternatively, ENS-aware HTTP proxy would just block until ENS is resolved 🙃
  • (Solution 2B) do lookup in companion and redirect *.eth to go-ipfs HTTP proxy
    • similar to 2A, but go-ipfs does not need to know anything about ENS, we just redirect to <foo>.ipfs.localhost or <bar>.ipns.localhost

Benefits of running "resolver as HTTP proxy"

Just to reiterate why this approach is exciting:

  • we do not add any additional pieces to existing stack (go-ipfs+ipfs-companion or public gateway + ipfs-companion)
  • simple setup - just set HTTP proxy - and we are able to add support for ENS and other naming systems (Namecoin's *.bit ?) as we go
  • cool side-effect if go-ipfs acts as HTTP proxy: we are able to support <cidv1b32>.ipfs.localhost solving Origin problem for local gateway at go-ipfs

Related Reading

@lidel lidel added kind/enhancement A net-new feature or improvement to an existing feature help wanted Seeking public contribution on this issue UX exp/intermediate Prior experience is likely helpful P2 Medium: Good to have, but can wait until someone steps up status/deferred Conscious decision to pause or backlog labels Feb 11, 2019
@parkan
Copy link

parkan commented Feb 14, 2019

FWIW I am unable to load the ENS resolvers (other than manually looking it up in the ENS manager):

DOES NOT work

works

https://manager.ens.domains/name/oasis.dappnode.eth (needs to be set to mainnet), click through to https://gateway.ipfs.io/ipfs/QmXXnnme2tC1JVxvHMM52xwy1gDfZnymrA1soTwiMTLqRK

@parkan
Copy link

parkan commented Feb 14, 2019

I still need to process @lidel's post fully (a lot of info there!) but a question that came to mind regarding the "bogus" nature of the domain is: how does .local and go work? I am fairly sure I've used internal network sites at past jobs that had SSL certs -- were those just forcibly added to the machine?

@lidel
Copy link
Member

lidel commented Feb 15, 2019

@parkan In short, domain resolution is effectively delegated to HTTP Proxy. If we make go-ipfs work as an HTTP Proxy it will be able to create responses for arbitrary domains on the fly. (I wrote some initial notes in ipfs/kubo#5982)

As for SSL, yes, it is possible to have HTTPS for a fake intranet domain. In bigger orgs machines handed out to employees often come with additional CA Root cert in system keystore, or some VPN software injects it. That CA is responsible for validation of certs for fake domains (and make employer able to look into HTTPS traffic).

@lidel
Copy link
Member

lidel commented Mar 14, 2019

Quick brain dump about "light/delegated ENS resolver" (a way to deliver 1B)

Note: This comment was extracted to https://github.com/protocol/collab-ens/issues/1

  • Goal: enable ENS lookups in contexts where running ethereum client is not feasible
  • How: do not invent things, as a part of migration path we should reuse DNS libraries and formats, especially DNS-over-HTTPS
  • What: DNS server responding to queries with domains within .eth TLD
    • returns A record with IP of HTTP gateway that gives access to ENS websites to people without Ethereum or IPNS clients:
      e.g. <domain-name>.eth.link
    • returns TXT record with the value of ENS record
      • if ENS points at IPFS, it would look like regular DNSLink, reusing all the code that already supports it
  • Does not need to be binary, MVP could just be DNS-over-HTTPS with JSON API (to enable use in ipfs-companion)

Value added by delegated approach:

  • Enables ENS support in legacy software that only speaks DNS and HTTP.
  • IPFS Companion could validate ENS names via ENS-over-HTTP JSON API.
  • GO-IPFS could simply send DNSLink lookups to a different DNS server when /ipns/<domain-name>.eth is requested (keeping changes to go-ipfs extremely minimal)
  • Browser vendors could add support for ENS by simply swapping DNS-over-HTTPS server for .eth TLD, or adding support to their own servers

@parkan
Copy link

parkan commented Mar 21, 2019

would be good to mirror/summarize this in https://github.com/protocol/collab-ens/

@parkan
Copy link

parkan commented Mar 21, 2019

it may also be worthwhile to step back a moment and consider how the DNS zone hierarchy is structured and to what extent does the ENS system follow or diverge from that: for example, if we consider ENS as simply the authoritative nameserver for the .eth zone (enacted via dns-over-https), could there be an even more elegant way to incorporate it?

although, perhaps fudging TXT records with a prefix is not quite elegant per se

@lidel
Copy link
Member

lidel commented Mar 22, 2019

@parkan I've extracted "DNS" and "HTTP Proxy" to issues there. LEt me know if something else should be extracted.

[..] if we consider ENS as simply the authoritative nameserver for the .eth zone (enacted via dns-over-https), could there be an even more elegant way to incorporate it?

I believe that if DNS-compatible ENS resolver exists and follows DNS RFCs, plugging it into mainstream DNS as the authoritative nameserver for *.eth could happen, but requires some entity to pay ICANN for that TLD (https://newgtlds.icann.org/en/)

@parkan
Copy link

parkan commented Mar 28, 2019

thank you, that will help direct the work across the various participants!

the TLD is... $200k or so? that's approximately one Lambo, maybe someone in the Ethereum community can swing that 😆

lidel added a commit that referenced this issue Oct 17, 2019
This change builds on top of #783 and:

-  adds support for recovery from DNS lookup failures
-  enables recovery for all HTTP Codes >= 400 
-  recovers `.eth` DNS failures bu reopening website on EthDNS gateway at `.eth.link`
-  simplifies some code paths and adds more tests

Motivation:

When a third-party IPFS gateway is discontinued or censored at DNS level, the IPFS Companion should retry request using currently active gateway set by the user (public or local).

We also want to recover in situation when website with DNSLink has a valid DNS `TXT` record, but HTTP behind `A` record is down or unreachable.

*Note*: right now the only real use for DNS recovery is support of .eth TLD via .eth.link gateway, however in the future this could provide means of working around DNS-based censorship (eg. by executing DNSLink lookups over libp2p as a fallback).

closes #678, closes #640
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
exp/intermediate Prior experience is likely helpful help wanted Seeking public contribution on this issue kind/enhancement A net-new feature or improvement to an existing feature P2 Medium: Good to have, but can wait until someone steps up status/deferred Conscious decision to pause or backlog
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants