Welcome! Log In Create A New Profile

Advanced

Is it possible to disable SSL if not certificates are found?

Posted by Simos Xenitellis 
Simos Xenitellis
Is it possible to disable SSL if not certificates are found?
May 22, 2017 10:40AM
Hi All,

I am trying to automate some tasks with adding multiple https
(LetsEncrypt) websites,
and using HAProxy as a TLS Termination Proxy.

The problem is that when you start off with an empty server, there are
no certificates yet,
and it is not possible to have "bind *:443 ssl crt
/etc/haproxy/certs/..." in haproxy.cfg.

LetsEncrypt can work with http, so it could easily use the "bind *:80"
front-end in the beginning.

Is there a way to express "If no certificates are found in
/etc/haproxy/certs/, then do not bind *:443"?

Simos
Hi Simos Xenitellis.

Simos Xenitellis have written on Mon, 22 May 2017 11:28:41 +0300:

> Hi All,
>
> I am trying to automate some tasks with adding multiple https
> (LetsEncrypt) websites,
> and using HAProxy as a TLS Termination Proxy.
>
> The problem is that when you start off with an empty server, there are
> no certificates yet,
> and it is not possible to have "bind *:443 ssl crt
> /etc/haproxy/certs/..." in haproxy.cfg.
>
> LetsEncrypt can work with http, so it could easily use the "bind *:80"
> front-end in the beginning.
>
> Is there a way to express "If no certificates are found in
> /etc/haproxy/certs/, then do not bind *:443"?

I don't know such a 'lazy read' option in haproxy, but this
feature sounds interesting.
Do you have any patches available yet or are you willing to provide one?

> Simos

Regards
Aleks
Hi Simos,

The workaround is to have a default (fake) certificat in first and use « strict-sni » parameter.

Manu

> Le 22 mai 2017 à 10:28, Simos Xenitellis <[email protected]> a écrit :
>
> Hi All,
>
> I am trying to automate some tasks with adding multiple https
> (LetsEncrypt) websites,
> and using HAProxy as a TLS Termination Proxy.
>
> The problem is that when you start off with an empty server, there are
> no certificates yet,
> and it is not possible to have "bind *:443 ssl crt
> /etc/haproxy/certs/..." in haproxy.cfg.
>
> LetsEncrypt can work with http, so it could easily use the "bind *:80"
> front-end in the beginning.
>
> Is there a way to express "If no certificates are found in
> /etc/haproxy/certs/, then do not bind *:443"?
>
> Simos
>
In haproxy 1.8dev, default certificate can now be optional.
This patch allow that.

Manu


> Le 29 mai 2017 à 11:09, Emmanuel Hocdet <[email protected]> a écrit :
>
>
> Hi Simos,
>
> The workaround is to have a default (fake) certificat in first and use « strict-sni » parameter.
>
> Manu
>
>> Le 22 mai 2017 à 10:28, Simos Xenitellis <[email protected]> a écrit :
>>
>> Hi All,
>>
>> I am trying to automate some tasks with adding multiple https
>> (LetsEncrypt) websites,
>> and using HAProxy as a TLS Termination Proxy.
>>
>> The problem is that when you start off with an empty server, there are
>> no certificates yet,
>> and it is not possible to have "bind *:443 ssl crt
>> /etc/haproxy/certs/..." in haproxy.cfg.
>>
>> LetsEncrypt can work with http, so it could easily use the "bind *:80"
>> front-end in the beginning.
>>
>> Is there a way to express "If no certificates are found in
>> /etc/haproxy/certs/, then do not bind *:443"?
>>
>> Simos
>>
>
Attachments:
open | download - 0001-MEDIUM-ssl-allow-haproxy-to-start-without-default-ce.patch (3.6 KB)
On 12.06.2017 16:21, Emmanuel Hocdet wrote:
> In haproxy 1.8dev, default certificate can now be optional.
> This patch allow that.

This looks like a big footgun. While the idea is interesting and useful
if this is to be considered at all this behavior should only be allowed
after the user explicitly opted into it by setting a special flag like
"allowmissingcerts" or something like that.

Regards,
Dennis
On 17-06-14 13:58:01, Dennis Jacobfeuerborn wrote:
> On 12.06.2017 16:21, Emmanuel Hocdet wrote:
> > In haproxy 1.8dev, default certificate can now be optional.
> > This patch allow that.
>
> This looks like a big footgun. While the idea is interesting and
> useful if this is to be considered at all this behavior should only be
> allowed after the user explicitly opted into it by setting a special
> flag like "allowmissingcerts" or something like that.

+1
> Le 14 juin 2017 à 13:58, Dennis Jacobfeuerborn <[email protected]> a écrit :
>
> On 12.06.2017 16:21, Emmanuel Hocdet wrote:
>> In haproxy 1.8dev, default certificate can now be optional.
>> This patch allow that.
>
> This looks like a big footgun. While the idea is interesting and useful
> if this is to be considered at all this behavior should only be allowed
> after the user explicitly opted into it by setting a special flag like
> "allowmissingcerts" or something like that.
>
> Regards,
> Dennis

What are you talking about?
The default certificate is the first parsed certificate and is mandatory. Start haproxy without certificate fail.
Now you can start without certificate. The default certificate will always be the first parsed certificate in next
haproxy reloads.

Manu
On Mon, Jun 12, 2017 at 5:21 PM, Emmanuel Hocdet <[email protected]> wrote:
> In haproxy 1.8dev, default certificate can now be optional.
> This patch allow that.
>

Thanks Manu for looking into this.

Here is my use-case:

1. A "frontend" would bind on port 80 and then look whether a request
is from Letsencrypt (URL: ~/.well-known/..). That is, an "http-01"
challenge request.
If so, it would forward the connection to a backend that deals with
certificates (that backend initiated this request in the first place).
If it is not an "http-01" challenge request, then it would redirect to https.

2. Another frontend would bind to port 443, and the "bind" line would
have a new keyword like "disable-if-no-certs".
If there are no certs yet installed, haproxy would cancel out the
whole frontend for port 443 and would not bind port 443.


Ideally, this would be implemented cleanly if there was a way to simply specify

use_frontend myhttps if { ssl_certs_exist }

Also, we could then specify to redirect to https (first frontend
earlier ) if { ssl_certs_exist }.


For this to work, it would require:

1. Addition of keyboard "use_frontend", just like "use_backend" exists.
2. HAProxy should set "ssl_certs_exist" when it loads up, depending on
whether certificates have been found or not.

Simos


