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

did:web resolver cannot resolve IPv6 handles #1338

Closed
dead10ck opened this issue Jul 14, 2023 · 3 comments
Closed

did:web resolver cannot resolve IPv6 handles #1338

dead10ck opened this issue Jul 14, 2023 · 3 comments
Labels
bug Something isn't working

Comments

@dead10ck
Copy link

Describe the bug

did:web handles that resolve to an IPv6 address fail with could not resolve valid DID document. For example, my server has the FQDN dead10ck.dev, which is the same as the did:web handle I'm trying to create on my sandbox PDS. It has a link local IPv6 address, which the FQDN resolves to when it makes a request from the same server (to itself).

[root@dead10ck ~]# ip addr show dev eth0
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 9001 qdisc mq state UP
 group default qlen 1000
    link/ether 12:6d:da:9e:b4:03 brd ff:ff:ff:ff:ff:ff
    altname enp0s5
    altname ens5
    inet 172.31.86.138/20 brd 172.31.95.255 scope global dynamic nopr
efixroute eth0
       valid_lft 3469sec preferred_lft 3469sec
    inet6 2600:1f18:6af3:9f05:f526:3a1a:611:6b22/128 scope global dyn
amic noprefixroute
       valid_lft 418sec preferred_lft 108sec
    inet6 fe80::62f0:705:bdbd:6279/64 scope link noprefixroute
       valid_lft forever preferred_lft forever

The DID document is served at the expected location successfully:

