Repository navigation
UDP/Datagram: Can't send messages while bind is done to 127.0.0.1 must bind to 0.0.0.0 #29047
Description
Activity
I assume you think there is a bug, but I'm not sure what it is. Could you elaborate?
That bind is implicitly done on first send is documented:
If the socket has not been previously bound with a call to bind, the socket is assigned a random port number and is bound to the "all interfaces" address ('0.0.0.0' for udp4 sockets, '::0' for udp6 sockets.)
While the bind on first send (if not already bounded) is documented, in case the dgram module is used only as a UDP client (outgoing messages only), opening a local port to 0.0.0.0 seems like a security issue.
Trying to reduce it and bind to 127.0.0.1 is limiting the outgoing UDP messages only to localhost, and this seems like a bug.opening a local port to 0.0.0.0 seems like a security issue
That's how UDP sockets work in general, it's not specific to Node.js. From http://man7.org/linux/man-pages/man7/udp.7.html:
In order to receive packets, the socket can be bound to a local address first by using bind(2). Otherwise, the socket layer will automatically assign a free local port out of the range defined by /proc/sys/net/ipv4/ip_local_port_range and bind the socket to INADDR_ANY.Trying to reduce it and bind to 127.0.0.1 is limiting the outgoing UDP messages only to localhost, and this seems like a bug.
I don't follow that line of reasoning. You ask the operating system to restrict it to localhost and that's what it does.
Thanks for taking the time to open an issue but I'm closing this out as notabug.
- addeddgramIssues and PRs related to UDP and the dgram module.Issues and PRs related to UDP and the dgram module.invalidIssues and PRs that are invalid.Issues and PRs that are invalid.
on Aug 9, 2019 So in order to (only) send UDP packets to a remote machine, you have to open a random local port to listen to 0.0.0.0?
(for example with netcat this is not needed)netcat does the exact same thing. And actually it's not netcat doing that but the kernel.
Think about it: the UDP packet header requires a source address and port.
The source port on the UDP packet header is optional (see https://tools.ietf.org/html/rfc768):
"Source Port is an optional field, when meaningful, it indicates the port
of the sending process, and may be assumed to be the port to which a
reply should be addressed in the absence of any other information. If
not used, a value of zero is inserted."I also don't think that the kernel does this bind, looking in uv/src/unix/udp.c:
'uv__udp_send' function specifically calls 'uv__udp_maybe_deferred_bind'. I wonder if this is mandatory?I linked you to the relevant man page. That rather closes the discussion, don't you think?
Yes, libuv does an explicit bind. If it didn't, the kernel would do it implicitly on libuv's behalf.
I agree, it looks like the bind will happen anyway.
Not sure if there is a difference if it's done implicitly or explicitly.In any case, thank you for addressing this issue and the quick responses!
Reacted by Ben Noordhuis and Doodad/Doodead
When using dgram for only sending UDP messages, upon the first send there is an automatic bind to 0.0.0.0
Trying to explicitly bind to 127.0.0.1 will cause send to fail with the error message:
Error: send EINVAL 111.111.111.111:11111
at SendWrap.afterSend [as oncomplete] (dgram.js:467:11)
Reproduction:
let PORT = 11111;
let HOST = '111.111.111.111';
let dgram = require('dgram');
let message = Buffer.from('Testing!');
let client = dgram.createSocket('udp4');
client.bind(0, '127.0.0.1'); /////////////////// remove this line for auto bind or change to 0.0.0.0 to be able to send
client.send(message, 0, message.length, PORT, HOST, function(err, bytes) {
if (err) throw err;
console.log('UDP message sent to ' + HOST +':'+ PORT);
client.close();
});