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
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'm implementing https server in nodejs which should be accessible as from local IP address as from public IP address over SSL. With help of documentation (and some answers here on SO) I found how I can dynamically provide different Certificate for different hostnames (using SNICallback) but as documentation points that SNICallback works only with hostnames and not with IPs:
Currently, the only server names supported are DNS hostnames Literal
IPv4 and IPv6 addresses are not permitted in "HostName"
Here is some code how the server is created:
var certs = {
'intern': {
key: fs.readFileSync(keyName, 'utf8'),
cert: fs.readFileSync(certName, 'utf8')
},
'extern': {
key: fs.readFileSync(keyNameExternal, 'utf8'),
cert: fs.readFileSync(certNameExternal, 'utf8')
}
}
var httpsOpts = {
SNICallback: function (hostname, cb) {
if (hostname === 'mydomain.com') {
var ctx = tls.createSecureContext(certs['extern'])
cb(null, ctx)
}
},
key: fs.readFileSync(keyName, 'utf8'),
cert: fs.readFileSync(certName, 'utf8')
}
httpsServer = https.createServer(httpsOpts, httpsApp)
httpsServer.listen(443, '0.0.0.0', onlisteningHttps)
Is there a possibility to provide certs['intern'] certificate when server is accessed by local IP '192.168.1.100'
and provide certs['extern'] certificate when server accessed by public IP (not a hostname)?
It is only possible if your server has two separate interface for internal and external network.
The second parameter to httpsServer.listen is actually the bind interface. So for example, assume that you have an "internal" interface at 192.168.1.100, you can do this:
httpsServerInt = https.createServer(certs.intern, httpsApp)
httpsServerExt = https.createServer(certs.extern, httpsApp)
httpsServerInt.listen(443, '192.168.1.100', onlisteningHttps)
httpsServerExt.listen(443, '0.0.0.0', onlisteningHttps)
If the server does not have separate interface, you can look into "linux virtual interface" (or windows if that is the case)
I'm using https://github.com/farhadi/node-smpp in order to create a smpp server.
I'm going to forbid connection if the client's IP address is not in the allowed ips list. For that when a new connection is open I have to check if the credentials are ok and if the IP address is a good one.
The question is how and where can I get the client (ESME's) IP address?
session.on('bind_transceiver', function(pdu) {
session.pause();
const username = pdu.system_id;
const password = pdu.password;
const ipAddress = ''; // WHERE TO GET IT??
if (credentialsAreOk(username, password, ipAddress)) {
session.send(pdu.response());
session.resume();
} else {
session.close();
}
});
When an ESME is connecting to your server, a session is created.
The network socket used by this TCP connection, which is a net.Socket class (https://nodejs.org/api/net.html#net_class_net_socket), is stored inside this session in the socket property.
const socket = session.socket;
So you can easily access this socket property of the session and get the remoteAddress (the clients IP) from there (https://nodejs.org/api/net.html#net_socket_remoteaddress).
const ipAddress = session.socket.remoteAddress;
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()