2.0.20 breaks DNS SRV hkp keyserver access via web proxy server

Phil Pennock gnupg-devel at spodhuis.org
Tue Jun 11 01:15:20 CEST 2013

On 2013-06-10 at 20:33 +1000, John Marshall wrote:
> The "SNI" changes to gnupg's handling of DNS SRV keyserver records means
> that a client accessing an hkp keyserver via a web proxy server can no
> longer contact the selected target keyserver.

The changes were explicitly requested by those of us in the SKS
operational community working on pool infrastructure, to make sure that
link security can work with pools and in the presence of DNS attacks,
but without requiring DNSSEC -- at this point in time, DNSSEC is a
worthy goal (and something I'm pushing towards elsewhere) but to mandate
it as the only approach to verifiable link security would be washing our
hands of a problem.

If there is to be validation, the SNI and the Host: header have to match
the identity that is validated.  In the absence of DNSSEC validation,
the only available non-compromisable input is the original domain name.
This is what led to the criteria for hkps.pool.sks-keyservers.net
outlined at <http://www.sks-keyservers.net/overview-of-pools.php>.

>                                                         However, in the
> case of a client behind a web proxy, the fake (SRV RR owner) domain is
> used as the hostname in the query and passed to the web proxy server.
> If the SRV RR owner also has an A or AAAA record, that (rather than
> whatever address was selected by gnupg) will be used by the proxy server
> to contact what may or may not be a keyserver.

If you use a dedicated port (11373 is spreading a little for hkps) then
you can default all handling through to the correct default vhost, and
put the port into the SRV record.  That way, things that don't
understand SRV will send the hostname you are expecting, and things that
do understand SRV will connect to the correct port.

The other alternative is to list hostnames for known pools/domains that
you serve for, so that you're not serving for unknown domains, which is
a common operational security stance.

So, you then need a certificate for the original domain, or to disable
verification.  Using the hostname is equivalent to disabling
verification, because the hostname is derived insecurely, but the
problem can be "hidden" so that folks don't recognise the attack vector.

Getting a certificate for the original domain means talking to whomever
controls the domain.  If it's not your domain and the operator doesn't
want to help sort out certs, then you simply don't offer hkps for that
domain, only for your own.

The link above includes instructions for how SKS keyserver operators can
get a certificate under a trust anchor available for sks-keyservers.net.
There's no sane way to manage this within the traditional PKIX because
no Certificate Authority is going to issue multiple certs for the same
name to different operators, and reusing keys between independently
operated keyservers would be a security joke.

> I am not a programmer and I don't speak C but I have made a little hack
> to keyservers/gpgkeys_hkp.c to get us operational again.  This is

Unfortunately, you've moved things back to a state where the client is
verifying that the delivered certificate has a hostname that was
retrieved over insecure DNS, introducing a security hole back into the

To safely do what you've done, you'd also have to add DNSSEC

Really, you might as well use `--keyserver-options no-check-cert` since
that's the security you're really getting, using the patch you provide.

> Is anyone able to suggest a better/safer patch for us - or better still,
> a proper solution to this problem that can be used as a patch in
> downstream ports?

The most proper solution is for DNSSEC to be deployed everywhere today.
In the absence of that, HKPS support has moved towards verifying the

Ultimately, with DNSSEC the way back out of this is with DANE and

For HKPS the solution would then be:

 * if no DNSSEC validation available, use the 2.0.20 logic
 * if DNSSEC insecure, use the 2.0.20 logic
 * if DNSSEC validates as secure, then check for a TLSA record for the
   members of the SRV pool
   * if TLSA record found, use the derived hostname for checks
   * if TLSA record not found, use the 2.0.20 logic

This gives as much security as is possible to each client and the
operator of the _target_ host can decide for themselves which hostname
should be validated, since they're presumably in control of the DNS for
the target domain (and can chop out support of pools which rename to
their own hostname).

-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 163 bytes
Desc: not available
URL: </pipermail/attachments/20130610/43e23a1a/attachment.sig>

More information about the Gnupg-devel mailing list