I want to create simple HTTPS server in Actix-Web using this tutorial
When using self-singned TLS keys created by openssl like in tutorial, everything works fine at localhost.
But when I try to load real keys from, i.e ZeroSSL, browser can't open my service with ERR_SSL_VERSION_OR_CIPHER_MISMATCH for Chrome-based and SSL_ERROR_NO_CYPHER_OVERLAP for Mozilla.
async fn main() -> std::io::Result<()> {
let cert_key_file: PathBuf = PathBuf::from("zerossl/private.key");
let cert_file: PathBuf = PathBuf::from("zerossl/certificate.crt");
let cert_ca_file: PathBuf = PathBuf::from("zerossl/ca_bundle.crt");
// To be shorter I omitted creation of paths: path_to_certificate, path_to_ca, path_to_key
let mut local_address = format!("0.0.0.0:{}", SERVICE_PORT);
let mut builder = SslAcceptor::mozilla_intermediate(SslMethod::tls()).unwrap();
builder
.set_private_key_file(path_to_key, SslFiletype::PEM)
.unwrap();
builder.set_certificate_chain_file(path_to_ca).unwrap();
builder.set_certificate_file(path_to_certificate, SslFiletype::PEM).unwrap();
HttpServer::new(|| {
App::new()
//.route("/{filename:.*}", web::get().to(index))
.route("/hello", web::get().to(|| async { "Hello World!" }))
.service(greet)
})
.bind_openssl(local_address, builder)?
.run()
.await
}
What did I do wrong?
Upd. Added curl info
➜ release git:(master) curl -v https://zavijavasoft.com:8080
* Trying 37.140.197.152:8080...
* TCP_NODELAY set
* Connected to zavijavasoft.com (37.140.197.152) port 8080 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS alert, handshake failure (552):
* error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
* Closing connection 0
curl: (35) error:14094410:SSL routines:ssl3_read_bytes:sslv3 alert handshake failure
Related
I am coding a Node application which requires me to create a TLS client to connect to a remote host. I'm running into an issue where my TLS connection will work properly when the application is run outside of Docker, however when run inside it will send a 'close notify' message immediately before the first message from the TLS server is received.
My TS for a TLS client is as follows:
const socket = tls.connect(
{
host: host,
port: port,
cert: certificate
key: key
},
() => {
logger.info('client connected', socket.authorized ? 'authorized' : 'unauthorized');
// Business logic to notify the user we're connected
process.stdin.pipe(socket);
process.stdin.resume();
}
);
socket.on('data', (data: Buffer) => {
// Processing the data received from the server here
});
socket.on('error', () => {
// Business logic to notify the user the connection had an error. This is not called when the
// connection is closed
});
socket.on('close', hadError => {
// Business logic to notify the user the connection has been closed. hadError is false
// when this callback is called.
});
I added extra logging using the socket.enableTrace() function built into the socket class and other than things like gmt_unix_time, random_bytes, and session_id all values are identical between a bare metal and Docker application. Here are the logs I saw:
TLS 1: client _init handle? true
**I'm only using self-signed certs in the dev environment**
(node:1) Warning: Setting the NODE_TLS_REJECT_UNAUTHORIZED environment variable to '0' makes TLS connections and HTTPS requests insecure by disabling certificate verification.
(Use `node --trace-warnings ...` to show where the warning was created)
TLS 1: client initRead handle? true buffered? false
TLS 1: client _start handle? true connecting? false requestOCSP? false
Client sends handshake
Client receives handshake
Client receives ChangeCipherSpec
Client receives ApplicationData (continuing handshake)
Sent Record
Header:
Version = TLS 1.2 (0x303)
Content Type = ApplicationData (23)
Length = 281
Inner Content Type = Handshake (22)
CertificateVerify, Length=260
Signature Algorithm: rsa_pss_rsae_sha256 (0x0804)
Signature (len=256): <snip>
Sent Record
Header:
Version = TLS 1.2 (0x303)
Content Type = ApplicationData (23)
Length = 69
Inner Content Type = Handshake (22)
Finished, Length=48
verify_data (len=48): <snip>
TLS 1: client onhandshakedone
TLS 1: client _finishInit handle? true alpn false servername false
**Sees the self-signed cert, but I'm ignoring this in my dev environment**
TLS 1: client emit secureConnect. rejectUnauthorized: false, authorizationError: SELF_SIGNED_CERT_IN_CHAIN
Sent Record
Header:
Version = TLS 1.2 (0x303)
Content Type = ApplicationData (23)
Length = 521
Inner Content Type = ApplicationData (23)
** Here is where the client is sending the close notify**
Sent Record
Header:
Version = TLS 1.2 (0x303)
Content Type = ApplicationData (23)
Length = 19
Inner Content Type = Alert (21)
Level=warning(1), description=close notify(0)
Received Record
Header:
Version = TLS 1.2 (0x303)
Content Type = ApplicationData (23)
Length = 453
Inner Content Type = ApplicationData (23)
** Here is where the server is acking the close notify**
Received Record
Header:
Version = TLS 1.2 (0x303)
Content Type = ApplicationData (23)
Length = 19
Inner Content Type = Alert (21)
Level=warning(1), description=close notify(0)
My docker compose file is exposing and publishing the TLS port in use for this connection.
My development server runs Ubuntu 22.04 whereas official Node Docker images run a Debian environment, so I developed my own Dockerfile from scratch however that did not change the behavior. Another thing I noticed was that the version of openssl was different between bare-metal and Docker (v3 vs v1), however making a custom Dockerfile which uses openssl v3 did not change anything either.
I can establish a generic TCP connection using a similar pattern in my code in both a bare metal and Docker environment.
I am running docker container which contains REST API with tls enable, For which I am passing self signed .pem certificate and I am using reqwest crate to call the REST API. If tls is disable with container it works well. But when I run container with certificate, reqwest API call giving me error as mention below.Even after passing the same certificate from self-signed also giving me error.
error trying to connect: The certificate was not trusted."
reqwest = { version = "0.11.4", features = ["blocking", "json","native-tls"] }
async fn call_api<T: serde::Serialize>(
&self,
builder: ClientBuilder,
params: &T,
request_url: &str,
) -> Result<serde_json::Value> {
let mut headers = header::HeaderMap::new();
headers.insert(
header::AUTHORIZATION,
header::HeaderValue::from_str(self.token.as_str()).unwrap(),
);
headers.insert(
header::CONTENT_TYPE,
header::HeaderValue::from_static("application/json"),
);
// read a local binary pem encoded certificate
let pem = std::fs::read("./cert.pem").unwrap();
let cert = reqwest::Certificate::from_pem(&pem)?;
let client = builder
.add_root_certificate(cert)
.default_headers(headers)
.build()?;
let response_json: serde_json::Value = client
.get(request_url)
.json(params)
.send()
.await?
.json()
.await?;
Ok(response_json)
}
Below is the code from server file. Trying to get the remoteAdress as host name. but it is giving Remote Address received: :ffff :10.197.0.145 instead of hostname.
async function serverImpl(stream) {
const ctx = {
id: crypto.createHash("sha256").update(stream.getSession())
.digest("hex"), // deriving a unique client id from the tls session identifier
remoteAddress: stream.remoteAddress,
remotePort: stream.remotePort,
servername: stream.servername
}
}
We are using TLS handshake for the Security. Expecting hostname from TCP or using TLS mandatorily. Help us on this
I'm trying to store MQTT payloads in a MongoDB database using NodeJS.
When I run my code I get the following error popped up at the Mosquitto server:
1427756032: Socket error on client <unknown>, disconnecting.
1427756033: New connection from 146.175.138.141 on port 8883.
1427756033: OpenSSL Error: error:1408F10B:SSL routines:SSL3_GET_RECORD:wrong version number
I'm not the only one facing this error but the proposed solutions on google won't work for me.
I'm working in a Ubuntu14.04 TLS (trusty) server environment. The version of OpenSSL which I used to make my own keys and certificates is:
OpenSSL 1.0.1f 6 Jan 2014
For making these keys I followed the manual of Mosquitto.
The version of nodejs is:
v0.10.25
The configuration file of mosquitto:
port 8883
cafile /etc/keys/ca.crt
certfile /etc/keys/server.crt
keyfile /etc/keys/server.key
tls_version tlsv1
require_certificate true
The nodejs file:
var mqtt=require('mqtt')
var mongodbClient=require('mongodb').MongoClient;
var deviceRoot="demo/device/"
var mqtthost = '146.175.138.141';
var KEY = '/etc/keys/client.key';
var CERT = '/etc/keys/client.crt';
var CAfile = '/etc/keys/ca.crt';
var options = {
host: mqtthost,
port: 8883,
protocolId: 'MQIsdp',
ca: CAfile,
keyPath: KEY,
certPath: CERT,
secureProtocol: 'TLSv1_method',
protocolId: 'MQIsdp',
protocolVersion: 3
};
var collection,client;
mongodbClient.connect("mongodb://localhost:27017/exampleDb", function(err,db){
if(err){return console.dir(err);}
collection=db.collection("test_mqtt");
client=mqtt.connect(options);
client.subscribe("#");
client.publish(deviceRoot, '21');
client.on('message', function(topic,payload){
str = payload.toString();
console.log(str);
var key=topic.replace(deviceRoot,'');
collection.update(
{ _id:key },
{ $push: { events: { event: { value:str, when:new Date() } } } },
{ upsert:true }
)})})
The keys should be working because publishing with the following command is not a problem:
mosquitto_pub -h 146.175.138.141 -p 8883 -t Server -m helloworld --cafile /etc/keys/ca.crt --cert /etc/keys/client.crt --key /etc/keys/client.key --tls-version tlsv1
Any idea what I'm doing wrong?
I can't say for sure, but I suspect that your nodejs connection isn't using TLS. You could verify this by connecting with mosquitto_pub without passing --cafile:
mosquitto_pub -h 146.175.138.141 -p 8883 -t Server -m helloworld
That should produce the same error on the broker that you see with your nodejs connection.
The next step is to remove the tls_version tlsv1 line from your mosquitto configuration and repeat the above command. In that case I would expect to get the following error message on the broker:
Client connection from ::1 failed: error:140760FC:SSL routines:SSL23_GET_CLIENT_HELLO:unknown protocol.
If you now repeat the test with your nodejs client and get the same error message, it is a fair bet that what I'm saying is correct. I'm afraid I don't know how to fix it though!
An easier test would be to leave your nodejs code unchanged, but set mosquitto to listen without using TLS. If node connects fine then it confirms the situation.
On a related note, if you are using mosquitto 1.4, the best option is to not force a particular version of TLS because the default behaviour is to allow TLS v1.0, v1.1 and v1.2. Earlier versions only provided a single version of TLS per listener.
Using "fs" guarantees access to the files
var fs = require('fs');
var mongodbClient=require('mongodb').MongoClient;
var deviceRoot="demo/device/"
var mqtthost = '146.175.138.141';
var KEY = fs.readFileSync('/etc/keys/client.key');
var CERT = fs.readFileSync('/etc/keys/client.crt');
var CAfile = [fs.readFileSync('/etc/keys/ca.crt')];
var options = {
host: mqtthost,
port: 8883,
protocol: 'mqtts', //also add this
protocolId: 'MQIsdp',
ca: CAfile,
key: KEY,
cert: CERT,
secureProtocol: 'TLSv1_method',
protocolId: 'MQIsdp',
protocolVersion: 3
};
I'm a node-js guy but I think this is about Certificate/CA only.
I want to set up an https server using a certificate which is signed by a public CA, so that all the browsers can visit my website without certificate error. At the same time, I want my server to provide two-way https authentication, so that the server can recognize my clients if my clients is using a certificate. Client certificate is signed by CA created by myself.
When I let the client connect to the server, it gets an error called Error: CERT_UNTRUSTED. But I have set up the "ca" & "agent" option for both the server and the client, so I can't figure out my mistake.
I have installed my self-signed CA in my windows 8 Root Certificates, altough I don't think it's really needed.
My Code:
Server
var options = {
key:keyForCertificate,
cert:certFromPublicCA,
ca:[PublicCA, self-signedCA],
requestCert: true,
rejectUnauthorized: false
};
var server = require('https').Server(options, require('express')());
server.listen(443);
Client
require('https').request({ host: "www.publicWebsite.com"
, method: "GET"
, port: 443
, headers: { host: "www.publicWebsite.com" }
, ca:[PublicCA, self-signedCA],
, path: "/" }, function (res) {
if (res.client.authorized) {
console.log("node test: OK")
} else {
throw new Error(res.client.authorizationError)
}
}).end()