Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FreeBSD: failure binding on a NAT-ed loopback interface. #1709

Open
karolyi opened this issue Aug 19, 2021 · 5 comments
Open

FreeBSD: failure binding on a NAT-ed loopback interface. #1709

karolyi opened this issue Aug 19, 2021 · 5 comments

Comments

@karolyi
Copy link

karolyi commented Aug 19, 2021

Hey guys,

yes I read the issue template, and this seems to be a genuine bug. For details, see https://community.jitsi.org/t/videobridge-problems/67691.

Because of this bug, I am unable to run Jitsi on FreeBSD now.

@bgrozev
Copy link
Member

bgrozev commented Aug 19, 2021

Hey, thanks for the report.

Most probably the failure is because ice4j refuses to bind on a loopback interface, and there are no other interfaces available. You can run the following to confirm (save as Test.java and run javac Test.java && java Test):


import java.lang.reflect.*;
import java.net.*;
import java.util.*;

class Test
{
   public static void main(String[] args)
   {
       getAllAllowedAddresses();
   }

   public static List<InetAddress> getAllAllowedAddresses()
   {
       List<InetAddress> addresses = new LinkedList<>();
       try
       {
           for (NetworkInterface iface
                   : Collections.list(NetworkInterface.getNetworkInterfaces()))
           {
               System.err.println("Interface: " + iface);
               System.err.println("  isLoopback:" + isInterfaceLoopback(iface));
               System.err.println("  isUp:" + isInterfaceUp(iface));
               if (isInterfaceLoopback(iface) || !isInterfaceUp(iface))
               {
                   continue;
               }

               Enumeration<InetAddress> ifaceAddresses = iface.getInetAddresses();
               while (ifaceAddresses.hasMoreElements())
               {
                   InetAddress address = ifaceAddresses.nextElement();
                   System.err.println("  Address"+address + " isIvp6="+(address instanceof Inet6Address));

                   if (address instanceof Inet6Address)
                       continue;

                   addresses.add(address);
               }
           }
       }
       catch (SocketException se)
       {
           System.err.println("Failed to get network interfaces: " + se);
       }

       return addresses;
   }

   public static boolean isInterfaceLoopback(NetworkInterface iface)
   {
       try
       {
           Method method = iface.getClass().getMethod("isLoopback");

           return (Boolean) method.invoke(iface);
       }
       catch(Throwable t)
       {
           //apparently we are not running in a JVM that supports the
           //is Loopback method. we'll try another approach.
       }
       Enumeration<InetAddress> addresses = iface.getInetAddresses();

       return addresses.hasMoreElements()
               && addresses.nextElement().isLoopbackAddress();
   }

   public static boolean isInterfaceUp(NetworkInterface iface)
   {
       try
       {
           Method method = iface.getClass().getMethod("isUp");

           return (Boolean) method.invoke(iface);
       }
       catch(Throwable t)
       {
           //apparently we are not running in a JVM that supports the
           //isUp method. returning default value.
       }

       return true;
   }
}

Assuming that this is the case. Do you know if it is normal for FreeBSD and/or jails to run with only loopback interfaces? We can accept a patch to make this ice4j behavior configurable.

@karolyi
Copy link
Author

karolyi commented Aug 19, 2021

Hey, thanks for the super quick reply.

Yes, in the case of FreeBSD, it is pretty usual that jails (the same as docker for linux but more powerful) get such interfaces, with NAT-ed internal IP addresses. As you can see on the linked forum topic, many people struggle with it, just like me.

I've got a bridge0, the videobridge can bind on it, but that is only a public ipv6 address in my case which is not sufficient. We need to bind all to all interfaces, be it loopback or not.

As for a patch, unfortunately I'm not a Java coder so I can't help you out here.

Hoping for a quick resolution.

Cheers!

@karolyi
Copy link
Author

karolyi commented Aug 19, 2021

Executing the test code, the output displayed the lo0 interface, but not its IPv4 address:

Interface: name:bridge0 (bridge0)
  isLoopback:false
  isUp:true
  Address/2aff::3e isIvp6=true
Interface: name:lo0 (lo0)
  isLoopback:true
  isUp:true

it's got an IPv4 address though:

lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
        options=680003<RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>
        inet 127.0.0.35 netmask 0xffffffff
        groups: lo
        nd6 options=21<PERFORMNUD,AUTO_LINKLOCAL>

Edit: alright, my bad, I saw the code exited on the interface being loopback. Commenting that part out displayed its IP address.

@bgrozev
Copy link
Member

bgrozev commented Aug 20, 2021

Thanks, this confirms that the reason the interface is not used by ice4j is because it's loopback.

@karolyi
Copy link
Author

karolyi commented Aug 22, 2021

Hey @bgrozev, see the submitted patch. Disclaimer: I'm still not a java coder, although I already built a small application in Kotlin a couple years ago.

This whole new configuration option I added has the caveat of making the other two configuration option for the allowed/blockes interfaces unclear.

I'd rather just use the two options already in place (but properly evaluated), and skip loopback address checking in isAddressAllowed().

On second thought, I might just added an error there, in the case of IPv6 link local addresses, I think.

It's your call.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants