RFC5766-turn-server with TLS - ssl

I'm trying to start my TURN server with TLS enabled. I use the following line to start the server:
daemon --user=$USER $TURN $OPTIONS --tls-listening-port 3478 --cert /root/cert_2014_11/my_domain_nl.crt --pkey /root/cert_2014_11/my_domain_nl.key --CA-file /root/cert_2014_11/PositiveSSLCA2.crt
The environment variables in there are set in the config file. The server works fine without TLS using the same startup line, but if I add the three SSL related arguments, the server still isn't reachable over TLS. I tried setting a different port for SLL instead of the standard port, but it still didn't work. Whatever I do, I can reach the server without SLL, but over TLS I can't reach it. The certificate chain I use if fine, I use it for our website as well.

I've run into this exact problem before. Have a look at the documentation for the --CA-file argument:
--CA-file <filename> CA file in OpenSSL format.
Forces TURN server to verify the client SSL certificates.
By default, no CA is set and no client certificate check is performed.
This argument is needed only when you will be verifying client certificates. It's not for the certificate chain for your server certificate.
Drop the --CA-file argument, keeping the --cert and --pkey arguments.
EDIT: FYI, the certificate file you give to the --cert option can contain the entire certificate chain (yours and your CA's).

Related

Using and then removing self-signed certificate localhost

Problem Background:
As part of the Computer Networking course assignment, I have been given task of implementing a Proxy Server ( using python socket and ssl module ) that handles https communications between the browser and the origin server (The real server that my browser wants to talk to).
What I have done so far:
I have implemented the above requirement using ssl sockets and also generated self-signed 'cert.pem' 'key.pem' files.
What I need to do:
Now I just need to tell my browser (chrome 89 on kubuntu 20.04) to accept this self-signed certificate and then test the working of my proxy server.
Reading from this stackoverflow question, I can see that I have to:
(1) become my own CA (2) then sign my SSL certificate as a CA. (3) Then import the CA certificate (not the SSL certificate, which goes onto my server) into Chrome.
My confusion/question:
So if I do this, when eventually I am done with this assignment, how do I reverse all these steps to get my browser in the previous state before I had made all these changes. Also, how to reverse the "become your own CA" and also delete the SSL certificates signed by my CA.
Basically, I want my system to return to the previous state it was before I would have made all these changes.
UPDATE:
I have done the previously outlined steps but now I get an error.
Here is a snippet of my code:
serv_socket = socket(AF_INET, SOCK_STREAM)
serv_socket.bind(('', serv_port))
serv_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
context = context.load_cert_chain('cert.pem', 'key.pem')
context.set_ciphers('EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH')
serv_socket.listen(10)
socket_to_browser, addr = serv_socket.accept()
conn_socket_to_browser = context.wrap_socket(socket_to_browser, server_side=True)
At the last line conn_socket_to_browser = context.wrap_socket(socket_to_browser, server_side=True) an exception is thrown: [SSL: HTTPS_PROXY_REQUEST] https proxy request (_ssl.c:1123)
What am I doing wrong ?
As glamorous as "becoming your own CA" sounds, with openssl it basically comes down to creating a self-signed certificate, and then creating a directory where some CA-specific configuration will be stored (I don't fully remember the specifics, but I think it was just some files related to CNs and serial numbers) so basically reversing the "become your own CA" step is something as mundane as deleting this directory along with the private key and self-signed certificate you were using for the CA. That's it, the CA is no more.
And for chrome returning to the previous state, you would just go the the CA list where you added the CA certificate, select it and delete it. Chrome will stop accepting certificates signed by your CA.
Regarding your new problem... In my opinion, you have developed some kind of reverse proxy (meaning that you expect normal HTTPS requests that you then redirect to the real server) but you have configured Chrome to use it as a forward proxy. In this case, Chrome does not send it a normal HTTPS request, it sends a special non-encrypted CONNECT command and only after receiving the non-encrypted response, it negotiates the TLS connection. That's why openssl says "https proxy request" because it has detected a "https proxy request" (a CONNECT command) instead of the normal TLS negotiation.
You can take a look at How can a Python proxy server (using SSL socket) pretend to be an HTTPS server and specify my own keys to get decrypted data?
It's python, but I think that you'll get the idea

Simulate expiring SSL certificate

I'm looking for a service online, able to simulate an expiring SSL certificate. I know about badssl.com, but that only seems to include an expired certificate. What I'm looking to do is to call an endpoint with a certificate expiring in something like 5 days. Possible?
I do not know about an online service tailored to your needs (you could also try to contact badssl.com and ask them if they would be willing to add your test case, as it may profit others too), but locally you can run openssl s_server and configure it to use any local certificate you would have created to be in the situation you need to test.
From its manual:
The s_server command implements a generic SSL/TLS server which listens for connections on a given port using SSL/TLS.
and:
s_server can be used to debug SSL clients. To accept connections from a web browser the command:
openssl s_server -accept 443 -www
can be used for example.
Otherwise, if you are outside of the world wide web world:
If a connection request is established with an SSL client and neither the -www nor the -WWW option has been used then normally any data received from the client is displayed and any key presses will be sent to the client.
(and follows a list of special keys for special operations).

How to simulate non-SNI browsers (without SNI support)?

I'm setting up Apache with several distinct SSL certificates for different domains that reside on the same server (and thus sharing the same IP address).
With Qualys SSL Test I discovered that there are clients (i.e. BingBot as of december 2013) that do not support the SNI extension.
So I'm thinking about crafting a special default web application that can gather the requests of such clients, but how can I simulate those clients?
I'm on Windows 8, with no access to Linux boxes, if that matters.
You can use the most commonly used SSL library, OpenSSL. Windows binaries are available to download.
openssl s_client -connect domain.com:443 command serves very well to test SSL connection from client side. It doesn't support SNI by default. You can append -servername domain.com argument to enable SNI.
If you are using OpenSSL 1.1.0 or earlier version, use openssl s_client -connect $ip:$port, and OpenSSL wouldn't enable the SNI extension
If you are using OpenSSL 1.1.1, you need add -noservername flag to openssl s_client.
Similar to openssl s_client is gnutls-cli
gnutls-cli --disable-sni www.google.com
You could install Strawberry Perl and then use the following script to simulate a client not supporting SNI:
use strict;
use warnings;
use LWP::UserAgent;
my $ua = LWP::UserAgent->new(ssl_opts => {
# this disables SNI
SSL_hostname => '',
# These disable certificate verification, so that we get a connection even
# if the certificate does not match the requested host or is invalid.
# Do not use in production code !!!
SSL_verify_mode => 0,
verify_hostname => 0,
});
# request some data
my $res = $ua->get('https://example.com');
# show headers
# pseudo header Client-SSL-Cert-Subject gives information about the
# peers certificate
print $res->headers_as_string;
# show response including header
# print $res->as_string;
By setting SSL_hostname to an empty string you can disable SNI, disabling this line enables SNI again.
The approach of using a special default web application simply would not work.
You can't do that because said limited clients not just open a different page, but they fail completely.
Consider you have a "default" vhost which a non-SNI client will open just fine.
You also have an additional vhost which is supposed to be open by an SNI-supporting client.
Obviously, these two must have different hostnames (say, default.example.com and www.example.com), else Apache or nginx wouldn't know which site to show to which connecting client.
Now, if a non-SNI client tries to open https://www.example.com, he'll be presented a certificate from default.example.com, which would give him a certificate error. This is a major caveat.
A fix for this error is to make a SAN (multi-domain) certificate that would include both www.example.com and default.example.com. Then, if a non-SNI client tries to open https://www.example.com, he'll be presented with a valid certificate, but even then his Host: header would still point to www.example.com, and his request will get routed not to default.example.com but to www.example.com.
As you can see, you either block non-SNI clients completely or forward them to an expected vhost. There's no sensible option for a default web application.
With a Java HTTP client you can disable the SNI extension by setting the system property jsse.enableSNIExtension=false.
More here: Java TLS: Disable SNI on client handshake

Boost Asio SSL Client Handshake Problems

I have been trying to implement a very basic Boost SSL implementation to try and learn the basics. The server I want to communicate with had already given me their public key in plain text. I already put a lot of the other code (asynchronous connection, handshaking, etc) in.
I first tried to implement SSL without verification of their certificate using the following setup of the Boost SSL stream:
boost::asio::ssl::context ctxt(boost::asio::ssl::context::sslv23);
ctxt.set_verify_mode(boost::asio::ssl::verify_none);
This implementation worked fine and I was able to connect with the server. When I tried to implement the verification of the peer certificate, however, the handshaking fails. I tried using the following code:
boost::asio::ssl::context ctxt(boost::asio::ssl::context::sslv23);
ctxt.set_verify_mode(boost::asio::ssl::verify_peer);
ctxt.load_verify_file("peer.crt");
I put the "peer.crt" containing the public key (along with the -----BEGIN CERTIFICATE----- and -----END CERTIFICATE----- tags) in the directory where I am running my executable. For whatever reason the handshake now fails with the error code 336134278: certificate verify failed. I also tried putting the full path to the verify file in there but with no luck.
My questions are the following:
Where should I be specifying the file name for the verify file in load_verify_file? Is it simply in the directory where I am running my executable?
Am I not setting up the handshaking process with peer verification properly? I do not have my own verify callback as I assumed the peer verification would happen automatically if I specified it as such.
Should I be handling the certificate in a certain way by installing it or something like that?
Is there a better way of debugging this functionality? I am using VS10 and can only get to the ipp so I cannot actually view the verification taking place.
Any help is appreciated, thanks!
You should be able to use either a relative or absolute path.
Your use of set_verify_mode() and load_verify_file() looks fine. I have done exactly this in my own code. A default verify callback is used if you do not specify one.
You don't need to "install" the certificate.
I don't know of easy ways to debug boost::asio SSL connections, but you can use OpenSSL command line tools, such as s_client, to test connections. boost::asio uses OpenSSL under the hood.
I suspect that you don't have the entire certificate chain of certificates in your file. You can extract them from your server with (replace www.google.com:443 with your server and port):
openssl s_client -connect www.google.com:443 -showcerts
If you only wish to check some of the certificates, e.g. only the leaf certificate, you can use your own verify callback. An example of a custom callback, as well as a description of the verification modes and options are on this page.
A good place to start is the HTTP Client in asio examples.
Are you calling set_verify_callback on the socket with the callback function to verify the certificate? E.g.:
bool verify_certificate(bool preverified, boost::asio::ssl::verify_context& ctx)
{
char subject_name[256];
X509* cert = X509_STORE_CTX_get_current_cert(ctx.native_handle());
X509_NAME_oneline(X509_get_subject_name(cert), subject_name, 256);
return preverified;
}

Self-hosting using SSL and WCF - can't bind certificate to port

I have a WCF service that I want to access using SSL. I'm on my developer machine, so I was thinking of self-hosting the service. I've been following Configuring HTTP and HTTPS.
I've created a self-signed certificate which I added to the Trusted Root Certification Authorities. I've created another two certificates signed by the first one, one for the client and the other for the server. I followed Using makecert to create certificates for development.
I can't get past the SSL certificates configuration step. When I'm binding the certificate to the port number using netsh it throws an SSL error:
Certificate add failed, Error: 1312 A specified logon session does not exist. It may already have been terminated.
Does the certificate need some special field or some other thing for this to work?
CA certificate:
makecert -n "CN=TestCA" -cy authority -a sha1 -sv "TestCA.pvk" -r "TEST_CA.cer"
Service certificate:
makecert -n "CN=rneapp.com" -ic "TEST_CA.cer" -iv "TestCA.pvk" -a sha1 -sky exchange -pe -sv "rneapp.com.pvk" "rneapp.com.cer"
Client certificate:
makecert -n "CN=rneClient" -ic "TEST_CA.cer" -iv "TestCA.pvk" -a sha1 -sky exchange -pe -sv "rneClient.pvk" "rneClient.cer"
I'm using this command to bind the certificate to the port:
netsh http add sslcert ipport=0.0.0.0:8465 certhash=a853f3b5b48b8a506bdc4212ba2726a3bfea2bb6 appid={2E53B9B0-17AE-4EBC-A1AE-43D53A6FD07D} clientcertnegotiation=enable
When I encountered the same issue, moving the certificate from Current User to Local Computer storage helped, so try checking your certificate storage.
Built-in help for netsh http add sslcert also mentions this with regard to certstorename option:
certstorename - Store name for the certificate. Defaults
to MY. Certificate must be stored in the
local machine context.
I also run into similar error code through different process of creating the self-signed certificate and find the source of my own problem. Using netsh, bind an SSL certificate to a port number is failing
Here is the article I follow to create the self-signed certificate and it is quite complete and thorough.
I have exactly the same issue on Windows 7 and Windows Server 2008 R2 but for me it is working the first time I bind the certificate with the port. However if I delete the binding (netsh.exe http delete sslcert ipport=0.0.0.0:9101) and bind again with the same certificate, it fails. If I try another port, it fails. If I create a brand new certificate then I can bind again. But again deleting/binding will fail.
I follow the same rules as this question:
Can't register a C# generated selfsigned SSL certificate with netsh (error 1312)
I also tried to install KB981506 http://support.microsoft.com/kb/981506 but it failed to install "The update is not applicable to your computer". Maybe I have it already.
I have a feeling something is not deleted in a right way when the binding is deleted. ProcessMonitor doesn't show any thing weird when I try to bind again.
This seems to be a known issue. Check out this Microsoft KB article.
You may also be setting up the certificates incorrectly. Check out this MSDN forum post for how another person was making a similar mistake and getting the 1312 error which was just distracting him from the real problem which was his certificate configuration.
I had a similar problem today, and this is how I fixed it. When I have watched certificates installed on my local computer/my in mmc.exe, I have seen that my certificate haven't icon with key.
So when I combine *.cer and *.pvk file to *.pfx with:
pvk2pfx -pvk "private_key.pvk" -spc "public.cert" -pfx "test.pfx"
And then import *.pfx file with mmc.exe.
Then the next commands will execute with no errors:
netsh http add sslcert...
netsh http delete sslcert...
I have posted this answer to similar Stack Overflow question, Can't register a C# generated selfsigned SSL certificate with netsh (error 1312).