mirror of
https://github.com/ipfs/kubo.git
synced 2025-09-10 05:52:20 +08:00
Make dns resolve paths under _dnslink.
Thus allowing to CNAME main site entry to gateway and stil specify dnslink. License: MIT Signed-off-by: Jakub Sztandera <kubuxu@gmail.com>
This commit is contained in:
@ -41,33 +41,76 @@ func (r *DNSResolver) ResolveN(ctx context.Context, name string, depth int) (pat
|
||||
return resolve(ctx, r, name, depth, "/ipns/")
|
||||
}
|
||||
|
||||
type lookupRes struct {
|
||||
path path.Path
|
||||
error error
|
||||
}
|
||||
|
||||
// resolveOnce implements resolver.
|
||||
// TXT records for a given domain name should contain a b58
|
||||
// encoded multihash.
|
||||
func (r *DNSResolver) resolveOnce(ctx context.Context, name string) (path.Path, error) {
|
||||
segments := strings.SplitN(name, "/", 2)
|
||||
domain := segments[0]
|
||||
|
||||
if !isd.IsDomain(segments[0]) {
|
||||
if !isd.IsDomain(domain) {
|
||||
return "", errors.New("not a valid domain name")
|
||||
}
|
||||
log.Infof("DNSResolver resolving %s", domain)
|
||||
|
||||
rootChan := make(chan lookupRes, 1)
|
||||
go workDomain(r, domain, rootChan)
|
||||
|
||||
subChan := make(chan lookupRes, 1)
|
||||
go workDomain(r, "_dnslink."+domain, subChan)
|
||||
|
||||
var subRes lookupRes
|
||||
select {
|
||||
case subRes = <-subChan:
|
||||
case <-ctx.Done():
|
||||
return "", ctx.Err()
|
||||
}
|
||||
|
||||
var p path.Path
|
||||
if subRes.error == nil {
|
||||
p = subRes.path
|
||||
} else {
|
||||
var rootRes lookupRes
|
||||
select {
|
||||
case rootRes = <-rootChan:
|
||||
case <-ctx.Done():
|
||||
return "", ctx.Err()
|
||||
}
|
||||
if rootRes.error == nil {
|
||||
p = rootRes.path
|
||||
} else {
|
||||
return "", ErrResolveFailed
|
||||
}
|
||||
}
|
||||
if len(segments) > 1 {
|
||||
return path.FromSegments("", strings.TrimRight(p.String(), "/"), segments[1])
|
||||
} else {
|
||||
return p, nil
|
||||
}
|
||||
}
|
||||
|
||||
func workDomain(r *DNSResolver, name string, res chan lookupRes) {
|
||||
txt, err := r.lookupTXT(name)
|
||||
|
||||
log.Infof("DNSResolver resolving %s", segments[0])
|
||||
txt, err := r.lookupTXT(segments[0])
|
||||
if err != nil {
|
||||
return "", err
|
||||
// Error is != nil
|
||||
res <- lookupRes{"", err}
|
||||
return
|
||||
}
|
||||
|
||||
for _, t := range txt {
|
||||
p, err := parseEntry(t)
|
||||
if err == nil {
|
||||
if len(segments) > 1 {
|
||||
return path.FromSegments("", strings.TrimRight(p.String(), "/"), segments[1])
|
||||
}
|
||||
return p, nil
|
||||
res <- lookupRes{p, nil}
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
return "", ErrResolveFailed
|
||||
res <- lookupRes{"", ErrResolveFailed}
|
||||
}
|
||||
|
||||
func parseEntry(txt string) (path.Path, error) {
|
||||
|
@ -65,6 +65,9 @@ func newMockDNS() *mockDNS {
|
||||
"ipfs.example.com": []string{
|
||||
"dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD",
|
||||
},
|
||||
"_dnslink.dipfs.example.com": []string{
|
||||
"dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD",
|
||||
},
|
||||
"dns1.example.com": []string{
|
||||
"dnslink=/ipns/ipfs.example.com",
|
||||
},
|
||||
@ -85,6 +88,12 @@ func newMockDNS() *mockDNS {
|
||||
"loop2.example.com": []string{
|
||||
"dnslink=/ipns/loop1.example.com",
|
||||
},
|
||||
"_dnslink.dloop1.example.com": []string{
|
||||
"dnslink=/ipns/loop2.example.com",
|
||||
},
|
||||
"_dnslink.dloop2.example.com": []string{
|
||||
"dnslink=/ipns/loop1.example.com",
|
||||
},
|
||||
"bad.example.com": []string{
|
||||
"dnslink=",
|
||||
},
|
||||
@ -100,6 +109,18 @@ func newMockDNS() *mockDNS {
|
||||
"withtrailingrec.example.com": []string{
|
||||
"dnslink=/ipns/withtrailing.example.com/segment/",
|
||||
},
|
||||
"double.example.com": []string{
|
||||
"dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD",
|
||||
},
|
||||
"_dnslink.double.example.com": []string{
|
||||
"dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD",
|
||||
},
|
||||
"double.conflict.com": []string{
|
||||
"dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD",
|
||||
},
|
||||
"_dnslink.conflict.example.com": []string{
|
||||
"dnslink=/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjE",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
@ -109,6 +130,7 @@ func TestDNSResolution(t *testing.T) {
|
||||
r := &DNSResolver{lookupTXT: mock.lookupTXT}
|
||||
testResolution(t, r, "multihash.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil)
|
||||
testResolution(t, r, "ipfs.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil)
|
||||
testResolution(t, r, "dipfs.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil)
|
||||
testResolution(t, r, "dns1.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil)
|
||||
testResolution(t, r, "dns1.example.com", 1, "/ipns/ipfs.example.com", ErrResolveRecursion)
|
||||
testResolution(t, r, "dns2.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil)
|
||||
@ -122,6 +144,10 @@ func TestDNSResolution(t *testing.T) {
|
||||
testResolution(t, r, "loop1.example.com", 2, "/ipns/loop1.example.com", ErrResolveRecursion)
|
||||
testResolution(t, r, "loop1.example.com", 3, "/ipns/loop2.example.com", ErrResolveRecursion)
|
||||
testResolution(t, r, "loop1.example.com", DefaultDepthLimit, "/ipns/loop1.example.com", ErrResolveRecursion)
|
||||
testResolution(t, r, "dloop1.example.com", 1, "/ipns/loop2.example.com", ErrResolveRecursion)
|
||||
testResolution(t, r, "dloop1.example.com", 2, "/ipns/loop1.example.com", ErrResolveRecursion)
|
||||
testResolution(t, r, "dloop1.example.com", 3, "/ipns/loop2.example.com", ErrResolveRecursion)
|
||||
testResolution(t, r, "dloop1.example.com", DefaultDepthLimit, "/ipns/loop1.example.com", ErrResolveRecursion)
|
||||
testResolution(t, r, "bad.example.com", DefaultDepthLimit, "", ErrResolveFailed)
|
||||
testResolution(t, r, "withsegment.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/segment", nil)
|
||||
testResolution(t, r, "withrecsegment.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/segment/subsub", nil)
|
||||
@ -129,4 +155,6 @@ func TestDNSResolution(t *testing.T) {
|
||||
testResolution(t, r, "withrecsegment.example.com/test2", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/segment/subsub/test2", nil)
|
||||
testResolution(t, r, "withrecsegment.example.com/test3/", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/segment/subsub/test3/", nil)
|
||||
testResolution(t, r, "withtrailingrec.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD/sub/segment/", nil)
|
||||
testResolution(t, r, "double.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjD", nil)
|
||||
testResolution(t, r, "conflict.example.com", DefaultDepthLimit, "/ipfs/QmY3hE8xgFCjGcz6PHgnvJz5HZi1BaKRfPkn1ghZUcYMjE", nil)
|
||||
}
|
||||
|
Reference in New Issue
Block a user