镜像站点 · 本页由第三方 GitHub 只读镜像提供,非 GitHub 官方站点,不接受任何登录或凭据输入。前往 github.com
Skip to content

UDP/Datagram: Can't send messages while bind is done to 127.0.0.1 must bind to 0.0.0.0 #29047

Description

@assaf-xm

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();
});

Activity

  1. sam-github commented on Aug 8, 2019

    @sam-github
    Contributor

    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.)

  2. assaf-xm commented on Aug 8, 2019

    @assaf-xm
    Author

    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.

  3. bnoordhuis commented on Aug 9, 2019

    @bnoordhuis
    Member

    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.

  4. added
    dgramIssues and PRs related to UDP and the dgram module.
    invalidIssues and PRs that are invalid.
    on Aug 9, 2019
  5. assaf-xm commented on Aug 9, 2019

    @assaf-xm
    Author

    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)

  6. bnoordhuis commented on Aug 9, 2019

    @bnoordhuis
    Member

    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.

  7. assaf-xm commented on Aug 11, 2019

    @assaf-xm
    Author

    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?

  8. bnoordhuis commented on Aug 11, 2019

    @bnoordhuis
    Member

    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.

  9. assaf-xm commented on Aug 11, 2019

    @assaf-xm
    Author

    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!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    dgramIssues and PRs related to UDP and the dgram module.invalidIssues and PRs that are invalid.

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions