How to open IPv4 and IPv6 sockets on the same port with http module in NodeJS?

Viewed 5358

I'm running the following NodeJS server code:

var express = require('express');
var path = require('path');
var fs = require('fs');
var bodyParser = require('body-parser');
var http = require('http');
var ejs = require('ejs');

var app = express();
//configure the app
app.set('port', process.env.PORT || 3000);
// set the view engine to ejs
app.set('view engine', 'ejs');
app.use(bodyParser.raw());
app.use(bodyParser.urlencoded({
    extended: true
}));

app.use(function(req, res, next) {
    res.set('Access-Control-Allow-Origin', 'https://myServer.com');
    res.set('Access-Control-Allow-Methods', 'GET, OPTIONS,POST, PUT, PATCH, DELETE');
    res.set('Access-Control-Allow-Headers', 'X-Requested-With,content-type');
    res.set('Access-Control-Allow-Credentials', true);
    next();
});

//assets
require(path.join(__dirname, './server.js')).Server(app);

When the server is parameterized using an IPv4 address:

var server = http.createServer(app);
//create server
server.listen(app.get('port'), "0.0.0.0", function() {
    var host = server.address().address;
    console.log('mockserver listening on host:' + host + ":" + app.get('port'));
});

Netstat gives the following output:

# netstat -plnt | grep node
tcp        0      0 0.0.0.0:3000            0.0.0.0:*               LISTEN      1234/node /local/op

In this case the TCP socket is created by using IPv4 address. The service can be reached by using an IPv4 address only.

When the server is parameterized using an IPv6 address:

var server = http.createServer(app);
//create server
server.listen(app.get('port'), "::",  function() {
    var host = server.address().address;
    console.log('mockserver listening on host:' + host + ":" + app.get('port'));
});

The netstat gives this output:

# netstat -plnt | grep node
tcp6       0      0 :::3000                 :::*                    LISTEN      1234/node /local/op

And the service can be reached by using both IPv4 and IPv6 addresses. (Probably a kernel option for emulating IPv4 is turned on)

Question: Is it possible to create separate (IPv4 and IPv6) sockets for a given port with NodeJS's express module?

I want a solution where the netstat's oputput is similar to this one:

# netstat -plnt | grep node
tcp        0      0 0.0.0.0:3000            0.0.0.0:*               LISTEN      1234/node /local/op
tcp6       0      0 :::3000                 :::*                    LISTEN      1234/node /local/op

Attempts: I've tried the following attempts, which are not working:

1st attempt: I've tried to open multiple sockets with one server, but the parametrization of the listen function probably differs from what I've imagined.

server.listen(app.get('port'), ["0.0.0.0", "::0"],  function() {
    console.log('EEA-mockserver server listening on host:' + app.get('port'));
});

or

server.listen(app.get('port'), "0.0.0.0", "::0",  function() {
    console.log('EEA-mockserver server listening on host:' + app.get('port'));
});

2nd attempt: I've tried to create multiple servers on the same port, but conflict happens when they want to initialize themselves over the same port.

var server4 = http.createServer(app);
var server6 = http.createServer(app);

server4.listen(app.get('port'), "0.0.0.0", function() {
    var host = server4.address().address;
    console.log('EEA-mockserver server listening on host:' + host + ":" + app.get('port'));
});

server6.listen(app.get('port'), "::",  function() {
    var host = server6.address().address;
    console.log('EEA-mockserver server listening on host:' + host + ":" + app.get('port'));
});
1 Answers

It is called dual stack mode and it is related to the platform configurations. Linux OS allows you to switch it on/off through the net.ipv6.bindv6only sysctl. I guess that Windows has something similar.

Related