Subject: [Acme] Well Known CA->client poll on port 80/443 in http-acme

From: Dirk-Willem van Gulik <[email-masked]>
Date: Sun, 15 Jan 2017 14:50:37 +0100

W.r.t. http-acme — as far as I understand; the current 0.4 draft (https://tools.ietf.org/html/draft-ietf-acme-acme-04) has the Well known fetch going to port 80:

	Section	7.2, page 47

	   3.  Dereference the URI using an HTTP GET request.  

		This request MUST be sent to TCP port 80 on the server.

The new draft: (https://letsencrypt.github.io/acme-spec/ also numbered ‘’04”) in section 7.1 ‘Simple HTTP’, does a 180 degree change on this ‘default’: to an httpS default with an option to explicitly move it to HTTP with:

	  "tls": false / false

With the explanation that:

	If this attribute is present and set to “false”, the server will perform its validation check over unencrypted HTTP (on port 80) rather than over HTTPS. Otherwise the check will be done over HTTPS, on port 443.

without the clarity of a MUST. And it then continues 3 paragraphs down with solving* the bootstrap issue by

	If using HTTPS, the ACME server MUST ignore the certificate provided by the HTTPS server.

I am currently puzzling over an implementation that makes it as easy as possible to bring up an HTTPS webserver if you do ‘nothing’ but flag the VirtualHost config with something like 'letsencrypt on’ - and then defers to sane ‘SSLLabs A+’ level SSl defaults.

What I’d like to understand is

-	What is the value of doing the exchange over HTTPS (as this is made the default as opposed to the current 80) when one does not check the certificate nor retains the ACME Servers its view of that cert in the further exchange (or uses the RSA key of the challenge to self sign) ?

-	Would there be any good reason to not allow the specification of a port number ?

The reason for the first question is that keeping the process simple is desirable from an implementers point of view - as you want it relatively robust because some of the backend server config processes need to hark back to pre-chroot and pre-fork/pre-setuid() as to get secure persistence of state and (private) keys (which you want be a social-internet citizen that does not willy nilly overload the lets encrypt infra every startup).

The reason for the latter question is that it 1) allows for non-root > 1024 settings and 2)  may be more ‘robust’ to allow the server to open a relatively random high ephemeral port for a short time during startup that does not give a false sense of having the actual virtual host yet up; or a HTTPS only virtualhost shortly seeming to be misconfigured and appearing on port 80.

Thanks,

Dw.

* Well not ‘solving’ it - as the cert seen by the ACME server or the session key negotiated are not mixed into the response as to allow the Client to verify that there was no MITM during this exchange — as this is sort of deferred to later - when you find out that the cert signed is not one you have a private key for. Or by for exampling insisting that this certificate that is ‘ignored’ is in fact one self-signed by the same RSA key used in the token dance (which would be probably easiest for implementors if HTTPS was a strong default/guidance/best-practice).

---

From: Ilari Liusvaara <[email-masked]>
Date: Sun, 15 Jan 2017 16:03:30 +0200

On Sun, Jan 15, 2017 at 02:50:37PM +0100, Dirk-Willem van Gulik wrote:
> The new draft: (https://letsencrypt.github.io/acme-spec/ also numbered 
> '04') in section 7.1 ‘Simple HTTP’, does a 180 degree change on this
> ‘default’: to an httpS default with an option to explicitly move it to
> HTTP with:
> 
>   "tls": false / false

That's not a new version. It is pre-WG version, published about 1.5
years ago.

The reason HTTPS support for HTTP authentication was removed was that
many webservers handle HTTPS in odd manner, making alphabetically
first HTTPS vhost the default, which would let one get certificates
for vhosts one should not.

Currently in acme spec, the only ways to do verification without port
80 are TLS-SNI-02 (uses port 443) and DNS-01 (no connections at all,
relies on DNS exclusively).

-Ilari

---

From: Dirk-Willem van Gulik <[email-masked]>
Date: Sun, 15 Jan 2017 15:11:32 +0100

> On 15 Jan 2017, at 15:03, Ilari Liusvaara <[email-masked]> wrote:
> 
>> ….

Ok - so I’ll ignore git - and will take the IETF latest as leading.

> for vhosts one should not.

Ok.

> relies on DNS exclusively).

Ok - and is there any reason why allowing one to specify the port would not be an option/bad idea ?

I am looking at the typical old school unix case - i.e. apache — where one starts up as root and quickly
chroots/setuid()s - and where the servers are commonly deployed on port > 1024 by end users.

Thanks,

Dw.

---

From: Ilari Liusvaara <[email-masked]>
Date: Sun, 15 Jan 2017 16:29:31 +0200

> Ok - so I’ll ignore git - and will take the IETF latest as leading.

There actually is another git repo (ietf-wg-acme/acme) that contains the
WG draft work. That one is a bit newer than ietf-04 (but shouldn't have
significant changes).
 