[root@dead10ck ~]# curl -vSs 'https://dead10ck.dev/.well-known/did.json'
*   Trying [fe80::62f0:705:bdbd:6279]:443...
* Connected to dead10ck.dev (fe80::62f0:705:bdbd:6279) port 443 (#0)
* ALPN: offers h2,http/1.1
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
*  CAfile: /etc/pki/tls/certs/ca-bundle.crt
*  CApath: none
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
* ALPN: server accepted h2
* Server certificate:
*  subject: CN=dead10ck.dev
*  start date: Jul  6 07:15:52 2023 GMT
*  expire date: Oct  4 07:15:51 2023 GMT
*  subjectAltName: host "dead10ck.dev" matched cert's "dead10ck.dev"
*  issuer: C=US; O=Let's Encrypt; CN=R3
*  SSL certificate verify ok.
* using HTTP/2
* h2h3 [:method: GET]
* h2h3 [:path: /.well-known/did.json]
* h2h3 [:scheme: https]
* h2h3 [:authority: dead10ck.dev]
* h2h3 [user-agent: curl/8.0.1]
* h2h3 [accept: */*]
* Using Stream ID: 1 (easy handle 0x55ee3f95d570)
> GET /.well-known/did.json HTTP/2
> Host: dead10ck.dev
> user-agent: curl/8.0.1
> accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* old SSL session ID is stale, removing
< HTTP/2 200
< server: nginx/1.24.0
< date: Fri, 14 Jul 2023 04:43:59 GMT
< content-type: application/json
< content-length: 533
< last-modified: Wed, 12 Jul 2023 03:55:49 GMT
< etag: "64ae2445-215"
< accept-ranges: bytes
<
{"@context": ["https://www.w3.org/ns/did/v1", "https://w3id.org/security/suites/secp256k1-2019/v1"], "id": "did:web:dead10ck.dev", "alsoKnownAs": ["at://dead10ck.dev"], "verificationMethod": [{"id": "#atproto", "type": "EcdsaSecp256k1VerificationKey2019", "controller": "did:web:dead10ck.dev", "publicKeyMultibase": "mAATYyJKDMlA1jThD+1WogVh2xuVt5jhyPRoUPPNcBrC1x3mKV8ZkFMWYjbM/BsO6ljRzQqsRiHJcmKAm8uHXoj6s"}], "service": [{"id": "#atproto_pds", "type": "AtprotoPersonalDataServer","serviceEndpoint": "https://bsky.dead10ck.dev"}]}

But when I try to create an account for this handle, it fails. I added extra debug print statements to see the actual error:

❯ : curl -SsX POST --user $"admin:xxxxxx" -H "Content-Type: application/json" --data ({inviteCode: "bsky-dead10ck-dev-xxxxxxxx", handle: dead10ck.dev, did: "did:web:dead10ck.dev", email: "skyler@dead10ck.dev", password: 'xxxxx'} | to json) https://bsky.dead10ck.dev/xrpc/com.atproto.server.createAccount
Jul 14 04:49:46 dead10ck.dev bsky-pds[35756]: {"level":50,"time":1689310185811,"pid":35756,"hostname":"dead10ck.dev","name":"xrpc-server","err":{"type":"InvalidRequestError","message":"could not resolve valid DID document: did:web:dead10ck.dev\n----------Error: connect EINVAL fe80::62f0:705:bdbd:6279:443 - Local (:::0)\n    at __node_internal_captureLargerStackTrace (node:internal/errors:490:5)\n    at __node_internal_exceptionWithHostPort (node:internal/errors:668:12)\n    at internalConnect (node:net:1066:16)\n    at defaultTriggerAsyncIdScope(node:internal/async_hooks:464:18)\n    at GetAddrInfoReqWrap.emitLookup [as callback] (node:net:1323:9)\n    at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:109:8)\n----------","stack":"Error: could not resolve valid DID document: did:web:dead10ck.dev\n----------Error: connect EINVAL fe80::62f0:705:bdbd:6279:443 - Local (:::0)\n    at __node_internal_captureLargerStackTrace (node:internal/errors:490:5)\n    at __node_internal_exceptionWithHostPort (node:internal/errors:668:12)\n    at internalConnect (node:net:1066:16)\n    at defaultTriggerAsyncIdScope (node:internal/async_hooks:464:18)\n    at GetAddrInfoReqWrap.emitLookup [as callback] (node:net:1323:9)\n    at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:109:8)\n----------\n
at getDidAndPlcOp (/opt/bsky/pds/packages/pds/src/api/com/atproto/server/createAccount.ts:211:11)\n    at process.processTicksAndRejections (node:internal/process/task_queues:95:5)\n    at <anonymous> (/opt/bsky/pds/packages/pds/src/api/com/atproto/server/createAccount.ts:34:28)\n    at <anonymous> (/opt/bsky/pds/packages/xrpc-server/src/server.ts:207:35)","errorMessage":"could not resolve valid DID document: did:web:dead10ck.dev\n----------Error: connect EINVAL fe80::62f0:705:bdbd:6279:443 - Local (:::0)\n    at __node_internal_captureLargerStackTrace (node:internal/errors:490:5)\n    at __node_internal_exceptionWithHostPort (node:internal/errors:668:12)\n    at internalConnect(node:net:1066:16)\n    at defaultTriggerAsyncIdScope (node:internal/async_hooks:464:18)\n    at GetAddrInfoReqWrap.emitLookup [as callback] (node:net:1323:9)\n    at GetAddrInfoReqWrap.onlookup [as oncomplete] (node:dns:109:8)\n----------","customErrorName":"UnresolvableDid"},"msg":"error in xrpc method com.atproto.server.createAccount"}

In particular, note this bit:

Error: connect EINVAL fe80::62f0:705:bdbd:6279:443 - Local (:::0)

It seems when it makes the HTTP request to https://dead10ck.dev/.well-known/did.json, it resolves to the IP address and port, but then simply uses the IPv6 address as the host without the necessary [] enclosure to disambiguate the port.

The particular line where it fails is here:

try {
const res = await axios.get(url.toString(), {
responseType: 'json',
timeout: this.timeout,
})
return res.data
} catch (err) {
if (err instanceof AxiosError && err.response) {
return null // Positively not found, versus due to e.g. network error
}
throw err
}

So this may be an upstream bug with Axios.

Details

  • Operating system: Fedora Server 38
  • Node version: v18.16.0
@dead10ck dead10ck added the bug Something isn't working label Jul 14, 2023
@dead10ck
Copy link
Author

Actually, when I open a node repl and do a request to an IPv6 only host, it works just fine, e.g.

axios.get('https://ipv6.google.com')

So maybe this is an edge case with when the domain name resolves to a link local address because it's from and to the same box.

@dead10ck
Copy link
Author

Filed an upstream issue:

axios/axios#5782

@dead10ck
Copy link
Author

I think this is resolved now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

1 participant