>
>> Le 29 mai 2017 à 11:09, Emmanuel Hocdet <[email protected]> a écrit :
>>
>>
>> Hi Simos,
>>
>> The workaround is to have a default (fake) certificat in first and use « strict-sni » parameter.
>>
>> Manu
>>
>>> Le 22 mai 2017 à 10:28, Simos Xenitellis <[email protected]> a écrit :
>>>
>>> Hi All,
>>>
>>> I am trying to automate some tasks with adding multiple https
>>> (LetsEncrypt) websites,
>>> and using HAProxy as a TLS Termination Proxy.
>>>
>>> The problem is that when you start off with an empty server, there are
>>> no certificates yet,
>>> and it is not possible to have "bind *:443 ssl crt
>>> /etc/haproxy/certs/..." in haproxy.cfg.
>>>
>>> LetsEncrypt can work with http, so it could easily use the "bind *:80"
>>> front-end in the beginning.
>>>
>>> Is there a way to express "If no certificates are found in
>>> /etc/haproxy/certs/, then do not bind *:443"?
>>>
>>> Simos
>>>
>>
>
>
> Le 15 juin 2017 à 16:42, Simos Xenitellis <[email protected]> a écrit :
>
> On Mon, Jun 12, 2017 at 5:21 PM, Emmanuel Hocdet <[email protected]> wrote:
>> In haproxy 1.8dev, default certificate can now be optional.
>> This patch allow that.
>>
>
> Thanks Manu for looking into this.
>
> Here is my use-case:
>
> 1. A "frontend" would bind on port 80 and then look whether a request
> is from Letsencrypt (URL: ~/.well-known/..). That is, an "http-01"
> challenge request.
> If so, it would forward the connection to a backend that deals with
> certificates (that backend initiated this request in the first place).
> If it is not an "http-01" challenge request, then it would redirect to https.
>
> 2. Another frontend would bind to port 443, and the "bind" line would
> have a new keyword like "disable-if-no-certs".
> If there are no certs yet installed, haproxy would cancel out the
> whole frontend for port 443 and would not bind port 443.
>
>
> Ideally, this would be implemented cleanly if there was a way to simply specify
>
> use_frontend myhttps if { ssl_certs_exist }
>
> Also, we could then specify to redirect to https (first frontend
> earlier ) if { ssl_certs_exist }.
>

with this patch you will not need such complicated needs.
just do:
bind :443 ssl strict-sni crt /my/cert/directory/

without this patch you need to have at least one certificate (fake or not)

>
> For this to work, it would require:
>
> 1. Addition of keyboard "use_frontend", just like "use_backend" exists.
> 2. HAProxy should set "ssl_certs_exist" when it loads up, depending on
> whether certificates have been found or not.
>
> Simos
>
>
>>
>>> Le 29 mai 2017 à 11:09, Emmanuel Hocdet <[email protected]> a écrit :
>>>
>>>
>>> Hi Simos,
>>>
>>> The workaround is to have a default (fake) certificat in first and use « strict-sni » parameter.
>>>
>>> Manu
>>>
>>>> Le 22 mai 2017 à 10:28, Simos Xenitellis <[email protected]> a écrit :
>>>>
>>>> Hi All,
>>>>
>>>> I am trying to automate some tasks with adding multiple https
>>>> (LetsEncrypt) websites,
>>>> and using HAProxy as a TLS Termination Proxy.
>>>>
>>>> The problem is that when you start off with an empty server, there are
>>>> no certificates yet,
>>>> and it is not possible to have "bind *:443 ssl crt
>>>> /etc/haproxy/certs/..." in haproxy.cfg.
>>>>
>>>> LetsEncrypt can work with http, so it could easily use the "bind *:80"
>>>> front-end in the beginning.
>>>>
>>>> Is there a way to express "If no certificates are found in
>>>> /etc/haproxy/certs/, then do not bind *:443"?
>>>>
>>>> Simos
>>>>
>>>
>>
>>
Hi Willy, Emeric

Can you consider this patch? I think it’s safe and it not depend on any openssl version.
(It’s possible since patch f6b37c67)

++
Manu


> Le 16 juin 2017 à 10:48, Emmanuel Hocdet <[email protected]> a écrit :
>
>> Le 15 juin 2017 à 16:42, Simos Xenitellis <[email protected]> a écrit :
>>
>> On Mon, Jun 12, 2017 at 5:21 PM, Emmanuel Hocdet <[email protected]> wrote:
>>> In haproxy 1.8dev, default certificate can now be optional.
>>> This patch allow that.
>>>
>>
>> Thanks Manu for looking into this.
>>
>> Here is my use-case:
>>
>> 1. A "frontend" would bind on port 80 and then look whether a request
>> is from Letsencrypt (URL: ~/.well-known/..). That is, an "http-01"
>> challenge request.
>> If so, it would forward the connection to a backend that deals with
>> certificates (that backend initiated this request in the first place).
>> If it is not an "http-01" challenge request, then it would redirect to https.
>>
>> 2. Another frontend would bind to port 443, and the "bind" line would
>> have a new keyword like "disable-if-no-certs".
>> If there are no certs yet installed, haproxy would cancel out the
>> whole frontend for port 443 and would not bind port 443.
>>
>>
>> Ideally, this would be implemented cleanly if there was a way to simply specify
>>
>> use_frontend myhttps if { ssl_certs_exist }
>>
>> Also, we could then specify to redirect to https (first frontend
>> earlier ) if { ssl_certs_exist }.
>>
>
> with this patch you will not need such complicated needs.
> just do:
> bind :443 ssl strict-sni crt /my/cert/directory/
>
> without this patch you need to have at least one certificate (fake or not)
>
>>
>> For this to work, it would require:
>>
>> 1. Addition of keyboard "use_frontend", just like "use_backend" exists.
>> 2. HAProxy should set "ssl_certs_exist" when it loads up, depending on
>> whether certificates have been found or not.
>>
>> Simos
>>
>>
>>>
>>>> Le 29 mai 2017 à 11:09, Emmanuel Hocdet <[email protected]> a écrit :
>>>>
>>>>
>>>> Hi Simos,
>>>>
>>>> The workaround is to have a default (fake) certificat in first and use « strict-sni » parameter.
>>>>
>>>> Manu
>>>>
>>>>> Le 22 mai 2017 à 10:28, Simos Xenitellis <[email protected]> a écrit :
>>>>>
>>>>> Hi All,
>>>>>
>>>>> I am trying to automate some tasks with adding multiple https
>>>>> (LetsEncrypt) websites,
>>>>> and using HAProxy as a TLS Termination Proxy.
>>>>>
>>>>> The problem is that when you start off with an empty server, there are
>>>>> no certificates yet,
>>>>> and it is not possible to have "bind *:443 ssl crt
>>>>> /etc/haproxy/certs/..." in haproxy.cfg.
>>>>>
>>>>> LetsEncrypt can work with http, so it could easily use the "bind *:80"
>>>>> front-end in the beginning.
>>>>>
>>>>> Is there a way to express "If no certificates are found in
>>>>> /etc/haproxy/certs/, then do not bind *:443"?
>>>>>
>>>>> Simos
>>>>>
>>>>
>>>
>>>
>
Le 27/07/2017 à 18:16, Emmanuel Hocdet a écrit :
>
> Hi Willy, Emeric
>
> Can you consider this patch? I think it’s safe and it not depend on any
> openssl version.
> (It’s possible since patch f6b37c67)
>

