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

IPIP-296: DNSLink resolution export with DNSSEC records #296

Closed
wants to merge 10 commits into from

Conversation

iowaguy
Copy link

@iowaguy iowaguy commented Jul 6, 2022

A full spec of the idea proposed in ipfs/kubo#8799 and ipfs/kubo#6129.

In the current gateway, clients are forced to trust the DNS and IPNS resolutions of the gateway. This proposal reduces the trust needed by a client, and allows honest gateways to prove it is responding truthfully. It does does this by serializing the DNSSEC responses along with the CAR requested by the client.

@iowaguy iowaguy requested a review from lidel as a code owner July 6, 2022 20:14
@lidel lidel changed the title Gateway: DNS resolution export with DNSSEC records IPIP: Gateway: DNS resolution export with DNSSEC records Jul 25, 2022
@lidel lidel changed the title IPIP: Gateway: DNS resolution export with DNSSEC records IPIP: DNS resolution export with DNSSEC records Jul 25, 2022
Copy link
Member

@lidel lidel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for submitting this @iowaguy and apologies it took long to review.
(I discussed this briefly in Iceland with @thibmeu, but this is my proper first pass at this IPIP)

Quick feedback (first pass)

The high level feedback on "How do the components work together" is that in the proposed form, IpfsDnssecChain response it is not flexible enough to allow clients to fully benefit from content-addressing.

Having "all-in-one" (proof+car) type of response is fine, but the spec should also allow for decoupling DNSLink's DNSSEC proof from the data transfer and fetching them separately.

Asks / Rationale

There are additional design constraints that we should include in this spec.

Clients should be able to:

  • Fetch DNSSEC proof alone, without content-addressed data
    • cache proof and avoid fetching proof multiple times
    • make smart decisions about which blocks/CIDs should be fetched (data deduplication, using multiple gateways/transports for redundancy)
  • Fetch DNSSEC proof for both DNSLink and DNSAddr
    • DNSAddr TXT records work the same as DNSLink ones, but for peer routing. They are optional, but their presence allows fast recovery when HTTP is down, skipping DHT lookup and opportunistically doing bitswap with trusted provider endpoint etc.
  • Send a single request and receive end-to-end "DNSLink integrity manifest". This is more than a single DNSSEC proof, because:
    • DNSLinks can be recursive
      • gateway should return integrity proofs for the entire chain up to the final immutable CID (with a limit of 32 jumps or so – that is the resolution limit in Kubo gateway today).
    • DNSLinks can point at mutable /ipns/FQDN or /ipns/KEY
      • this means "DNSLink integrity manifest" should include DNSSEC proofs for all recursive DNSLink TXT records and all Signed IPNS Record (if dnslink=/ipns/KEY was found during the resolution)

