CARVIEW |
Navigation Menu
-
-
Notifications
You must be signed in to change notification settings - Fork 112
Mutual TLS-AUTH #337
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Mutual TLS-AUTH #337
Conversation
Second part (server authenticates the client): The second commit, adds a dedicated port on the server in order to enforce TLS Authentication for connecting clients (secondary servers) and address #336 from the server's side. nsd does not support multiple tls-port(s) so I had to put checks in multiple places to see if we are on tls-port or tls-auth-port. Another approach would be to put a tls-auth: yes/no knob where we could enforce tls authentication on the normal tls-port. Now let me explain a little about my initial approach which was adding tls-auth on provide-xfr acl. I've tried the approach of doing SSL_CTX_set_verify with SSL_VERIFY_PEER | SSL_VERIFY_POST_HANDSHAKE Client sends SSL_set_post_handshake_auth() in the first ClientHello to say that it supports Post-Handshake Authentication (PHA) Server carries data->tls pointer down to query_process() where it calls a new function process_tls_auth() in order to query_process() was the first place where the ACL requiring tls-auth was available to me.
Up to this point I knew if we are on an ACL that requires TLS-AUTH in order to provide XFR to that specific client. Don't know if the problem was calling SSL_do_handshake direct and not via tls_handshake() but it didn't work. This is where I stopped and though about tls-auth-port as a dedicated SSL_CTX that requires As I said, since this is the enforcing option, as well as passing a non-empty CAfile, this could also be done via a simpler YES/NO knob to enforce it on normal tls-port. |
The If the client has to set It is nicer if this option can exist together with regular tls service, so an on/off button is not really where I would take it either. But the check of client certificate at the initial handshake stage, on the tls_auth port, seems like a fine idea to me. If that works for the clients. |
I agree that most clients do not set it. There are multiple talks online about this and various browsers that do not want to set it. Don't know about resolvers.
I'm not 100% decided that an on/off knob is that bad. Maybe if you want different policies per zone (stubs for instance). But then you need to go down to the ACL and tls-auth. In any case the tls-auth-port seems the most friendly one in terms of compatibility and it does not sacrifice/alter the normal TLS behaviour. |
As a side note, if this is finally accepted, I would also add something like the following in the manual page, which is important in my opinion: Client's certificate name in not validated by the server. Server accepts any certificate presented by the client that is validated with tls-cert-bundle. If server uses the default verify location of the system, then any certificate signed by a valid CA is accepted. For this reason it is highly recommended to either setup a local PKI or create self signed certificates specifically for this purpose (XoT) for your secondary servers and only add those to a custom tls-cert-bundle file on the primary. |
@wcawijngaards do you know if this will be accepted? If yes, I would like to extend my work on top of this and address the 2 issues I've mentioned above.
This can be solved on the nsd side, by implementing something like a "tls-auth-xfr-only" yes/no knob
This can be solved by adding "tls-auth" in provide-xfr like it is in request-xfr, and use auth-domain-name from specified tls-auth, in order to verify client name is matching the presented certificate. The same way client verifies server's certificate. Interested on these? I believe they are not hard to implement and will add to the security. Now, for both of these to work I can pass both of them as args or the whole data struct pointer. What do you think is best? |
I would like to have this accepted. For passing the parameter, it is now part of tcp_data struct, but at line server.c:5293, over there, it can be stored as data->query->variable = variable_to_save; and then in the query handler it can use query->variable to access the information. The query->variable is then added to struct query in query.h. Perhaps that can help have the information accessible that is needed. |
e1df996
to
31dd982
Compare
1fb6ed0
to
43de2a4
Compare
Everything is ready and uploaded into this PR but in different commits.
Future work: These kind of protections can very easily be extended to other connections as well, such as notify, in order for all commucations between primaries/secondaries to be protected by TLS with authentication based on certificates. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you for the updates for the patch. It is very nice to have good mutual authentication. During review I found some issues that are serious enough to request changes before approval; a memory leak and a question on name comparison. The reason I am asking though, is also to make sure these changes are improvements, perhaps there is good reason for doing it this way. Maybe that code is there on purpose?
The memory leak and name comparisons have suggested code changes, and I would approve the patch if they are applied; and if you also think these are the correct way of handling the certificate names. Comparing only a substring of the name was I think not desirable, so I suggested strcasecmp that compares the entire name, and also case insensitively, since the examples from the reference do that too.
The suggestion is to remove SSL_CTX_set_default_verify_paths
, since the extra certificates could be a surprise for users that only want to use their own .pem file. And then suddenly public certificate authorities can allow access with certificates. I guess a separate change could add it, and also the newer fail if no peer cert option. A separate patch is not needed, right now. Although that is nicer for not changing the code path when this feature is not used, the question is if the suggested changes are alright for this patch.
apply changes from @wcawijngaards Co-authored-by: Wouter Wijngaards <wcawijngaards@users.noreply.github.com>
Generic case Co-authored-by: Wouter Wijngaards <wcawijngaards@users.noreply.github.com>
Co-authored-by: Wouter Wijngaards <wcawijngaards@users.noreply.github.com>
by @wcawijngaards: The value is set to a strdup of a string or left at NULL, and this then needs to be freed. Co-authored-by: Wouter Wijngaards <wcawijngaards@users.noreply.github.com>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The changes are looking good! Is it alright if I merge this now, or are there more edits you want to make?
I'm OK. Thanks for looking into this :) |
- Merge #337 from bilias: Mutual TLS-AUTH.
First part: Client side TLS-auth (client is authenticating to server).
[client's authentication of the server is fine]
commit 10eca88
When request-xfr is setup on secondary with tls-auth and client-cert/client-key defined,
client/secondary makes initial connection to server/primary without having setup it's client-cert and client-key at an early stage.
The order that is done on the client is:
SSL_CTX_new
SSL_CTX_set_default_verify_paths
SSL_CTX_load_verify_locations
SSL_new()
SSL_set_connect_state()
SSL_set_mode(tp->ssl, SSL_MODE_AUTO_RETRY);
SSL_set_verify(tp->ssl, SSL_VERIFY_PEER, tls_verify_callback);
SSL_set1_host(tp->ssl, auth_domain_name)
SSL_CTX_use_certificate_chain_file()
SSL_CTX_use_PrivateKey_file()
ssl_handshake()
So the first SSL_new() does not have certificate_chain_file/PrivateKey_file which are loaded on CTX and not inherited in that first SSL_new().
Subsequent connections have the key but the first connection does not.
If server is setup to require/force client cert/key, on server we see:
error: TLS handshake failed from 127.0.0.1 crypto error:0A0000C7:SSL routines::peer did not return a certificate
If we load first the cert/key on the client and then make connection to server,
client will reply to server's request for client authentication. I've just changed the order things are done.
This is the first patch, for the client side, in order for the client to authenticate correctly to server using tls-auth.
I'm preparing another patch for the server.c in order for the server to require/force client to authenticate on a provide-xfr using tls-auth and complete mutual auth.
#336