Hi Manu,

Since this commit, the certificates generation doesn't work anymore. I'm
working on a patch. I'll send it today I guess.

To work, the certificates generation uses the default certificate, to
get its private key. It uses it for the generated certificates. Generate
keys is pretty expensive and the one from the default certificate is not
worse than another.

Since commit f6b37c67, when certificates generation is performed,
instead of the default certificate (default_ctx), the SSL connection is
attached to the initial one (initial_ctx). The last one does not have
private key, so the generation always fails.

My first idea to fix the patch was to remove the initial_ctx. Because by
checking all recent changes, it seems useless. Its initialization is
done in the same time than default_ctx (that was not the case when
initial_ctx was introduced in commit f6b37c67).

But it is definitely in conflict with you current patch. Because without
initial_ctx, we need to have a default_ctx. So I can probably work
around this problem. But before doing it, I prefer to know if your patch
will be accepted or not :)

From my point of view, I can't see why anyone would want to start a SSL
frontend without any certificate. Because it will reject all
connections. Simos explained his use-case with Letsencrypt. But it is
only useful for the first generation of the first certificate. It is
easy to comment the SSL frontend at this step. Get a certificate from
Letsencrypt or generate a default one by hand is quick and trivial. To
automate this part, you can have a default certificate, probably
self-signed, and the strict-sni parameter on the bind line (You already
proposed this solution). For me, this is not a workaround, this is the
way to do it. But that's just my opinion, I can understand the need :)
So I'll let Willy and/or Emeric make the final decision.

--
Christopher Faulet
On Fri, Jul 28, 2017 at 11:08:33AM +0200, Christopher Faulet wrote:
> But it is definitely in conflict with you current patch. Because without
> initial_ctx, we need to have a default_ctx. So I can probably work around
> this problem. But before doing it, I prefer to know if your patch will be
> accepted or not :)

I think we don't know :-) The only thing I understood is that Manu's
patch was a fix but that it didn't find the rest of the breakage you
spotted, and conflicts with another possible fix. So you seem to be
the only two ones understanding what is broken and why (or each having
an idea about part of it), so I think we'll calmly rely on you both to
figure what needs to be fixed.

> From my point of view, I can't see why anyone would want to start a SSL
> frontend without any certificate. Because it will reject all connections.
> Simos explained his use-case with Letsencrypt. But it is only useful for the
> first generation of the first certificate. It is easy to comment the SSL
> frontend at this step. Get a certificate from Letsencrypt or generate a
> default one by hand is quick and trivial. To automate this part, you can
> have a default certificate, probably self-signed, and the strict-sni
> parameter on the bind line (You already proposed this solution). For me,
> this is not a workaround, this is the way to do it. But that's just my
> opinion, I can understand the need :) So I'll let Willy and/or Emeric make
> the final decision.

I personally think that with the current architecture it does indeed not
make much sense to start without any cert, but that in the future we may
go towards this direction to further improve what can dynamically be updated
without restarting.

At the moment Letsencrypt requires manual changes anyway so the reload is
inevitable and the extra complexity involved by the changes do not provide
any benefit.

For the long term we could imagine having native support for Letsencrypt
(or whatever else will have replaced it) and think about how to implement
it correctly. We might not be that far from being able to do it considering
that you're already capable of issuing certs on the fly, which means that
some parts already support dynamic certs being loaded.

So it means to me that we need to be forwardthinking but that's not a
reason for needlessly bloating everything. Baby steps are more reasonable.

Just my two cents,
Willy
Hi Christopher

> Le 28 juil. 2017 à 11:08, Christopher Faulet <[email protected]> a écrit :
>
> Le 27/07/2017 à 18:16, Emmanuel Hocdet a écrit :
>> Hi Willy, Emeric
>> Can you consider this patch? I think it’s safe and it not depend on any openssl version.
>> (It’s possible since patch f6b37c67)
>
> Hi Manu,
>
> Since this commit, the certificates generation doesn't work anymore. I'm working on a patch. I'll send it today I guess.
>
> To work, the certificates generation uses the default certificate, to get its private key. It uses it for the generated certificates. Generate keys is pretty expensive and the one from the default certificate is not worse than another.
>
> Since commit f6b37c67, when certificates generation is performed, instead of the default certificate (default_ctx), the SSL connection is attached to the initial one (initial_ctx). The last one does not have private key, so the generation always fails.
>

Oh i remember now. I have discarded the split between initial_ctx and default_ctx to not touch any dependancy with generate certificat.
And introduce it finally in f6b37c67 to fix a bug.

The only dependancy to default_ctx is the private key?

> My first idea to fix the patch was to remove the initial_ctx. Because by checking all recent changes, it seems useless. Its initialization is done in the same time than default_ctx (that was not the case when initial_ctx was introduced in commit f6b37c67).
>
> But it is definitely in conflict with you current patch. Because without initial_ctx, we need to have a default_ctx. So I can probably work around this problem. But before doing it, I prefer to know if your patch will be accepted or not :)

Private key is the only missing thing for generate certificat?

such patch can fix the issue?
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index c71c2e3..00ebb80 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -4328,6 +4328,12 @@ int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
node = ebmb_next(node);
}
+
+#ifndef SSL_NO_GENERATE_CERTIFICATES
+ if (bind_conf->default_ctx) {
+ SSL_CTX_use_PrivateKey(bind_conf->initial_ctx, SSL_CTX_get0_privatekey(bind_conf->default_ctx));
+ } /* else generate error */
+#endif
return err;
}



> From my point of view, I can't see why anyone would want to start a SSL frontend without any certificate. Because it will reject all connections. Simos explained his use-case with Letsencrypt. But it is only useful for the first generation of the first certificate. It is easy to comment the SSL frontend at this step. Get a certificate from Letsencrypt or generate a default one by hand is quick and trivial. To automate this part, you can have a default certificate, probably self-signed, and the strict-sni parameter on the bind line (You already proposed this solution). For me, this is not a workaround, this is the way to do it. But that's just my opinion, I can understand the need :) So I'll let Willy and/or Emeric make the final decision.

A useless certificat should be provide with haproxy configuration?, it’s definitely a workaround. It’s legacy from pre SNI.

++
Manu
> Le 28 juil. 2017 à 12:41, Emmanuel Hocdet <[email protected]> a écrit :
>
>
> Hi Christopher
>
>> Le 28 juil. 2017 à 11:08, Christopher Faulet <[email protected] <mailto:[email protected]>> a écrit :
>>
>> Le 27/07/2017 à 18:16, Emmanuel Hocdet a écrit :
>>> Hi Willy, Emeric
>>> Can you consider this patch? I think it’s safe and it not depend on any openssl version.
>>> (It’s possible since patch f6b37c67)
>>
>> Hi Manu,
>>
>> Since this commit, the certificates generation doesn't work anymore. I'm working on a patch. I'll send it today I guess.
>>
>> To work, the certificates generation uses the default certificate, to get its private key. It uses it for the generated certificates. Generate keys is pretty expensive and the one from the default certificate is not worse than another.
>>
>> Since commit f6b37c67, when certificates generation is performed, instead of the default certificate (default_ctx), the SSL connection is attached to the initial one (initial_ctx). The last one does not have private key, so the generation always fails.
>>
>
> Oh i remember now. I have discarded the split between initial_ctx and default_ctx to not touch any dependancy with generate certificat.
> And introduce it finally in f6b37c67 to fix a bug.
>
> The only dependancy to default_ctx is the private key?
>
>> My first idea to fix the patch was to remove the initial_ctx. Because by checking all recent changes, it seems useless. Its initialization is done in the same time than default_ctx (that was not the case when initial_ctx was introduced in commit f6b37c67).
>>
>> But it is definitely in conflict with you current patch. Because without initial_ctx, we need to have a default_ctx. So I can probably work around this problem. But before doing it, I prefer to know if your patch will be accepted or not :)
>
> Private key is the only missing thing for generate certificat?
>
> such patch can fix the issue?
> diff --git a/src/ssl_sock.c b/src/ssl_sock.c
> index c71c2e3..00ebb80 100644
> --- a/src/ssl_sock.c
> +++ b/src/ssl_sock.c
> @@ -4328,6 +4328,12 @@ int ssl_sock_prepare_all_ctx(struct bind_conf *bind_conf)
> err += ssl_sock_prepare_ctx(bind_conf, sni->conf, sni->ctx);
> node = ebmb_next(node);
> }
> +
> +#ifndef SSL_NO_GENERATE_CERTIFICATES
> + if (bind_conf->default_ctx) {
> + SSL_CTX_use_PrivateKey(bind_conf->initial_ctx, SSL_CTX_get0_privatekey(bind_conf->default_ctx));
> + } /* else generate error */
> +#endif
> return err;
> }
>
>

.. fix generate_certificates issue
perhaps it’s more simple to do:
diff --git a/src/ssl_sock.c b/src/ssl_sock.c
index c71c2e3..311d465 100644
--- a/src/ssl_sock.c
+++ b/src/ssl_sock.c
@@ -1587,7 +1587,7 @@ ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL
int key_type;

/* Get the private key of the defautl certificate and use it */
- if (!(pkey = SSL_get_privatekey(ssl)))
+ if (!pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx))
goto mkcert_error;

/* Create the certificate */

.. for the patch "allow haproxy to start without default certificate"
default_ctx could be required when bind_conf.generate_certs is set.

>
>> From my point of view, I can't see why anyone would want to start a SSL frontend without any certificate. Because it will reject all connections. Simos explained his use-case with Letsencrypt. But it is only useful for the first generation of the first certificate. It is easy to comment the SSL frontend at this step. Get a certificate from Letsencrypt or generate a default one by hand is quick and trivial. To automate this part, you can have a default certificate, probably self-signed, and the strict-sni parameter on the bind line (You already proposed this solution). For me, this is not a workaround, this is the way to do it. But that's just my opinion, I can understand the need :) So I'll let Willy and/or Emeric make the final decision.
>
> A useless certificat should be provide with haproxy configuration?, it’s definitely a workaround. It’s legacy from pre SNI.
>
> ++
> Manu
Le 28/07/2017 à 14:28, Emmanuel Hocdet a écrit :
> . fix generate_certificates issue
> perhaps it’s more simple to do:
> *diff --git a/src/ssl_sock.c b/src/ssl_sock.c*
> *index c71c2e3..311d465 100644*
> *--- a/src/ssl_sock.c*
> *+++ b/src/ssl_sock.c*
> @@ -1587,7 +1587,7 @@ssl_sock_do_create_cert(const char *servername,
> struct bind_conf *bind_conf, SSL
> int key_type;
>
>
> /* Get the private key of the defautl certificate and use it */
> - if (!(pkey = SSL_get_privatekey(ssl)))
> +if (!pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx))
> goto mkcert_error;
>
>
> /* Create the certificate */
>
> . for the patch "allow haproxy to start without default certificate"
> default_ctx could be required when bind_conf.generate_certs is set.
>
SSL_CTX_get0_privatekey is only available in openssl >= 1.0.2. So for
previous versions, you need to create a SSL object with the default
certificate and then extract the private key:

@@ -1637,7 +1639,17 @@ ssl_sock_do_create_cert(const char *servername,
struct bind_conf *bind_conf, SSL
int key_type;

/* Get the private key of the defautl certificate and use it */
- if (!(pkey = SSL_get_privatekey(ssl)))
+#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined
LIBRESSL_VERSION_NUMBER)
+ pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
+#else
+ SSL *tmp_ssl = SSL_new(bind_conf->default_ctx);
+
+ if (tmp_ssl) {
+ pkey = SSL_get_privatekey(tmp_ssl);
+ SSL_free(tmp_ssl);
+ }
+#endif
+ if (!pkey)
goto mkcert_error;


This is the workaround I mentioned in my previous mail. That's
acceptable, but my question remains. Is the initial certificate is still
needed ?

Even if we allow haproxy to be started without default certificate, we
can probably remove initial_ctx. That's just I want to be sure to not
have missed something :)

--
Christopher Faulet
Le 28/07/2017 à 12:41, Emmanuel Hocdet a écrit :
>
> A useless certificat should be provide with haproxy configuration?, it’s
> definitely a workaround. It’s legacy from pre SNI.
>

Not really. The default certificate is not useless. It is the
certificate to use when no other matches. Expect if you use the
"strict-sni" option, it should be chosen carefully, because everyone can
fallback on it. And by default, "strict-sni" is disabled.

But here the question is not to know if having a default certificate is
a good or a bad thing but it is if an SSL listener without any
certificate is an error or not. I think it should be by default, because
this is the current behavior and some users may want to rely on it to
detect problems. So if we want to support it, it should be done using a
keyword.

Then, I agree that the feature could be nice, especially, as Willy said,
if we add a way to load certificates on the fly. But I still think that
having a listener rejecting all connections is a bit clumsy. It could be
far better to parse its configuration but disable it. However, I don't
see an easy way to do this automatically :) So, for now, maybe having a
keyword to let HAProxy starts is a good compromise.

