UDP broadcast java.net.socketexception under Linux: permission denied

Posted by wildncrazyath3rt on Thu, 04 Nov 2021 22:23:57 +0100

0. Background

  first explain the environment:

OpenJDK8
CentOS7

   secondly, it is common to send messages through UDP broadcasting. When deploying in Linux environment today, the following exceptions occurred when sending messages:

java.net.SocketException: insufficient privilege
        at sun.nio.ch.DatagramChannelImpl.send0(Native Method)
        at sun.nio.ch.DatagramChannelImpl.sendFromNativeBuffer(DatagramChannelImpl.java:528)
        at sun.nio.ch.DatagramChannelImpl.send(DatagramChannelImpl.java:505)
        at sun.nio.ch.DatagramChannelImpl.send(DatagramChannelImpl.java:469)

  if you retrieve similar problems according to the problem description, you will probably find them, because you are listening to ports within 1024, but I am listening to 10568. I even refer to centOS permissions - selinux summary Turn SELinux off and grant various permissions. After I was exhausted, I began to think: what if it was really a code problem?

1. Switch search keywords

  I started to try to retrieve sun.nio.ch.DatagramChannelImpl.send0 permission and found such a question and answer: SecurityException sends broadcasts from Java on OS X . There was a similar problem. One reply was as follows:

After a little Google search, you need to tell the socket datagram channel that it is in use. It is a broadcast channel using code:
channel.socket().setBroadcast(true);
I think you just need to set the broadcast socket option on the "channel", which is the underlying O / S socket. Obviously, once Java 7 appears, this will be implemented at the channel level, but currently you need to access the datagram socket to set parameters.

  yes, this is the line configuration:

channel.socket().setBroadcast(true);

  add it under Linux or Mac to allow you to broadcast. So far, the problem has been solved.

2. What is socket. Setbroadcast()?

  socket.setBroadcast() method is the built-in application programming interface of Socket class in dgram module, which is used to set or clear SO_BROADCAST Socket option, which helps clients send datagrams to specific broadcast addresses.

  SO_ The original text of broadcast is explained as follows:

Sets SO_BROADCAST for a socket. This option enables and disables the ability of the process to send broadcast messages. It is supported for only datagram sockets and only on networks that support the concept of a broadcast message (e.g. Ethernet, token ring, etc.),and it is set by default for DatagramSockets.

  we can see that setting it in the source code uses true and false. This is closed by default under datagram sockets.

  then how did we get into it?

  let's go back to the send function. It has a check in sun.nio.ch.DatagramChannelImpl to check whether it is Multicast.

SecurityManager var7 = System.getSecurityManager();
if (var7 != null) {
    if (var5.isMulticastAddress()) {
        var7.checkMulticast(var5);
    } else {
        var7.checkConnect(var5.getHostAddress(), var4.getPort());
    }
}

  this isMulticastAddress() is very fierce. It directly determines whether the first four digits of your address are 1110. Obviously, I am broadcasting, not multicast. I entered checkConnect, and then it checked permission

  the official interpretation of this function is:

    /**
     * Throws a <code>SecurityException</code> if the requested
     * access, specified by the given permission, is not permitted based
     * on the security policy currently in effect.
     * <p>
     * This method calls <code>AccessController.checkPermission</code>
     * with the given permission.
     *
     * @param     perm   the requested permission.
     * @exception SecurityException if access is not permitted based on
     *            the current security policy.
     * @exception NullPointerException if the permission argument is
     *            <code>null</code>.
     * @since     1.2
     */
    public void checkPermission(Permission perm) {
        java.security.AccessController.checkPermission(perm);
    }

   it means that this is based on the current security policy. If you go further, it is the native method. I'm too lazy to see it. Anyway, it will check whether the io operation is safe. socket.setBroadcast() can help it determine that we are legal. Turn to the source code when you have time.

Topics: Java Linux udp