http-gateways/DNSSEC_EXPORT_DNSLINK.md Outdated Show resolved Hide resolved
http-gateways/DNSSEC_EXPORT_DNSLINK.md Outdated Show resolved Hide resolved
http-gateways/DNSSEC_EXPORT_DNSLINK.md Outdated Show resolved Hide resolved
http-gateways/DNSSEC_EXPORT_DNSLINK.md Outdated Show resolved Hide resolved
http-gateways/DNSSEC_EXPORT_DNSLINK.md Outdated Show resolved Hide resolved
Comment on lines +187 to +191
struct DnssecProof {
uint16 initial_key_tag;
uint8 num_zones;
ZonePair zones[num_zones];
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭
If we decouple content-addressed data from DNSSEC proof, then THIS alone could be what the client receives when they request application/vnd.dnslink.dnssec; version=1.

Ensuring this struct is useful to clients (such as web browsers) should be our main focus.

Reusing existing RFC formats where possible is 👍
Will ping some browser folks for review here.

Comment on lines +302 to +303
### Security
DDoS Amplification: For each request to the gateway, a request must be made to the resolver and to IPFS, leading to several server-side computations. However, This information is cacheable, which should reduce the risk.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the main concern here is that DNSLink's DNSSEC proofs should not be returned with every block or CAR.

The client needs to fetch the proof only once, and the proof, once generated, can be cached for some time. I think this spec should explicitly state that proof can be cached by the gateway for at least 60 seconds, and up to the TTL of the TXT record.

This should mitigate use of proof requests as a surface for DoS.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Requiring a minimum TTL could go against DNS behaviour, and adding a new layer of cache should be left to the gateway operator.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, I forgot we already talked about his around DNS.MaxCacheTTL.

Ignore my comment then, no special treatment here,
gateway and client should reuse DNS cache around TTL value for TXT record with DNSLink.



## Open Problems
The DNS query (via DNSLink) will often not resolve to a CID. It may resolve to either a CID with a subresource (e.g. /ipfs/QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG/readme) or it may resolve to an IPNS name (e.g. /ipns/QmSrPmbaUKA3ZodhzPWZnpFgcPMFWF4QsxXbkWfEptTBJd). Regarding subresources: our choice is either to have the client do the recursive resolution, or do the resolution on the server side. As the point of this spec is to avoid client side DNSSEC resolutions, it would probably make more sense to go with the second approach. However, this second approach may involve adding new headers to the CAR.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭
re: subresource, if we decouple data from proof response, the problem of subresources goes away: no need to trust gateway did resolution right, the client will fetch root CID block to learn about CID of subresource.

## Open Problems
The DNS query (via DNSLink) will often not resolve to a CID. It may resolve to either a CID with a subresource (e.g. /ipfs/QmYwAPJzv5CZsnA625s3Xf2nemtYgPpHdWEz79ojWnPbdG/readme) or it may resolve to an IPNS name (e.g. /ipns/QmSrPmbaUKA3ZodhzPWZnpFgcPMFWF4QsxXbkWfEptTBJd). Regarding subresources: our choice is either to have the client do the recursive resolution, or do the resolution on the server side. As the point of this spec is to avoid client side DNSSEC resolutions, it would probably make more sense to go with the second approach. However, this second approach may involve adding new headers to the CAR.

Regarding IPNS names: we can most likely serialize the IPNS proof using similar techniques as described above.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good point. It would be good to clearly state the scope of this Version 1 spec.

Sidenote: context on recursive DNSLinks

If the DNSLink value is /ipfs/.. then the story is simple, we have two distinct stages of resolution and DNSSEC proof closes the gap, allowing clients to display end-to-end integrity indicators:

flowchart LR
    dnslink=/ipfs/CID-->/ipfs/CID
    subgraph DNSSEC
      example.com-->dnslink=/ipfs/CID
    end
    subgraph IPFS
    /ipfs/CID-->DAG
    DAG-->blocks
    end

If we add /ipns/ to the picture, that namespace requires an additional resolution step: /ipns/ path can point at an IPNS KEY or another domain name (FQDN), which requires doing recursive DNSLink resolution. This resolution creates more complexity and potential gap around client's ability to verify signed IPNS records (KEY ones):

To illustrate:

flowchart TB
    dnslink=/ipfs/CID-->/ipfs/CID
    FQDN-->dnslink=/ipns/KEY
    dnslink=/ipns/KEY-->/ipfs/CID
    dnslink=/ipns/KEY-->/ipfs/CID
    /ipns/FQDN-->FQDN
    /ipns/KEY-->/ipfs/CID
    