--
Christopher
> Le 28 juil. 2017 à 15:37, Christopher Faulet <[email protected]> a écrit :
>
> Le 28/07/2017 à 14:28, Emmanuel Hocdet a écrit :
>> . fix generate_certificates issue
>> perhaps it’s more simple to do:
>> *diff --git a/src/ssl_sock.c b/src/ssl_sock.c*
>> *index c71c2e3..311d465 100644*
>> *--- a/src/ssl_sock.c*
>> *+++ b/src/ssl_sock.c*
>> @@ -1587,7 +1587,7 @@ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL
>> int key_type;
>> /* Get the private key of the defautl certificate and use it */
>> - if (!(pkey = SSL_get_privatekey(ssl)))
>> +if (!pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx))
>> goto mkcert_error;
>> /* Create the certificate */
>> . for the patch "allow haproxy to start without default certificate"
>> default_ctx could be required when bind_conf.generate_certs is set.
> SSL_CTX_get0_privatekey is only available in openssl >= 1.0.2. So for previous versions, you need to create a SSL object with the default certificate and then extract the private key:
>
> @@ -1637,7 +1639,17 @@ ssl_sock_do_create_cert(const char *servername, struct bind_conf *bind_conf, SSL
> int key_type;
>
> /* Get the private key of the defautl certificate and use it */
> - if (!(pkey = SSL_get_privatekey(ssl)))
> +#if (OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined LIBRESSL_VERSION_NUMBER)
> + pkey = SSL_CTX_get0_privatekey(bind_conf->default_ctx);
> +#else
> + SSL *tmp_ssl = SSL_new(bind_conf->default_ctx);
> +
> + if (tmp_ssl) {
> + pkey = SSL_get_privatekey(tmp_ssl);
> + SSL_free(tmp_ssl);
> + }
> +#endif
> + if (!pkey)
> goto mkcert_error;
>

okay compat…
SSL_free should not be call until pkey is dup. for SSL_get_privatekey:
"These functions retrieve certificate and key data from an SSL object. They return internal pointers that must not be freed by the application program. »

perhaps add the declaration in openssl-compat.h:
EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx)
{
if (ctx->cert != NULL)
return ctx->cert->key->privatekey;
else
return NULL;
}

>
> This is the workaround I mentioned in my previous mail. That's acceptable, but my question remains. Is the initial certificate is still needed ?
>
> Even if we allow haproxy to be started without default certificate, we can probably remove initial_ctx. That's just I want to be sure to not have missed something :)
>
initial_ctx is still needed, remove it could be painful.
The case is ssl params per certificate. take on bind line with only crt-list.
crtlist:
a.pem [ alpn h2,http/1.1]
b.pem

default_ctx is set with the first parsed certificate (and is configuration)
b.pem will inherited from « alpn » configuration from a.pem
to fix that:
1) clean all ssl configuration inherited from default_ctx (does not work in all cases, much time spent testing with openssl versionS)
2) change the definition of default_ctx: first parsed certificate without is configuration (only the bind configuration)
I don’t want do that, this is an unexpected behavior
3) force usage of one crt in bind line to set the default cert (and before crt-list)
It break old configurations. (and i don’t want a default cert)
other? i try, fail and fix with introduce initial_ctx to normalise the behavior in a clean manner.

++
Manu
Le 28/07/2017 à 16:35, Emmanuel Hocdet a écrit :
>
> okay compat…
> SSL_free should not be call until pkey is dup. for SSL_get_privatekey:
> "These functions retrieve certificate and key data from an SSL object.
> They return internal pointers that must not be freed by the application
> program. »
>

Good catch

> perhaps add the declaration in openssl-compat.h:
> EVP_PKEY *SSL_CTX_get0_privatekey(const SSL_CTX *ctx)
> {
> if (ctx->cert != NULL)
> return ctx->cert->key->privatekey;
> else
> return NULL;
> }
>

Good idea, I'll do that


>>
> initial_ctx is still needed, remove it could be painful.
> The case is ssl params per certificate. take on bind line with only
> crt-list.
> crtlist:
> a.pem [ alpn h2,http/1.1]
> b.pem
>
> default_ctx is set with the first parsed certificate (and is configuration)
> b.pem will inherited from « alpn » configuration from a.pem
> to fix that:
> 1) clean all ssl configuration inherited from default_ctx (does not work
> in all cases, much time spent testing with openssl versionS)
> 2) change the definition of default_ctx: first parsed certificate
> without is configuration (only the bind configuration)
> I don’t want do that, this is an unexpected behavior
> 3) force usage of one crt in bind line to set the default cert (and
> before crt-list)
> It break old configurations. (and i don’t want a default cert)
> other? i try, fail and fix with introduce initial_ctx to normalise the
> behavior in a clean manner.
>

Ok, Thanks for you explanations. I'll keep initial_ctx so. I'll quickly
proposed a patch to fix certificates generation.

--
Christopher Faulet
> Le 28 juil. 2017 à 16:24, Christopher Faulet <[email protected]> a écrit :
>
> Le 28/07/2017 à 12:41, Emmanuel Hocdet a écrit :
>> A useless certificat should be provide with haproxy configuration?, it’s definitely a workaround. It’s legacy from pre SNI.
>
> Not really. The default certificate is not useless. It is the certificate to use when no other matches. Expect if you use the "strict-sni" option, it should be chosen carefully, because everyone can fallback on it. And by default, "strict-sni" is disabled.
>

I talk with the case we don’t want a default cert. With strict-sni the « fake » default_cert can be use if it as sni (i don’t want that ideally).
with strict-sni: no certificate match sni -> no ssl connection.
I add strict-sni to haproxy because customers call when browser show warning with https on their vhost (without certificat), and they don’t wont that.

> But here the question is not to know if having a default certificate is a good or a bad thing but it is if an SSL listener without any certificate is an error or not. I think it should be by default, because this is the current behavior and some users may want to rely on it to detect problems. So if we want to support it, it should be done using a keyword.
>

The question is: force to have a default certificat is really necessary? generate an error or move to a warning?
I understand the old use case but what about the strict-sni use case? is not incompatible with the default_ctx relax.

> Then, I agree that the feature could be nice, especially, as Willy said, if we add a way to load certificates on the fly. But I still think that having a listener rejecting all connections is a bit clumsy. It could be far better to parse its configuration but disable it. However, I don't see an easy way to do this automatically :) So, for now, maybe having a keyword to let HAProxy starts is a good compromise.

