Cloud-Automation / node-modbus

Modbus TCP Client/Server implementation for Node.JS
456 stars 169 forks source link

Using library with TLS instead of Net #277

Closed mschloapps closed 3 years ago

mschloapps commented 3 years ago

Is it possible to use the Node TLS module instead of the Net module to send modbus requests? I set up simple TLS client/server config using two computers and the client appears to connect to the server properly (according to the socket.authorized property), but when I add a modbus TCP server on the server side and make modbus requests from the client side, I keep getting an Offline error message saying 'no connection to modbus server'. The same modbus code works properly using only the Net module. Any thoughts?

stefanpoeter commented 3 years ago

Can you provider some example code. The way I see it is that the TLS Module use a different set of events to transport data.

For example: this module uses the close, connect and data events on a socket which are not provided on a TLS socket.

mschloapps commented 3 years ago

I suppose that that could be the issue.

Client (commented portion using Net at the beginning of the function works):

function getHolding() {

    /* const socket = new net.Socket();
    const options = {
        host: '10.10.10.156',
        port: '802'
    };    

    const client = new modbus.client.TCP(socket, 1);

    socket.on('connect', function() {
        client.readHoldingRegisters(0, 10)
            .then(function(resp) {
                let vals = resp.response._body.valuesAsArray;                
                console.log(vals);
                socket.end();
            }).catch(function(err) {                
                socket.end();
            })
    });
    socket.on('error', function(err) {        
        console.log(err);        
    }); 

    socket.connect(options); */

    const options = {
        port: 802,
        host: '10.10.10.156',
        ca: [fs.readFileSync('cert.pem')],
    };

    let socket = tls.connect(options, function() {
        console.log('client connected', socket.authorized ? 'authorized' : 'unauthorized');        
        if (socket.authorized) {
            const client = new modbus.client.TCP(socket, 1);            
            client.readHoldingRegisters(0, 10)
                .then(function(resp) {
                    let vals = resp.response._body.valuesAsArray;                
                    console.log(vals);
                    socket.end();
                }).catch(function(err) {   
                    console.log(err);
                    socket.end();
                })
        } else {
            socket.end();
        }
    });

    socket.on('error', function(err) {        
        console.log(err);
        socket.end();
    });

    socket.on('end', function() {
        console.log('ended');
    });
}

setInterval(function() {
    getHolding();
}, 2000);

Server (works with commented Net server), additionally the "New Connection" and holding registers are printed on the console when using TLS, so it's reaching that block of code under TLS:

const mbholding = Buffer.alloc(1000, 0xFF)
for (let i=0; i<10; i++) {
    mbholding.writeInt16BE(i, (0+i)*2);
}

const tls_options = {
    key: fs.readFileSync('key.pem'),
    cert: fs.readFileSync('cert.pem'),    
};

// const netserver = new net.Server();
const netserver = new tls.createServer(tls_options, function(socket) {
    console.log('server connected', socket.authorized ? 'authorized' : 'unauthorized');
});

let mbserver = new modbus.server.TCP(netserver, {
    holding: mbholding
});

mbserver.on('connection', function (client) {
    console.log('New Connection')    
    console.log(mbserver.holding);
});

netserver.listen(802);

Using TLS: modbus_tls

I'm not sure about the "unauthorized" in the server connection above, but matches what I saw in this gist: https://gist.github.com/anhldbk/3ea07d006c0fd411f19c0e362d4e0ec0

Using Net: modbus_net

stefanpoeter commented 3 years ago

Sorry for the late answer. I guess it is possible if you wrap TLS into the defined socket interface. I don't think that this will be added to this library.