getssl icon indicating copy to clipboard operation
getssl copied to clipboard

XMPP / SRV compatible certificate check

Open masgo opened this issue 3 years ago • 3 comments

Feature request Make SERVER_TYPE="xmpp" use the SRV DNS records to check against the real XMPP server, which might be != the certificate domain. Or as a workaround: allow to specify the host which should be checked for the certificate.

Background I am using getssl to generate a certificate for a private XMPP server hosted at home. The way XMPP works (in this scenario) is, that there is a SRV DNS entry pointing to the server providing the service, e.g.: _xmpp-client._tcp.example.com. 18000 IN SRV 0 5 5222 xmpp.example.com. When I use [email protected] as XMPP id, the client does a DNS query and then connects to xmpp.example.com on port 5222. The server running at xmpp.example.com needs to respond with a certificate for example.com.

The generating part works fine. getssl runs on the VM at xmpp.example.com, it uploads the challenge token via SFTP to the webserver running at example.com the certificates are successfully obtained.

When trying to validate the certificate getssl fails:

Either it tries to validate it against example.com and gives this error:

/root/.getssl/example.com/example.com.crt didn't match server
getssl: example.com - rsa certificate obtained but certificate on server is different from the new certificate

Which is an understandable since example.org really does use a different certificate.

Or if I use

SERVER_TYPE="xmpp"
CHECK_REMOTE="true"

it fails with

example.com: no certificate obtained from host
example.com: certificate is valid for more than 30 days (until Jun  3 20:52:22 2021 GMT)

Which is also understandable, since example.com does not run anything in port 5222.

masgo avatar Mar 05 '21 22:03 masgo

Hi @masgo

This seems like a good enhancement, I'll add it to my list of things to do (happy to review a PR if you feel up to coding the change)

timkimber avatar Mar 08 '21 21:03 timkimber

My bash skills are rather limited.

The easyest way would probably be to provide an additonoal variable like CHECK_REMOTE_HOSTNAME where one could manually specify the host to check against. This would probably also be useful for mail servers, and others where SRV records are used. This would also deal with the situation where the SRV record points to multiple hosts with different priorities. In such a case the generated certificate might only be used for a subset of the servers.

OR You could provide a variable like EXECUTE_EXTERNAL_CHECK_REMOTE which would be a commandline to execute. Then one could provide an external script which does the certificate check. You would then just check the return value.

OR If you, or somebody else, wants to do it for XMPP, here are more informations about the XMPP specifications. I am using the real public XMPP jabber.ccc.de server as an example here.

  1. Query the DNS for the SRV records, for client and/or server
$ host -t SRV _xmpp-client._tcp.jabber.ccc.de
_xmpp-client._tcp.jabber.ccc.de has SRV record 10 0 5222 jabberd.jabber.ccc.de.
_xmpp-client._tcp.jabber.ccc.de has SRV record 30 0 5222 jabberd-ipv6.jabber.ccc.de.
_xmpp-client._tcp.jabber.ccc.de has SRV record 20 0 80 jabberd.jabber.ccc.de.
_xmpp-client._tcp.jabber.ccc.de has SRV record 31 0 5222 jabberd-ipv4.jabber.ccc.de.

$ host -t SRV _xmpp-server._tcp.jabber.ccc.de
_xmpp-server._tcp.jabber.ccc.de has SRV record 31 0 5269 jabberd-ipv4.jabber.ccc.de.
_xmpp-server._tcp.jabber.ccc.de has SRV record 30 0 5269 jabberd-ipv6.jabber.ccc.de.
_xmpp-server._tcp.jabber.ccc.de has SRV record 10 0 5269 jabberd.jabber.ccc.de.

Now one needs to parse the response according to the XMPP documentation.

An SRV record has the form:

_service._proto.name TTL class SRV priority weight port target

    service: the symbolic name of the desired service.
    proto: the transport protocol of the desired service; this is usually either TCP or UDP.
    name: the domain name for which this record is valid.
    TTL: standard DNS time to live field.
    class: standard DNS class field (this is always IN).
    priority: the priority of the target host, lower value means more preferred.
    weight: A relative weight for records with the same priority.
    port: the TCP or UDP port on which the service is to be found.
    target: the canonical hostname of the machine providing the service.

Then check all(?) servers for the new certificate. As per defition the target needs to be an A record, so no CNAME or similar problems here.

masgo avatar Mar 09 '21 07:03 masgo

Thanks @masgo, that's some great requirements. I'll look at implementing it soonish

timkimber avatar Mar 10 '21 21:03 timkimber