Manu
On Fri, Jul 28, 2017 at 05:04:16PM +0200, Emmanuel Hocdet wrote:
> I talk with the case we don't want a default cert. With strict-sni the « fake
> » default_cert can be use if it as sni (i don't want that ideally).
> with strict-sni: no certificate match sni -> no ssl connection.
> I add strict-sni to haproxy because customers call when browser show warning
> with https on their vhost (without certificat), and they don't wont that.

That's a good point to keep in mind.

> The question is: force to have a default certificat is really necessary?
> generate an error or move to a warning? I understand the old use case but
> what about the strict-sni use case? is not incompatible with the default_ctx
> relax.

The default cert is useful every time the strict-sni is not in use. In fact
you are in the position of a hosting provider with no reason for presenting
your company's name instead of a hosted customer's cert when unknown, but
the other situation is very common : company "acme" has a certificate for
"www.acme.com" and occasionally needs a temporary vhost on "dev.acme.com"
or "cms.acme.com" or "support.acme.com" but they don't want to have to buy
and deploy an extra cert just for this, especially when they already have
a few domains in the alt names of the first cert. So it's very common to
see them just create the new name and fall back to the default cert. For
partners it's not a problem, they see a browser warning, they check it,
can confirm the cert is not for the correct hostname but valid for the same
domain (eg: www.acme.com when they asked for support.acme.com) and they can
pass through. It also happens with multi-tld names. You can have "acme.fr"
redirect to "acme.com" without having to buy a cert for "acme.fr". Just a
warning once in a while and that's all.

Then of course there's the case of the certificate generation on the fly
which needs one private key. Using that of the default cert is the current
choice and it makes quite some sense. It's obviously exclusive with strict-sni
by definition!

All these use cases are pretty valid and we just need to keep them all in
mind when seeking the proper fix.

Willy
> Le 28 juil. 2017 à 17:13, Willy Tarreau <[email protected]> a écrit :
>
> On Fri, Jul 28, 2017 at 05:04:16PM +0200, Emmanuel Hocdet wrote:
>> I talk with the case we don't want a default cert. With strict-sni the « fake
>> » default_cert can be use if it as sni (i don't want that ideally).
>> with strict-sni: no certificate match sni -> no ssl connection.
>> I add strict-sni to haproxy because customers call when browser show warning
>> with https on their vhost (without certificat), and they don't wont that.
>
> That's a good point to keep in mind.
>
>> The question is: force to have a default certificat is really necessary?
>> generate an error or move to a warning? I understand the old use case but
>> what about the strict-sni use case? is not incompatible with the default_ctx
>> relax.
>
> The default cert is useful every time the strict-sni is not in use. In fact
> you are in the position of a hosting provider with no reason for presenting
> your company's name instead of a hosted customer's cert when unknown, but
> the other situation is very common : company "acme" has a certificate for
> "www.acme.com" and occasionally needs a temporary vhost on "dev.acme.com"
> or "cms.acme.com" or "support.acme.com" but they don't want to have to buy
> and deploy an extra cert just for this, especially when they already have
> a few domains in the alt names of the first cert. So it's very common to
> see them just create the new name and fall back to the default cert. For
> partners it's not a problem, they see a browser warning, they check it,
> can confirm the cert is not for the correct hostname but valid for the same
> domain (eg: www.acme.com when they asked for support.acme.com) and they can
> pass through. It also happens with multi-tld names. You can have "acme.fr"
> redirect to "acme.com" without having to buy a cert for "acme.fr". Just a
> warning once in a while and that's all.
>
> Then of course there's the case of the certificate generation on the fly
> which needs one private key. Using that of the default cert is the current
> choice and it makes quite some sense. It's obviously exclusive with strict-sni
> by definition!
>
> All these use cases are pretty valid and we just need to keep them all in
> mind when seeking the proper fix.

I propose:
strict_sni is set and generated_cert is not set: default_cert is optional (with or without warning?)
else default_cert is required

++
Manu
> Le 28 juil. 2017 à 17:48, Emmanuel Hocdet <[email protected]> a écrit :
>
>>
>> Le 28 juil. 2017 à 17:13, Willy Tarreau <[email protected]> a écrit :
>>
>> On Fri, Jul 28, 2017 at 05:04:16PM +0200, Emmanuel Hocdet wrote:
>>> I talk with the case we don't want a default cert. With strict-sni the « fake
>>> » default_cert can be use if it as sni (i don't want that ideally).
>>> with strict-sni: no certificate match sni -> no ssl connection.
>>> I add strict-sni to haproxy because customers call when browser show warning
>>> with https on their vhost (without certificat), and they don't wont that.
>>
>> That's a good point to keep in mind.
>>
>>> The question is: force to have a default certificat is really necessary?
>>> generate an error or move to a warning? I understand the old use case but
>>> what about the strict-sni use case? is not incompatible with the default_ctx
>>> relax.
>>
>> The default cert is useful every time the strict-sni is not in use. In fact
>> you are in the position of a hosting provider with no reason for presenting
>> your company's name instead of a hosted customer's cert when unknown, but
>> the other situation is very common : company "acme" has a certificate for
>> "www.acme.com" and occasionally needs a temporary vhost on "dev.acme.com"
>> or "cms.acme.com" or "support.acme.com" but they don't want to have to buy
>> and deploy an extra cert just for this, especially when they already have
>> a few domains in the alt names of the first cert. So it's very common to
>> see them just create the new name and fall back to the default cert. For
>> partners it's not a problem, they see a browser warning, they check it,
>> can confirm the cert is not for the correct hostname but valid for the same
>> domain (eg: www.acme.com when they asked for support.acme.com) and they can
>> pass through. It also happens with multi-tld names. You can have "acme.fr"
>> redirect to "acme.com" without having to buy a cert for "acme.fr". Just a
>> warning once in a while and that's all.
>>
>> Then of course there's the case of the certificate generation on the fly
>> which needs one private key. Using that of the default cert is the current
>> choice and it makes quite some sense. It's obviously exclusive with strict-sni
>> by definition!
>>
>> All these use cases are pretty valid and we just need to keep them all in
>> mind when seeking the proper fix.
>
> I propose:
> strict_sni is set and generated_cert is not set: default_cert is optional (with or without warning?)
> else default_cert is required

to be exact:
/default_cert/have at least one certificate in bind configuration/

Manu
On Fri, Jul 28, 2017 at 06:01:10PM +0200, Emmanuel Hocdet wrote:
>
> > Le 28 juil. 2017 à 17:48, Emmanuel Hocdet <[email protected]> a écrit :
> > I propose:
> > strict_sni is set and generated_cert is not set: default_cert is optional (with or without warning?)
> > else default_cert is required
>
> to be exact:
> /default_cert/have at least one certificate in bind configuration/

I understood just before this sentence :-)
I think it's fine not to have a default_cert if not needed
(strict_sni && !generate). I don't know if it complicates anything
or not though.

Willy
> Le 28 juil. 2017 à 18:43, Willy Tarreau <[email protected]> a écrit :
>
> On Fri, Jul 28, 2017 at 06:01:10PM +0200, Emmanuel Hocdet wrote:
>>
>>> Le 28 juil. 2017 à 17:48, Emmanuel Hocdet <[email protected]> a écrit :
>>> I propose:
>>> strict_sni is set and generated_cert is not set: default_cert is optional (with or without warning?)
>>> else default_cert is required
>>
>> to be exact:
>> /default_cert/have at least one certificate in bind configuration/
>
> I understood just before this sentence :-)
ok :-)

> I think it's fine not to have a default_cert if not needed