> would not be an option/bad idea ?

The list of ports public CAs can use is pretty short (5 ports in fact).

> I am looking at the typical old school unix case - i.e. apache — where
> one starts up as root and quickly chroots/setuid()s - and where the
> servers are commonly deployed on port > 1024 by end users.

There actually are restrictions on what ports public CAs can use for
authentication. These are:

- 80 (HTTP)
- 443 (HTTPS)
- 115 (SFTP; no, not _that_ SFTP [1])
- 25 (SMTP)
- 22 (SSH)

These limits are exactly so that unprivileged users don't bind
daemons to the ports and use those to obtain certificates (the
certificates are valid for all ports).

[1] This is likely a mistake (but it is still allowed). The "SFTP"
is not _Secure_ File Transfer Protocol (shares port 22 with SSH) but
instead _Simple_ File Transfer Protocol... Described in three-digit-
number historic-status RFC, from the 80s...

-Ilari

---

From: Dirk-Willem van Gulik <[email-masked]>
Date: Sun, 15 Jan 2017 15:39:43 +0100

> On 15 Jan 2017, at 15:29, Ilari Liusvaara <[email-masked]> wrote:
> 

Just to make sure I understand the reasoning:

	CA Policy prohibits an ACME CA Server from fetching the token (authenticating) from a subscriber port > 1024 (or a port not an element of [80,443,115,25,22)) because an (on common  flavours of unix) an un(der)privileged) user may run a daemon on such a port.

Correct ? Just so I understand the tradeoffs made correctly when implementing/mitigating the root-risk on the webserver side.

You would not happen to know where these are documented (I’ve scanned CPS, SA and policy but no cookie yet).

Dw

---

From: Ilari Liusvaara <[email-masked]>
Date: Sun, 15 Jan 2017 17:04:07 +0200

On Sun, Jan 15, 2017 at 03:39:43PM +0100, Dirk-Willem van Gulik wrote:
> CA Policy prohibits an ACME CA Server from fetching the token
> (authenticating) from a subscriber port > 1024 (or a port not an
> element of [80,443,115,25,22)) because an (on common  flavours of
> unix) an un(der)privileged) user may run a daemon on such a port.
>
> Correct ? Just so I understand the tradeoffs made correctly when
> implementing/mitigating the root-risk on the webserver side.

Actually, ACME as of currently can use only 80 or 443 (there is
no explicit port selection anywhere). The remaining three ports
might be used by  non-ACME public CAs.

And all those five ports are privileged to bind to (but once
bound, are not privileged to accept connections from[2]). And if
you are talking about abuse from root, there is not much that
can be done, outside Mandatory Access Control extensions like
SELinux and such.

> You would not happen to know where these are documented (I’ve
> scanned CPS, SA and policy but no cookie yet).

CABForum Baseline Requirements.(I looked up version 1.3.9, since
the 1.4 versions are AFAIK essentially withdrawn).

[2] It is actually possible to bind to such port, drop privileges
and then pass the descriptor to another program via exec or even
local socket. The receiver can then accept connections from it,
even if receiver never was privileged. I have one daemon on one VM
that does just that with port 443.

-Ilari

---

From: "Salz, Rich" <[email-masked]>
Date: Sun, 15 Jan 2017 15:35:52 +0000

> Ok - so I’ll ignore git - and will take the IETF latest as leading.

Are you looking at the LetsEncrypt git repo?  The IETF one is at https://github.com/ietf-wg-acme/acme

---

From: Dirk-Willem van Gulik <[email-masked]>
Date: Sun, 15 Jan 2017 17:59:43 +0100

> On 15 Jan 2017, at 16:04, Ilari Liusvaara <[email-masked]> wrote:
> 
> no explicit port selection anywhere).

Which makes sense given the current CABForum limitation.

> The remaining three ports

Agreed - I am more concerned about the opposite - allowing well intending non-root users who want to spin up a server to do the right thing.

The more educated/capable group is already well served by, for example, a trivial apache SSL config file  in conjunction with shell scripts [1,2].

> the 1.4 versions are AFAIK essentially withdrawn).

Lovely - thanks!

> that does just that with port 443.
``
We have sufficient infrastructure for that in apache and its APR utility library.

I am trying to understand enough of the considerations of ACME (such as the choise for the the ‘Authorized Ports’ list as defined in that CABForum BR) to help me make the right trade offs between a) bringing the webserver up in a relatively insecure fashion for a short period of time and getting the business of (re)new cert’s over as robustly as possible v.s. spinning up much more surface of things that can confuse -or- go wrong (including apache its normal devolved setuid()/chroot() post forking & opening the < 1024 sockets), are expensive to maintain or prone to abuse.

