Obtaining Let's Encrypt intermediates over IPv6


So, slightly relevant to your announcement last year; https://letsencrypt.org/2016/07/26/full-ipv6-support.html.

This “full IPv6 support” is partly true – if you want to verify the certificate chain when creating a “fullchain” (like dehydrated does), you need to download the intermediate certificate to get the full chain. You could specify the chain “manually”, but that would lead to problems if/when the intermediate is changed – in other words; the only way to properly do this automatic, is the way dehydrated currently does it (by fetching the intermediate certificate).

Currently that intermediate certificate has the following URL;


That FQDN does not have IPv6 support (i.e. it’s a CNAME pointing to apps.digsigtrust.com, which again only has A-records).

In other words; you cannot fully deploy/use/verify LE on an IPv6-only host; you either need to be dual stacked, use a proxy, or have some other means of gaining directly or indirectly IPv4 connectivity.

Is there a plan to get proper IPv6 support on the entire chain any time soon? (-:

1 Like

There is already an issue created for this on dehydrated (https://github.com/lukas2511/dehydrated/issues/382), but this is not really an issue with dehydrated; this needs to be resolved by giving proper IPv6 support for the relevant URIs relating to the certificate chain.

In other words; http://apps.identrust.com/roots/dstrootcax3.p7c should become dual stacked, and that is more of an “LE issue”, than it is an “dehydrated issue” (-:

Not really.

In a fullchain, you don’t need to include the Root cert. Just include the intermediate cert and your leaf cert.

In ACME protocol, there is not link to download the Root cert, just a link to download the correct intermediate cert:


This url is ipv6 ready:

curl -6 https://acme-staging.api.letsencrypt.org/acme/issuer-cert
1 Like

This doesn’t actually break anything. dehydrated has already got the certificate and the chain from Let’s Encrypt via ACME and is just performing a sanity check. You can safely ignore this error. EDIT: I misunderstood what it is doing, upon looking at the code I see it may indeed fail to get the chain because of this.

Please note that Let’s Encrypt does not operate the DST Root CA X3. All they can do is ask IdenTrust nicely.

these are also available on the Let’s Encrypt website which is also IPV6 compatible



Yes, I knew where to download the root cert. but what I meant is there is really no need to take care of/include the root cert.

See here too: ISRG Root X1 chain issues

1 Like

The dehydrated author doesn't want to hardcode specifics of Let's Encrypt into his program like this. He thinks it should work with any service conforming to the ACME RFC.

I looked at the code. dehydrated doesn't read the Link headers in the ACME response and instead uses the url for the intermediate encoded within the certificate, walking back until it gets to the root. So it doesn't actually use the root certificate for anything other than deciding it's done and doesn't need it.

That being said, I'm not sure if this method would always get the right chain with other CAs. Don't some roots sign their new root with their old one? dehydrated could walk all the way back to 1998 this way...

I know, but the request should still come from LE, and not a third-party client like dehydrated.

I agree on this (that it shouldn’t need to involve LE-specific things), and as such, “walking the chain” using the URLs in the certificates is more or less the “only” way (unless the part of including URLs to the intermediates, as part of the request, becomes a part of the ACME RFC).

The ACME RFC already specifies its own way of getting the chain. In the currently implemented Boulder version, it uses Link headers. In ACME v2, it will provide the full chain as PEM. ACME clients like dehydrated should prefer this method over following the AIA CA Issuers field in certificates. For clients that do, the question of whether IdenTrust offers IPv6 is moot. However, I’ll file a ticket to ask them, just on the grounds of “more IPv6 is better.”


Maybe point out that the digsigtrust.com/identrust.com nameservers are also IPv4-only.

It’s totally impractical to run an IPv6-only system without configuring it to use an IPv4-capable recursive DNS server, but still.

Edit: Then again, some of Akamai’s zones (dscq.akamai.net, dscb.akamaiedge.net) have the same issue anyway.


Good point, thanks! I’ll see about requesting improvements to Akamai’s zones too.

Ah, I see. Out of curiosity; is the URL in the Link header the one specified by @Neilpang, or the identrust.com one?

Yes, that sounds more reasonable.

Thanks (-:

The Link header contains the @Neilpang’s URL – or it’s production equivalent, https://acme-v01.api.letsencrypt.org/acme/issuer-cert.

Link: <https://acme-v01.api.letsencrypt.org/acme/issuer-cert>;rel="up"

The IdenTrust URL is the root certificate, which ACME clients typically don’t need to obtain. As they said, the ACME API server just gives you the necessary intermediate(s).

That client is using a somewhat fraught method of dynamically determining the intermediates that requires downloading the root (and then realizing that it’s the root, discarding it, and stopping).

Edit: I called @Neilpang “the”. :frowning:

Ah, okay, thanks.

The complete code/logic is one thing (and I don't disagree with you), but the concept of "use whatever info we have in the issued cert to determine the chain" seems like a good approach (at least in principle), rather than just "trust whatever intermediate certificate we get handed"... but then again; it's the root that ultimately decides wether or not the chain is valid, so maybe it's somewhat of a "potato, potato" after all (-:

It is boulder that writes the Link header into the ACME response and it is boulder that writes the AIA field into the certificate.

This is like saying it is better to read the drug facts on the back of the bottle rather than the outer carton. Yes they could screw up one but it’s all highly regulated and thus very unlikely and who knows which one is correct if they don’t match anyway?

To be honest, i shouldn’t complain. It’s not specifically incorrect and it is, after all, producing the right chain. (The only issue is IdenTrust’s lack of IPv6 support.)

Dynamic path building just makes me nervous. :sweat: I don’t know if following AIA like that can ever lead you down the wrong path. Maybe not. But older CAs are often a tangled web of cross-certificates. I don’t know if they always keep their AIA URLs straight. Maybe they do and i’m nervous for nothing. Maybe they don’t and five certificates down you find a 1024-bit Symantec root from 1997. :stuck_out_tongue:

1 Like


This is not the ideal way to fetch the issuer for any given end-entity certificate, because it doesn't allow for end-entity certificates to be issued from a variety of intermediates. Let's Encrypt doesn't currently operate multiple intermediates at once, but we (and other CAs) are likely to in the future.. We added this URL early on to satisfy a certain use case, but it's not in the spec, and won't continue to exist under ACME v2. I would recommend using the Link header instead, since it's more future-proof.


Hardcoding the issuer-cert URL in a client is, i assume, a terrible idea, but it is where the Link header currently points. As a demonstration, it’s correct at the moment.

yes, I meant reading the url from the Link-Issuer: header, not hard coded.

1 Like

Ah, excellent. I misunderstood earlier; thanks for the clarification.