The default_cert is always set with the first certificate.
The default_cert is used if no certificate match sni.
With strict-sni, the default_cert is never used as this.
With strict-sni, fail on ssl connection is ok.
Have no certificate in bind line fail on all ssl connection. It’s ok with the behavior of strict-sni.

> (strict_sni && !generate). I don't know if it complicates anything
> or not though.

I think is not.
I'm on holiday for a week, i'll look at this after.

++
Manu
On Fri, Jul 28, 2017 at 07:17:24PM +0200, Emmanuel Hocdet wrote:
> > I think it's fine not to have a default_cert if not needed
>
> The default_cert is always set with the first certificate.
> The default_cert is used if no certificate match sni.
> With strict-sni, the default_cert is never used as this.
> With strict-sni, fail on ssl connection is ok.
> Have no certificate in bind line fail on all ssl connection. It's ok with the behavior of strict-sni.
>
> > (strict_sni && !generate). I don't know if it complicates anything
> > or not though.
>
> I think is not.
> I'm on holiday for a week, i'll look at this after.

OK! No rush anyway, what matters is to have a clear mind on how we want
all this stuff to work together. It's important to keep in mind that SSL
combinations become a bit complex and I feel like over the last few months,
we've caused various types of breakage by lacking a global view on all use
cases, so it's good to let things cool down a bit after having identified
them all. That tends to ignite more generic and cleaner designs.

Cheers,
Willy
Hi Willy, Emeric, Christopher

The new patch is much simpler:

++
Manu




> Le 28 juil. 2017 à 23:24, Willy Tarreau <[email protected]> a écrit :
>
> On Fri, Jul 28, 2017 at 07:17:24PM +0200, Emmanuel Hocdet wrote:
>>> I think it's fine not to have a default_cert if not needed
>>
>> The default_cert is always set with the first certificate.
>> The default_cert is used if no certificate match sni.
>> With strict-sni, the default_cert is never used as this.
>> With strict-sni, fail on ssl connection is ok.
>> Have no certificate in bind line fail on all ssl connection. It's ok with the behavior of strict-sni.
>>
>>> (strict_sni && !generate). I don't know if it complicates anything
>>> or not though.
>>
>> I think is not.
>> I'm on holiday for a week, i'll look at this after.
>
> OK! No rush anyway, what matters is to have a clear mind on how we want
> all this stuff to work together. It's important to keep in mind that SSL
> combinations become a bit complex and I feel like over the last few months,
> we've caused various types of breakage by lacking a global view on all use
> cases, so it's good to let things cool down a bit after having identified
> them all. That tends to ignite more generic and cleaner designs.
>
> Cheers,
> Willy
>
Attachments:
open | download - 0001-MINOR-ssl-allow-to-start-without-certificate-if-stri.patch (1.9 KB)
Hi Manu,

On Tue, Aug 08, 2017 at 03:00:47PM +0200, Emmanuel Hocdet wrote:
> Hi Willy, Emeric, Christopher
>
> The new patch is much simpler:

> From f2918c87910f3ba18a2536eee5f4b9573cc695e3 Mon Sep 17 00:00:00 2001
> From: Emmanuel Hocdet <[email protected]>
> Date: Sun, 30 Jul 2017 18:29:04 +0200
> Subject: [PATCH] MINOR: ssl: allow to start without certificate if strict-sni
> is set
> MIME-Version: 1.0
> Content-Type: text/plain; charset=UTF-8
> Content-Transfer-Encoding: 8bit
>
> With strict-sni, ssl connection will fail if no certificate match. Have no
> certificate in bind line, fail on all ssl connections. It’s ok with the
> behavior of strict-sni. When 'generate-certificates' is set 'strict-sni' is
> never used. When 'strict-sni' is set, default_ctx is never used. Allow to start
> without certificate only in this case.
>
> Use case is to start haproxy with ssl before customer start to use certificates.
> Typically with 'crt' on a empty directory and 'strict-sni' parameters.
> ---
> src/ssl_sock.c | 12 +++++++++---
> 1 file changed, 9 insertions(+), 3 deletions(-)
>
> diff --git a/src/ssl_sock.c b/src/ssl_sock.c
> index d81dd70..041cba6 100644
> --- a/src/ssl_sock.c
> +++ b/src/ssl_sock.c
> @@ -4283,9 +4283,15 @@ int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
> return 0;
> }
> if (!bind_conf->default_ctx) {
> - Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
> - px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
> - return -1;
> + if (bind_conf->strict_sni && !bind_conf->generate_certs) {
> + Warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
> + px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
> + }
> + else {
> + Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
> + px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
> + return -1;
> + }
> }
>
> alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global_ssl.private_cache && (global.nbproc > 1)) ? 1 : 0);

Quick question, what happens when we start in this case and only the
warning is emitted ? Will all SSL connections simply fail ? The impact
should be presented in the warning so that the user knows if he needs
to act on it or not. This aside, yes I think it should do the trick.

Thanks,
Willy
> Le 9 août 2017 à 08:37, Willy Tarreau <[email protected]> a écrit :
>
> Hi Manu,
>
> On Tue, Aug 08, 2017 at 03:00:47PM +0200, Emmanuel Hocdet wrote:
>> Hi Willy, Emeric, Christopher
>>
>> The new patch is much simpler:
>
>> From f2918c87910f3ba18a2536eee5f4b9573cc695e3 Mon Sep 17 00:00:00 2001
>> From: Emmanuel Hocdet <[email protected]>
>> Date: Sun, 30 Jul 2017 18:29:04 +0200
>> Subject: [PATCH] MINOR: ssl: allow to start without certificate if strict-sni
>> is set
>> MIME-Version: 1.0
>> Content-Type: text/plain; charset=UTF-8
>> Content-Transfer-Encoding: 8bit
>>
>> With strict-sni, ssl connection will fail if no certificate match. Have no
>> certificate in bind line, fail on all ssl connections. It’s ok with the
>> behavior of strict-sni. When 'generate-certificates' is set 'strict-sni' is
>> never used. When 'strict-sni' is set, default_ctx is never used. Allow to start
>> without certificate only in this case.
>>
>> Use case is to start haproxy with ssl before customer start to use certificates.
>> Typically with 'crt' on a empty directory and 'strict-sni' parameters.
>> ---
>> src/ssl_sock.c | 12 +++++++++---
>> 1 file changed, 9 insertions(+), 3 deletions(-)
>>
>> diff --git a/src/ssl_sock.c b/src/ssl_sock.c
>> index d81dd70..041cba6 100644
>> --- a/src/ssl_sock.c
>> +++ b/src/ssl_sock.c
>> @@ -4283,9 +4283,15 @@ int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
>> return 0;
>> }
>> if (!bind_conf->default_ctx) {
>> - Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
>> - px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
>> - return -1;
>> + if (bind_conf->strict_sni && !bind_conf->generate_certs) {
>> + Warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
>> + px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
>> + }
>> + else {
>> + Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
>> + px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
>> + return -1;
>> + }
>> }
>>
>> alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global_ssl.private_cache && (global.nbproc > 1)) ? 1 : 0);
>
> Quick question, what happens when we start in this case and only the
> warning is emitted ? Will all SSL connections simply fail ? The impact
> should be presented in the warning so that the user knows if he needs
> to act on it or not. This aside, yes I think it should do the trick.
>

