TLS not working for dockerized MQTT broker
rauleteee opened this issue · 0 comments
Issue Summary:
I have a Dockerized MQTT broker server where I want to add TLS connections using certificates from a private CA (root-ca.cer has signed server.cer as a trust chain ). I have configured the server and client code with certificates, and the server configuration seems correct. However, I'm encountering an error during the TLS handshake when the client tries to connect to the MQTT broker. It is important to say that the broker accepts connections when running the server C# program and client C# program locally, the problem comes when dockerizing it.
Server Code (Publisher):
var certificate = new X509Certificate2(Constants.PATH_SERVER_CERT, Constants.CERT_PASSWORD);
var certificateCA = new X509Certificate2(Constants.PATH_CA_CERT, Constants.CERT_PASSWORD);
MqttClient client = new MqttClient(BrokerAddress, 8883, true,
certificateCA,
certificate,
MqttSslProtocols.TLSv1_2, RemoteCertificateValidationCallback);
client.Connect(Guid.NewGuid().ToString());
client.Publish(topic, Encoding.UTF8.GetBytes(message), MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE, false);
Client Code (Subscriber):
// Cargar el certificado PFX
var certificate = new X509Certificate2(Constants.PATH_CLIENT_CERT, Constants.CERT_PASSWORD);
var certificateCA = new X509Certificate2(Constants.PATH_CA_CERT, Constants.CERT_PASSWORD);
// Crear cliente MQTT con soporte TLS
MqttClient client = new MqttClient(BrokerAddress, 8883, true,
certificateCA,
certificate,
MqttSslProtocols.TLSv1_2, RemoteCertificateValidationCallback);
Console.WriteLine($"INFO: BROKER ADDRESS: {BrokerAddress}");
client.MqttMsgPublishReceived += (sender, e) =>
{
//...
};
client.Connect(Guid.NewGuid().ToString());
client.Subscribe(new string[] { topic }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
Console.WriteLine($"{Colors.YELLOW}{Colors.BOLD}[info]{Colors.RESET} Subscribed to topic {Colors.BOLD}[{topic}]{Colors.RESET}");
}
catch (MqttClientException ex)
{
Console.WriteLine($"{Colors.RED}{Colors.BOLD}[MQTT Connection Exception]{Colors.RESET} {ex}");
// Manejo específico para errores de conexión MQTT
}
catch (SocketException ex)
{
Console.WriteLine($"{Colors.RED}{Colors.BOLD}[Socket Exception]{Colors.RESET} {ex}");
// Manejo específico para errores de Socket
}
catch (Exception ex)
{
Console.WriteLine($"{Colors.RED}{Colors.BOLD}[General Exception]{Colors.RESET} {ex}");
// Manejo para cualquier otro tipo de error no capturado específicamente
}
}
RemoteCertificateValidationCallback returns always true. It works in local mode, not in dockerized mode.
Mosquitto Configuration (mosquitto.conf):
persistence true
persistence_location /mosquitto/data/
log_dest file /mosquitto/log/mosquitto.log
# TLS
certfile /mosquitto/certs/server.crt
keyfile /mosquitto/certs/server.key
listener 8883 0.0.0.0
## Authentication ##
# By default, Mosquitto >=2.0 allows only authenticated connections. Change to true to enable anonymous connections.
require_certificate true
allow_anonymous true
log_type all
connection_messages true
# password_file /mosquitto/config/password.txt
Server's Docker compose:
version: '3.8'
services:
mosquitto:
image: eclipse-mosquitto:1.6
container_name: mosquitto
environment:
- TZ=Europe/Madrid
volumes:
- ./mosquitto/config:/mosquitto/config
- ./mosquitto/data:/mosquitto/data
- ./mosquitto/log:/mosquitto/log
- ./mosquitto/certs:/mosquitto/certs
ports:
- "8883:8883"
networks:
- mls_network
restart: unless-stopped
mls_server:
build:
context: .
dockerfile: Dockerfile
container_name: mls_server
environment:
- BROKER_IP_ADDRESS=mosquitto
ports:
- "10003:10003"
depends_on:
- mosquitto
networks:
- mls_network
volumes:
- ./mls-server/keys:/mls-server/mls-server/keys
- ./mls-server/data:/mls-server/mls-server/data
restart: on-failure
networks:
mls_network:
driver: bridge
external: true
Client's Docker compose:
version: '3.8'
services:
mls_client:
build:
context: .
dockerfile: Dockerfile
container_name: mls_client
environment:
BROKER_IP_ADDRESS: ${BROKER_IP_ADDRESS}
SERVER_IP: ${SERVER_IP}
N: ${N}
ALGORITHM: ${ALGORITHM}
TZ: Europe/Madrid
env_file:
- .env
ports:
- "10003"
- "8883"
networks:
- mls_network
volumes:
- ./mls-client/keys:/mls-client/keys
- ./mls-client/data:/mls-client/data
- ./mls-client/scripts:/mls-client/scripts
restart: on-failure
networks:
mls_network:
driver: bridge
external: true
Mosquitto log:
I have tried to see if there are uploaded certs as follows:
sudo docker exec -it 4a91e96b0825 ls /mosquitto/certs
server.crt server.key
As you can see, they are in the correct place, but mosquitto cannot use them.
1703761378: mosquitto version 1.6.15 starting
1703761378: Config loaded from /mosquitto/config/mosquitto.conf.
1703761378: Opening ipv4 listen socket on port 8883.
1703761378: mosquitto version 1.6.15 running
1703761558: mosquitto version 1.6.15 terminating
1703761558: Saving in-memory database to /mosquitto/data/mosquitto.db.
1703761821: mosquitto version 1.6.15 starting
1703761821: Config loaded from /mosquitto/config/mosquitto.conf.
1703761821: Opening ipv4 listen socket on port 8883.
1703761821: mosquitto version 1.6.15 running
1703761959: New connection from 172.22.0.4 on port 8883.
1703761959: Client <unknown> disconnected due to protocol error.
1703761959: New connection from 172.22.0.4 on port 8883.
1703761959: Client <unknown> disconnected due to protocol error.
Error Message:
[Exception] Exception in MQTT: uPLibrary.Networking.M2Mqtt.Exceptions.MqttConnectionException: Exception connecting to the broker
...
mls_client | [General Exception] uPLibrary.Networking.M2Mqtt.Exceptions.MqttConnectionException: Exception connecting to the broker
mls_client | ---> System.IO.IOException: Unable to read data from the transport connection: Connection reset by peer.
mls_client | ---> System.Net.Sockets.SocketException (104): Connection reset by peer
mls_client | at System.Net.Sockets.NetworkStream.Read(Span`1 buffer)
mls_client | --- End of inner exception stack trace ---
mls_client | at System.Net.Sockets.NetworkStream.Read(Span`1 buffer)
mls_client | at System.Net.Security.SyncReadWriteAdapter.ReadAsync(Stream stream, Memory`1 buffer, CancellationToken cancellationToken)
mls_client | at System.Net.Security.SslStream.EnsureFullTlsFrameAsync[TIOAdapter](CancellationToken cancellationToken, Int32 estimatedSize)
mls_client | at System.Runtime.CompilerServices.PoolingAsyncValueTaskMethodBuilder`1.StateMachineBox`1.System.Threading.Tasks.Sources.IValueTaskSource<TResult>.GetResult(Int16 token)
mls_client | at System.Net.Security.SslStream.ReceiveHandshakeFrameAsync[TIOAdapter](CancellationToken cancellationToken)
mls_client | at System.Net.Security.SslStream.ForceAuthenticationAsync[TIOAdapter](Boolean receiveFirst, Byte[] reAuthenticationData, CancellationToken cancellationToken)
mls_client | at System.Net.Security.SslStream.AuthenticateAsClient(SslClientAuthenticationOptions sslClientAuthenticationOptions)
mls_client | at uPLibrary.Networking.M2Mqtt.MqttNetworkChannel.Connect()
mls_client | at uPLibrary.Networking.M2Mqtt.MqttClient.Connect(String clientId, String username, String password, Boolean willRetain, Byte willQosLevel, Boolean willFlag, String willTopic, String willMessage, Boolean cleanSession, UInt16 keepAlivePeriod)
mls_client | --- End of inner exception stack trace ---
mls_client | at uPLibrary.Networking.M2Mqtt.MqttClient.Connect(String clientId, String username, String password, Boolean willRetain, Byte willQosLevel, Boolean willFlag, String willTopic, String willMessage, Boolean cleanSession, UInt16 keepAlivePeriod)
mls_client | at uPLibrary.Networking.M2Mqtt.MqttClient.Connect(String clientId)
mls_client | at Idbotic.MlsClient.Utilities.Mqtt.SubscribeToMqttTopic(String topic) in /mls-client/src/Mqtt.cs:line 60
...
The server certificates (server.crt
, server.key
) have been successfully copied to the Mosquitto container's path, and their existence has been confirmed.
I appreciate any guidance or suggestions to troubleshoot and resolve this problem.