    subgraph DNSSEC
      FQDN-->dnslink=/ipfs/CID
      FQDN-->dnslink=/ipns/KEY
      FQDN-->dnslink=/ipns/FQDN
    end
    subgraph IPNS    
      dnslink=/ipns/KEY-->/ipfs/CID
      dnslink=/ipns/KEY-->/ipns/KEY
      dnslink=/ipns/KEY-->/ipns/FQDN
      dnslink=/ipns/FQDN-->/ipns/FQDN

     
    end
    subgraph IPFS
      /ipfs/CID-->CID
      CID-->DAG
      DAG-->blocks
    end

What to do with /ipns/ ?

For Version 1, we could say the /ipns/ gap is out of the scope and needs to be resolved client-side.

I think we don't need to worry about dnslink=/ipns/FQDN – client will be able to send follow-up DNSSEC proof requests for the new FQDN, and do that recursive dance until a non-DNS, cryptographically verifiable path is found.

Open problem / need for spec: fetching signed IPNS records from Gateway

I think Gateways should support a scenario where dnslink=/ipns/KEY.
Many clients won't be able to retrieve IPNS records (no p2p, no dht), and asking clients to implement delegated routing via separate protocol like reframe (allowing light clients to fetch Signed IPNS Records) may be a stretch for many.

I think the Gateway should provide a way for a client to request IPNS proof (signed IPNS record) in a way that is as easy as requesting a DNSSEC one.

Details TBD, but my initial take is that either

  • "IPNS proof" should be a separate request-response type, allowing clients to resolve and cache IPNS resolutions independently, or

  • part of unified application/vnd.dnslink.integrity; version=1 response that returns both DNSSEC proof and (optional) IPNS signed record, broad strokes:

    struct DnslinkIntegrity {
      DnssecProofs dnssecProofs;
      SignedIPNSRecords ipnsRecords;
    }
    struct DnssecProofs {
      uint32 length;
      IpfsDnssecChain chains[length];
    }
    struct SignedIPNSRecords {
      uint32 length;
      IPNSRecord records[length];
    }

To make things easier for light clients, we should lean towards the latter one. A single request-response made by a thin client that can be cached for the duration of the retrieval session.

ipfs --> Gateway: IPFS file
```

### Reduced TLS DNSSEC Chain Extension
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💭
Needs clarification: since "Reduced TLS DNSSEC Chain Extension" here is based on RFC 9102, does it also include setting dnssec_chain flag on request's TLS handshake?

My feedback here is that custom TLS is a very big ask for everyone to implement, and limits the utility of DNSLink proofs on Gateways, especially given they can be decoupled from retrieving content-addressed data. Ok to experiment, but we should always have a plain way for fetching them without messing with TLS layer.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Reduced TLS DNSSEC Chain Extension is an experimental RFC, which has inspired some of the design in this IPIP. There is no ask for gateways to implement a custom TLS layer.

@lidel lidel changed the title IPIP: DNS resolution export with DNSSEC records IPIP: DNSLink resolution export with DNSSEC records Jul 28, 2022
iowaguy and others added 7 commits August 2, 2022 11:21
Co-authored-by: Marcin Rataj <lidel@lidel.org>
Co-authored-by: Marcin Rataj <lidel@lidel.org>
Co-authored-by: Marcin Rataj <lidel@lidel.org>
Co-authored-by: Marcin Rataj <lidel@lidel.org>
Co-authored-by: Marcin Rataj <lidel@lidel.org>
Copy link
Member

@lidel lidel left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We've discussed this last week, and my understanding of next steps is that Cloudflare will prototype DNSSEC proofs as an extension of DNS-over-HTTPS specification.
This will be independent of IPFS, and have utility beyond securing DNSLink TXT records.

When that thing exists, we can get back to this discussion, and see if Gateways could reuse that work and expose the same proofs for DNSLinks, and also include signed IPNS records (covering entire /ipns/ proof space).

@iowaguy is it ok to close this PR for now, or do you want to keep it as draft?

@lidel lidel added the status/blocked Unable to be worked further until needs are met label Aug 18, 2022
@iowaguy
Copy link
Author

iowaguy commented Aug 18, 2022 via email

@lidel lidel changed the title IPIP: DNSLink resolution export with DNSSEC records IPIP-296: DNSLink resolution export with DNSSEC records Oct 26, 2022
@lidel lidel closed this Jan 12, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status/blocked Unable to be worked further until needs are met
Projects
Status: Deferred
Development

Successfully merging this pull request may close these issues.

None yet

4 participants