Yes, connections simply fail, as is already with a fake 'default’ cert and strict-sni.

Manu
On Wed, Aug 09, 2017 at 10:26:54AM +0200, Emmanuel Hocdet wrote:
>
> > Le 9 août 2017 à 08:37, Willy Tarreau <[email protected]> a écrit :
> >
> > Hi Manu,
> >
> > On Tue, Aug 08, 2017 at 03:00:47PM +0200, Emmanuel Hocdet wrote:
> >> Hi Willy, Emeric, Christopher
> >>
> >> The new patch is much simpler:
> >
> >> From f2918c87910f3ba18a2536eee5f4b9573cc695e3 Mon Sep 17 00:00:00 2001
> >> From: Emmanuel Hocdet <[email protected]>
> >> Date: Sun, 30 Jul 2017 18:29:04 +0200
> >> Subject: [PATCH] MINOR: ssl: allow to start without certificate if strict-sni
> >> is set
> >> MIME-Version: 1.0
> >> Content-Type: text/plain; charset=UTF-8
> >> Content-Transfer-Encoding: 8bit
> >>
> >> With strict-sni, ssl connection will fail if no certificate match. Have no
> >> certificate in bind line, fail on all ssl connections. It’s ok with the
> >> behavior of strict-sni. When 'generate-certificates' is set 'strict-sni' is
> >> never used. When 'strict-sni' is set, default_ctx is never used. Allow to start
> >> without certificate only in this case.
> >>
> >> Use case is to start haproxy with ssl before customer start to use certificates.
> >> Typically with 'crt' on a empty directory and 'strict-sni' parameters.
> >> ---
> >> src/ssl_sock.c | 12 +++++++++---
> >> 1 file changed, 9 insertions(+), 3 deletions(-)
> >>
> >> diff --git a/src/ssl_sock.c b/src/ssl_sock.c
> >> index d81dd70..041cba6 100644
> >> --- a/src/ssl_sock.c
> >> +++ b/src/ssl_sock.c
> >> @@ -4283,9 +4283,15 @@ int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
> >> return 0;
> >> }
> >> if (!bind_conf->default_ctx) {
> >> - Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
> >> - px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
> >> - return -1;
> >> + if (bind_conf->strict_sni && !bind_conf->generate_certs) {
> >> + Warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
> >> + px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
> >> + }
> >> + else {
> >> + Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
> >> + px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
> >> + return -1;
> >> + }
> >> }
> >>
> >> alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global_ssl.private_cache && (global.nbproc > 1)) ? 1 : 0);
> >
> > Quick question, what happens when we start in this case and only the
> > warning is emitted ? Will all SSL connections simply fail ? The impact
> > should be presented in the warning so that the user knows if he needs
> > to act on it or not. This aside, yes I think it should do the trick.
> >
>
> Yes, connections simply fail, as is already with a fake 'default' cert and strict-sni.

Thanks. Then can you please update the message in the warning accordingly ?

Willy
> Le 9 août 2017 à 11:13, Willy Tarreau <[email protected]> a écrit :
>
> On Wed, Aug 09, 2017 at 10:26:54AM +0200, Emmanuel Hocdet wrote:
>>
>>> Le 9 août 2017 à 08:37, Willy Tarreau <[email protected]> a écrit :
>>>
>>> Hi Manu,
>>>
>>> On Tue, Aug 08, 2017 at 03:00:47PM +0200, Emmanuel Hocdet wrote:
>>>> Hi Willy, Emeric, Christopher
>>>>
>>>> The new patch is much simpler:
>>>
>>>> From f2918c87910f3ba18a2536eee5f4b9573cc695e3 Mon Sep 17 00:00:00 2001
>>>> From: Emmanuel Hocdet <[email protected]>
>>>> Date: Sun, 30 Jul 2017 18:29:04 +0200
>>>> Subject: [PATCH] MINOR: ssl: allow to start without certificate if strict-sni
>>>> is set
>>>> MIME-Version: 1.0
>>>> Content-Type: text/plain; charset=UTF-8
>>>> Content-Transfer-Encoding: 8bit
>>>>
>>>> With strict-sni, ssl connection will fail if no certificate match. Have no
>>>> certificate in bind line, fail on all ssl connections. It’s ok with the
>>>> behavior of strict-sni. When 'generate-certificates' is set 'strict-sni' is
>>>> never used. When 'strict-sni' is set, default_ctx is never used. Allow to start
>>>> without certificate only in this case.
>>>>
>>>> Use case is to start haproxy with ssl before customer start to use certificates.
>>>> Typically with 'crt' on a empty directory and 'strict-sni' parameters.
>>>> ---
>>>> src/ssl_sock.c | 12 +++++++++---
>>>> 1 file changed, 9 insertions(+), 3 deletions(-)
>>>>
>>>> diff --git a/src/ssl_sock.c b/src/ssl_sock.c
>>>> index d81dd70..041cba6 100644
>>>> --- a/src/ssl_sock.c
>>>> +++ b/src/ssl_sock.c
>>>> @@ -4283,9 +4283,15 @@ int ssl_sock_prepare_bind_conf(struct bind_conf *bind_conf)
>>>> return 0;
>>>> }
>>>> if (!bind_conf->default_ctx) {
>>>> - Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
>>>> - px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
>>>> - return -1;
>>>> + if (bind_conf->strict_sni && !bind_conf->generate_certs) {
>>>> + Warning("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
>>>> + px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
>>>> + }
>>>> + else {
>>>> + Alert("Proxy '%s': no SSL certificate specified for bind '%s' at [%s:%d] (use 'crt').\n",
>>>> + px->id, bind_conf->arg, bind_conf->file, bind_conf->line);
>>>> + return -1;
>>>> + }
>>>> }
>>>>
>>>> alloc_ctx = shared_context_init(global.tune.sslcachesize, (!global_ssl.private_cache && (global.nbproc > 1)) ? 1 : 0);
>>>
>>> Quick question, what happens when we start in this case and only the
>>> warning is emitted ? Will all SSL connections simply fail ? The impact
>>> should be presented in the warning so that the user knows if he needs
>>> to act on it or not. This aside, yes I think it should do the trick.
>>>
>>
>> Yes, connections simply fail, as is already with a fake 'default' cert and strict-sni.
>
> Thanks. Then can you please update the message in the warning accordingly ?

Yep:



Manu
Attachments:
open | download - 0001-MINOR-ssl-allow-to-start-without-certificate-if-stri.patch (1.9 KB)
Sorry, only registered users may post in this forum.

Click here to login