And secondly I am trying to come to grips with the advent of virtualisation & containerisation causing the concepts of virtual hosts to change; rather than have 10’s of thousands of VHOSTs in a single config/binary; all listening to all IP’s on port 80 - so common at the turn of the century - one now  increasingly sees a lot of port mapping - where in effect each httpd runs ‘alone’, in a container, with a single vhost config - albeit on a funny port. 

Which may, or may not be, mapped to some IP:80 or through some LB/fan-out proxy that has a FQDN->internal IP & port table. Software defined networking seems to favour the latter.

But the net effect is that that makes the listening on port 80 for a FQDN that is elsewhere configured to be visible on just a single IP:443 (mapped to -> internal-ip + high port) rather much out of reach. As a listen *:80 is no longer effective. Especially for the cohort of users for whom the scripting is already out of reach.

Hence the desire to understand the design better.

Thanks,

Dw.

1: https://github.com/Neilpang/acme.sh <https://github.com/Neilpang/acme.sh>
2: https://github.com/lukas2511/dehydrated <https://github.com/lukas2511/dehydrated>

---

From: Ilari Liusvaara <[email-masked]>
Date: Sun, 15 Jan 2017 19:36:59 +0200

On Sun, Jan 15, 2017 at 05:59:43PM +0100, Dirk-Willem van Gulik wrote:
> I am trying to understand enough of the considerations of ACME
> (such as the choise for the the ‘Authorized Ports’ list as defined
> in that CABForum BR) to help me make the right trade offs between
> a) bringing the webserver up in a relatively insecure fashion for
> a short period of time and getting the business of (re)new cert’s
> over as robustly as possible v.s. spinning up much more surface of
> things that can confuse -or- go wrong (including apache its normal
> devolved setuid()/chroot() post forking & opening the < 1024 sockets),
> are expensive to maintain or prone to abuse.

There's also the fact that HTTP-01 will follow redirects to https://
(just the initial request has to be http://), ignoring certificate
validity.

> And secondly I am trying to come to grips with the advent of 
> virtualisation & containerisation causing the concepts of virtual
> hosts to change; rather than have 10’s of thousands of VHOSTs in a
> single config/binary; all listening to all IP’s on port 80 - so common
> at the turn of the century - one now  increasingly sees a lot of port
> mapping - where in effect each httpd runs ‘alone’, in a container, with
> a single vhost config - albeit on a funny port. 

The funny ports are because one can't get enough IPv4 address space
to give each container its own address?

> Which may, or may not be, mapped to some IP:80 or through some LB/fan-out
> proxy that has a FQDN->internal IP & port table. Software defined
> networking seems to favour the latter.
> 
> But the net effect is that that makes the listening on port 80 for a FQDN
> that is elsewhere configured to be visible on just a single IP:443 (mapped
> to -> internal-ip + high port) rather much out of reach. As a listen *:80
> is no longer effective. Especially for the cohort of users for whom the
> scripting is already out of reach.

Well, if the port 80 on the same external IP could be configured to serve
a redirect to https for validation requests (which is just a static
mapping per FQDN), then those requests would presumably be sent to the
container.

That is, rule of form: http://foo.example/.well-known/acme-challenge/bar
-> https://foo.example/.well-known/acme-challenge/bar 

And the secondary requests also AFAIK have SNI on TLS level, so one can
route on that too.

-Ilari

---

From: Dirk-Willem van Gulik <[email-masked]>
Date: Sun, 15 Jan 2017 18:54:10 +0100

> On 15 Jan 2017, at 18:36, Ilari Liusvaara <[email-masked]> wrote:
> 

That is indeed the alternative — surmise that as the user (no matter how VM’s, containers, virtual load balancers or whatever is configured) will want to end up visible on port 443 with a cert — we focus on some blind http->https redirect which can be configured in bulk; and always bring up an TLS+SSL on 443 with a self signed cert if we do not yet have an acme cert (and using the same private key for thus).

Dw.

---

From: Ilari Liusvaara <[email-masked]>
Date: Sun, 15 Jan 2017 20:29:15 +0200

On Sun, Jan 15, 2017 at 06:54:10PM +0100, Dirk-Willem van Gulik wrote:
> 
> 
> That is indeed the alternative — surmise that as the user (no matter
> how VM’s, containers, virtual load balancers or whatever is configured)
> will want to end up visible on port 443 with a cert — we focus on some
> blind http->https redirect which can be configured in bulk; and always
> bring up an TLS+SSL on 443 with a self signed cert if we do not yet
> have an acme cert (and using the same private key for thus).

Well, if the container is not visible on port 80, you presumably want
a path-preserving HTTP -> HTTPS redirect for all URLs on the FQDN. Such
redirect would also redirect ACME HTTP requests.

Or if one wants just to redirect ACME HTTP requests, one can redirect
just the paths under .well-known/acme-challenge/. No need to be
discriminate: the target server will sort it out anyway.

-Ilari