MQTT TLS with VPS: Mosquitto TLS error (SAN settings?) [duplicate] - ssl

I have provided the broker and the client with certificates. The broker is avaible at 172.27.224.1.
When I try to connect with the client, I get following error message:
Error [ERR_TLS_CERT_ALTNAME_INVALID]: Hostname/IP does not match certificate's altnames: IP: 172.27.224.1 is not in the cert's list:
at new NodeError (node:internal/errors:371:5)
at Object.checkServerIdentity (node:tls:297:12)
at TLSSocket.onConnectSecure (node:_tls_wrap:1540:27)
at TLSSocket.emit (node:events:390:28)
at TLSSocket._finishInit (node:_tls_wrap:944:8)
at TLSWrap.ssl.onhandshakedone (node:_tls_wrap:725:12) {
reason: "IP: 172.27.224.1 is not in the cert's list: ",
host: '172.27.224.1',
cert: {
subject: [Object: null prototype] {
C: 'AU',
ST: 'Some-State',
O: '',
OU: '',
CN: '172.27.224.1'
},
issuer: [Object: null prototype] {
C: 'DE',
ST: 'Some-State',
O: '',
OU: '',
CN: '172.27.224.1'
},
[...]
What's the error here? The ca.crt is a self signed cert with issued for 172.27.224.1 and issued from 172.27.224.1. The client.crt is issed from 172.27.224.1 and issued for "username".
should't this work?
Steps I used to generate the certificate:
openssl genrsa -des3 -out ca.key 2048
openssl req -new -x509 -days 1826 -key ca.key -out ca.crt
openssl genrsa -out client.key 2048
openssl req -new -out client.csr -key client.key
openssl x509 -req -in client.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out client.crt -days 360
I use for the client node.js v16.13 and the mqtt library.

Assuming you are using OpenSSL to create the CA cert then you can do it as follows:
openssl req -x509 -nodes -newkey rsa:2048 -days 3650 -sha256 \
-keyout ca.key -out ca.crt -reqexts SAN -extensions SAN \
-subj '/CN=Broker Cert' \
-config <(cat /etc/pki/tls/openssl.cnf; printf "[SAN]\nsubjectAltName=IP:172.27.224.1")
This makes an assumption that you are using a openss.cnf file stored at /etc/pki/tls/openssl.cnf
But as a rule it's better to create a CA cert and then sign server certs with that as it makes changing things easier and you don't need to update all the clients when you want to change something. It also makes issuing client certificates a lot easier.
Please do still update the question with details of the programming language and client library you are using that is now enforcing the SAN rules.

Related

MQTT mosquitto - set up client for intermediate CA

I have created CA, intermediate CA and certificates signed by intermediate CA by these commands:
CA:
openssl req -new -newkey rsa:4096 -days 365 -extensions v3_ca -subj "/C=CZ/ST=aa/L=bb/O=company/OU=development/CN=ca/" -nodes -x509 -sha256 -set_serial 0 -keyout ca.key -out ca.crt
Intermediate CA:
openssl genrsa -out subca.key 4096
openssl req -new -key subca.key -out subca.csr
openssl x509 -req -days 365 -in subca.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out subca.crt -extfile openssl.cfg -extensions v3_ca
Server:
openssl req -newkey rsa:4096 -nodes -keyout server.key -subj "/C=CZ/ST=aa/L=bb/O=company/OU=development/CN=server/" -out server.csr
openssl x509 -req -extfile <(printf "subjectAltName=IP:177.18.0.1") -days 365 -in server.csr -CA subca.crt -CAkey subca.key -CAcreateserial -out server.crt
Client:
openssl genrsa -des3 -out client.key 4096
openssl req -new -key client.key -subj "/C=CZ/ST=aa/L=bb/O=company/OU=development/CN=client/" -out client.csr
openssl x509 -req -in client.csr -CA subca.crt -CAkey subca.key -CAcreateserial -out client.crt -days 365
When I verify server or client certificate, everything seems good.
Verify command I use:
openssl verify -verbose -CAfile <(cat subca.crt ca.crt) server.crt
I want to connect to the mosquitto with TLS/SSl support with these certificates.
Mosquitto configuration:
listener 1883
require_certificate false
allow_anonymous true
listener 8883
capath /mosquitto/config/certs/ca/
certfile /mosquitto/config/certs/server.crt
keyfile /mosquitto/config/certs/server.key
require_certificate true
allow_anonymous true
use_identity_as_username true
But when I want to connect with my client, I do not know how to set function tls_set() for intermediate CA. Can you help me to setup this function ? When I look to the official documentation https://www.eclipse.org/paho/index.php?page=clients/python/docs/index.php#option-functions
for function tls_set(), there is sentence that says:
"ca_certs = a string path to the Certificate Authority certificate files that are to be treated as trusted by this client."
But I don't know how to put more certificates there and I cannot use directory as argument.
Client code:
client = mqtt.Client(client_id='Monitoring Test',
clean_session=None,
userdata=None,
protocol=mqtt.MQTTv5,
transport='tcp')
client.on_message = on_message
client.tls_set(ca_certs="ca-chain.pem",
certfile="client.pem",
keyfile="client.key",
tls_version=ssl.PROTOCOL_TLSv1_2)
client.connect("177.18.0.1", port=8883, keepalive=60)
client.subscribe("topic", qos=2)
client.loop_forever(timeout=60)
I know how to do it for root CA and signed certificate by this CA.
You need to create a single file that contains all the CA certificates, much in the same way you used cat subca.crt ca.crt to pass in a "single" file to the openssl verify command.
So cat subca.crt ca.crt > ca-chain.crt (order is important)
And then pass the path to that file in the client.
p.s. You probably want per_listener_settings true if you are going to require different authentication options per listener and require_certificate false on the first listener is not doing anything in much the same way that allow_anonymous true for the second listener doesn't do anything useful if you are requiring a client certificate.
hardillb suggested me to use for client:
cat subca.crt ca.crt > ca-chain.crt (order is important)
When I used it only for client it still did not work, but as soon as I also used file ca-chain.crt for server, it works.
So change line capath /mosquitto/config/certs/ca/ in mosquitto configuration and use cafile /mosquitto/config/test/ca-chain.pem instead.

gRPC SSL No subject alternative names present

How can disable the hostnameverfifier in gRPC to avoid exception below?
java.security.cert.CertificateException: No subject alternative names present
The recommended way to use test certificates where the hostname doesn't match is to call ManagedChannelBuilder.overrideAuthority("test-hostname"). This is functionally similar to adding test-hostname to /etc/hosts. This allows you to choose different IPs/DNS names with forAddress()/forTarget() without disabling security.
But it still seems like your certificate is a bit broken. Subject Alternative Name is required; using the certificate's Subject had been deprecated for a decades.
You may also be interested in using gRPC's test certificates. We provide TlsTesting to load them.
server = ServerBuilder.forPort(0)
// Use test cert on server-side
.useTransportSecurity(
TlsTesting.loadCert("server1.pem"),
TlsTesting.loadCert("server1.key"))
// ...
.build().start();
channel = NettyChannelBuilder
.forAddress("localhost", server.getPort())
// Trust test CA on client-side
.sslContext(
GrpcSslContexts.forClient()
.trustManager(TlsTesting.loadCert("ca.pem"))
.build())
// Change hostname to match certificate
.overrideAuthority("foo.test.google.fr")
.build();
Just to elaborate on #Eric Anderson answer. In the gRPC's test certificates he points to there are 2 types *.cnf files used to generate the client and server certs
1.Generate client cert: openssl.cnf
2.Generate server cert: server1-openssl.cnf
at the very bottom of both files you will find the hostnames where you need to add the matching entries for the client and server
for example if you are local testing for client and server resolving on "localhost" then you would need for both openssl.cnf and server1-openssl.cnf to have
[alt_names]
DNS.1 = localhost
after this you would need to regenerate the certificates
here is a simple script based on the grpc-java info here
#!/bin/bash
SERVER_CN=localhost
CLIENT_CN=localhost # Used when doing mutual TLS
TLS_KEY_PSSWD=somepsswd
echo "When prompted for cert information, everything is default except the common name which is set to localhost"
echo Generate CA key:
openssl genrsa -passout pass:TLS_KEY_PSSWD -des3 -out ca.key 4096
echo Generate CA:
openssl req -passin pass:TLS_KEY_PSSWD -x509 -new -nodes -key ca.key -out ca.pem -config conf/ca-openssl.cnf -days 3650 -extensions v3_req -subj "/CN=${SERVER_CN}"
echo "Now that we’re a CA on all our devices, we can sign certificates for any new dev sites that need HTTPS"
echo Generate client key:
openssl genrsa -out client.key.rsa 1024
openssl pkcs8 -topk8 -in client.key.rsa -out client.key -nocrypt
rm client.key.rsa
echo Generate client signing request:
openssl req -passin pass:TLS_KEY_PSSWD -new -key client.key -out client.csr -subj "/CN=${CLIENT_CN}"
echo Generate client cert:
openssl ca -passin pass:TLS_KEY_PSSWD -in client.csr -out client.pem -keyfile ca.key -cert ca.pem -verbose -config conf/openssl.cnf -days 3650 -updatedb
openssl x509 -in client.pem -out client.pem -outform PEM
echo Generate server key:
openssl genrsa -passout pass:TLS_KEY_PSSWD -out server1.key.rsa 1024
openssl pkcs8 -topk8 -in server1.key.rsa -out server1.key -nocrypt
rm server1.key.rsa
echo Generate server signing request:
openssl req -passin pass:TLS_KEY_PSSWD -new -key server1.key -out server1.csr -config conf/server1-openssl.cnf -subj "/CN=${CLIENT_CN}"
echo Generate server cert:
openssl ca -passin pass:TLS_KEY_PSSWD -in server1.csr -out server1.pem -keyfile ca.key -cert ca.pem -verbose -config conf/server1-openssl.cnf -days 3650 -extensions v3_req -updatedb
openssl x509 -in server1.pem -out server1.pem -outform PEM

docker swarm certificate expiry

I am trying to create a docker swarm that has certificates that expire after 1 year or more. The documentation states the syntax and I tried this docker swarm init --cert-expiry 8760h0m0s
However under cat /var/lib/docker/swarm/certificates/swarm-node.crt when I decipher the certificate the validity is still 3 months. How do I make sure that validity is what I have set it to?
You can generate certificates manually using the OpenSSL tool and configure Docker daemon to use these certificates.
Generate Server Certificates
Generate CA private and public keys:
openssl genrsa -aes256 -out ca-key.pem 4096
openssl req -new -x509 -days 1000 -key ca-key.pem -sha256 -out ca.pem
Create a server key and certificate signing request (CSR):
openssl genrsa -out server-key.pem 4096
openssl req -subj "/CN=my.company.com" -sha256 -new -key server-key.pem -out server.csr
Sign the public key with CA:
echo subjectAltName = DNS:my.company.com,IP:127.0.0.1 >> extfile.cnf
echo extendedKeyUsage = serverAuth >> extfile.cnf
Generate the key:
openssl x509 -req -days 1000 -sha256 -in server.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out server-cert.pem -extfile extfile.cnf
Generate Client Certificates
Create a client key and certificate signing request:
openssl genrsa -out key.pem 4096
openssl req -subj '/CN=client' -new -key key.pem -out client.csr
Create an extensions config file:
echo extendedKeyUsage = clientAuth >> extfile.cnf
Sign the private key:
openssl x509 -req -days 1000 -sha256 -in client.csr -CA ../server/ca.pem -CAkey ../server/ca-key.pem -CAcreateserial -out cert.pem -extfile extfile.cnf
Export cert.pem into PFX format to be added into Trusted Root Certification Authorities
openssl pkcs12 -export -in cert.pem -inkey key.pem -out cert.pfx
Configure Docker daemon with /etc/docker/daemon.json
{
"debug": false,
"tls": true,
"tlsverify": true,
"tlscacert": "/etc/docker/certificates/server/ca.pem",
"tlscert": "/etc/docker/certificates/server/server-cert.pem",
"tlskey": "/etc/docker/certificates/server/server-key.pem",
"hosts": ["tcp://0.0.0.0:2376", "unix:///var/run/docker.sock"]
}
Start Docker Service
systemctl start docker
Have a look at this article Building Jenkins Pipelines – Setting Up Docker Swarm. There's a step-by-step guide there.
Run the following commands on any of the management nodes:
docker swarm update --cert-expiry 8760h0m0s
docker swarm ca --rotate | openssl x509 -text -noout
The first one will set certificate expiry date.
The last one will actually apply changes and rotate certificates on all swarm nodes automatically. If not interested in decoding cert text output, the openssl part can be omitted.

Update SSL Certificate Issuer value

I have created key, pem and exported certificate with the following commands
openssl genrsa -out Kumar.key 2048
openssl req -x509 -new -nodes -key Kumar.key -sha256 -days 1024 -out Kumar.pem
openssl pkcs12 -export -name Kumar -in Kumar.pem -inkey Kumar.key -out Kumar.p12
When i installed certificate in machine personal store, it shows
Issue to Kumar and Issued by Kumar
I want to change Issued by value to localhost.
Should i change or use any other command to update the value of Issued by?
Thanks id advance.
To change Issued by to 'localhost', you will need to change this line
openssl req -x509 -new -nodes -key Kumar.key -sha256 -days 1024 -out Kumar.pem
by this command
openssl req -x509 -new -nodes -key Kumar.key -sha256 -days 1024 -out Kumar.pem -outform PEM -subj /CN=localhost
However, this command "openssl req" will create the root certificate, hence, Issued By value will always be the same as the Issued To value
You need to generate a self-signed certificate from this CA certificate in order to have Issued by = localhost and Issued to = Kumar
See this article on how to create a self signed certificate, especially the section "Create a Certificate"
# openssl ca -config intermediate/openssl.cnf \
-extensions server_cert -days 375 -notext -md sha256 \
-in intermediate/csr/www.example.com.csr.pem \
-out intermediate/certs/www.example.com.cert.pem
However, keep in mind that it doesn't make sense to have a CA name of 'localhost' as it doesn't define a specific entity but is rather generic.

How to add custom field to certificate using openssl

I'm trying to create certificates for internal use. I'm the CA and I would like to have an additional field in my client certificates so that when I generate a certificate for a client, it will hold some specific data in that field.
I read the following article and another article and I understand that I can do that with x509 v3 format by generating an oid for each field, and then use it with the -extfile parameter when creating the public key
so I took the deafult /etc/ssl/openssl.cnf config file and uncomment one of the mentioned fields:
[ new_oids ]
testoid1 = 1.2.3.4
Then I generate all the certificates by the following:
openssl genrsa -aes256 -out ca-key.pem 4096
openssl req -new -x509 -days 365 -key ca-key.pem -sha256 -out ca.pem -config openssl.cnf
openssl genrsa -out key.pem 4096
openssl req -subj '/CN=client' -new -key key.pem -out client.csr
openssl x509 -req -days 365 -sha256 -in client.csr -CA ca.pem -CAkey ca-key.pem -CAcreateserial -out cert.pem -extfile extfile.cnf
Where extfile.cnf content is:
1.2.3.4 = Something
I get:
Error Loading extension section default
140218200073872:error:22097082:X509 V3 routines:DO_EXT_NCONF:unknown extension name:v3_conf.c:125:
140218200073872:error:22098080:X509 V3 routines:X509V3_EXT_nconf:error in extension:v3_conf.c:95:name=1.2.3.4, value=Something
unable to write 'random state'
Documentation in this topic is lacking. Can someone walk me through it and explain how it can be done?
In order to add a custom field, first create a config file:
[req]
req_extensions = v3_req
[v3_req]
1.2.3.4.5.6.7.8=ASN1:UTF8String:Something
Then, create the CSR:
openssl req [params] -out mycsr.csr -config myconfig.cnf
Then, Create the certificate:
openssl x509 -req -sha256 -in mycsr.csr [params] -out mycert.pem -extfile myconfig.cnf -extensions v3_req