Local user detection apparently not looking for IPv6 [fixed in v1.399]

edited August 2020 in Problems Now Fixed
The KiwiSDR lets you bypass some user limits (like idle connect time) when you're on the local LAN. This is very nice. But sometimes I still get bounced, other times not.

I suspect the checks only look for local IPv4 addresses and I'm getting bounced when I happen to use IPv6. A lot of networks use IPv6 these days, even if you don't think you are, e.g., mDNS with link-local IPv6 addresses when routable prefixes are not available. (That's the reason for the link-local prefix -- so you can plug things together and have them work even on an isolated network with no DHCP server or external Internet router, like a point-to-point link.)

If this is the case, note that IPv6 requires -- and frequently uses -- more than one local subnet prefix so you have to check for them all. The link local subnet fe80::/16 is always present, and there may also be more than one globally-routable IPv6 prefix (I have two).
Thanks!

Comments

  • I wonder if a hostname lookup could be used instead?

    E.G. Allow local IPv4 subnet + "pc1.something.local", "single.trusted.remote" as long as your PC is what that FQDN points to it assumes local.
    I distrust IPv6 as it seems so "well you could do the address by X,Y,Z, but obviously that relies on your ISP having L,K,M enabled"
    Obviously it opens more support and security issues but then that is v6 anyway (IMO).

    Stu
  • A server can't necessarily know the DNS name of the client talking to it. To do that it has to take the incoming IP address and perform a reverse DNS lookup, which often fails because people don't bother to maintain reverse records. Also, not every client implements mDNS. Even if you do find one, that still won't tell you if it's local or remote. Just look at the incoming client IP address, note whether it's IPv4 or IPv6, and compare it against its own list of IPv4 and IPv6 prefixes (not just IPv4) to see if it's local.
  • Actually, IPv6 doesn't depend on your ISP doing anything. It doesn't require you to have a router or even an Ethernet switch! That's what the link-local prefix fe80::/16 is for; every host is required to implement it so you will at least have local connectivity whether or not you have a public IP address, a route to the outside world or even a local DHCP server.

    With mDNS (multicast DNS, which is what the .local suffix refers to), you can even plug your computer directly into the KiwiSDR with a point-to-point link, open your browser, enter "kiwisdr.local" and have it work. Your PC and the KiwiSDR assign themselves link local addresses and your browser discovers the KiwiSDR with mDNS.

    IPv4 does have something like this, the "self assigned" address block 169.254.0.0/16 that you may have seen when you're having local network trouble. mDNS can use it too. But the IPv6 link-local prefix is a cleaner solution to the problem as everyone always has an address in that block in addition to whatever prefixes are assigned by your ISPs (there can be several). IPv4 addresses in the 169.254.0.0/16 block are used only as a fallback because it's rare to have more than one IPv4 subnet active at a time.

    For example, my KiwiSDR at home has the following addresses:

    eth0: mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 88:3f:4a:9a:2d:08 brd ff:ff:ff:ff:ff:ff
    inet 192.168.42.165/24 brd 192.168.42.255 scope global eth0
    valid_lft forever preferred_lft forever
    inet6 2001:470:d:aa4:8a3f:4aff:fe9a:2d08/64 scope global mngtmpaddr dynamic
    valid_lft 86091sec preferred_lft 14091sec
    inet6 2605:e000:1c0e:43f7:8a3f:4aff:fe9a:2d08/64 scope global mngtmpaddr dynamic
    valid_lft 86091sec preferred_lft 14091sec
    inet6 fe80::8a3f:4aff:fe9a:2d08/64 scope link
    valid_lft forever preferred_lft forever

    The "inet" line is my local (non-routable) IPv4 address. The next two "inet6" lines are globally routable prefixes from my upstream ISPs, Spectrum cable (2605) and a Hurricane Electric tunnel (2001). The last "inet6" line is the link-local address.

    With IPv6 I can talk directly to my KiwiSDR from the outside provided I have IPv6 connectivity without any NAT port forwarding kludges. I do have that set up too, but only for the web service. With IPv6 I can talk transparently to any port on the KiwiSDR, including the SSH port, with no special configuration. If I had more than one, I could address each one individually without having to assign a different port number to each one.

    Phil
  • The Kiwi code handles ipv4, ipv4LL (avahi), ipv4 mapped ipv6, ipv6 and ipv6LL (fe80::/16) addresses. There might be a bug in the code, but the code is there. It was developed over a long period of time as we experienced people with differing/odd local network setups. I don't have full ipv6 capability here which made this code difficult to develop and test.

    Two routines are relevant, net/net.c: find_local_IPs() and isLocal_if_ip(). They produce lots of debug prints that will appear in the admin log tab. The next time you have a local net login failure it would be instructive to take a screenshot of the log tab (scrolled to the two appropriate places described below). Most of these debug prints do _not_ also appear in syslog due to space/noise.

    First, find_local_IPs() queries all the Linux network interfaces to collect all possible ipv4/6 addresses that might be required for subsequent local network matching when a admin/user connection is made. This appears at startup near the top of the log messages. Example:
    Fri Jul 24 18:01:03 00:00:02.117 ....      L NET(0) DEBUG getifaddrs: IF lo fam=17(other) flags=0x10049 UP RUNNING | BAD: family
    Fri Jul 24 18:01:03 00:00:02.117 ....      L NET(0) DEBUG getifaddrs: IF eth0 fam=17(other) flags=0x19043 UP RUNNING | BAD: family
    Fri Jul 24 18:01:03 00:00:02.117 ....      L NET(0) DEBUG getifaddrs: IF usb0 fam=17(other) flags=0x1003 UP | BAD: family
    Fri Jul 24 18:01:03 00:00:02.117 ....      L NET(0) DEBUG getifaddrs: IF usb1 fam=17(other) flags=0x1003 UP | BAD: family
    Fri Jul 24 18:01:03 00:00:02.117 ....      L NET(0) DEBUG getifaddrs: IF wlan0 fam=17(other) flags=0x1002 | BAD: family
    Fri Jul 24 18:01:03 00:00:02.117 ....      L NET(0) DEBUG getifaddrs: IF SoftAp0 fam=17(other) flags=0x1002 | BAD: family
    Fri Jul 24 18:01:03 00:00:02.117 ....      L NET(0) DEBUG getifaddrs: IF lo fam=2(ipv4) flags=0x10049 UP RUNNING | BAD: IF
    Fri Jul 24 18:01:03 00:00:02.117 ....      L NET(0) DEBUG getifaddrs: IF eth0 fam=2(ipv4) flags=0x19043 UP RUNNING | OK
    Fri Jul 24 18:01:03 00:00:02.118 ....      L NET(0) DEBUG IF IPv4 0xc0a8016b /24 0xffffff00 eth0
    Fri Jul 24 18:01:03 00:00:02.118 ....      L NET(0) DEBUG getifaddrs: IF usb0 fam=2(ipv4) flags=0x1003 UP | BAD: IF
    Fri Jul 24 18:01:03 00:00:02.118 ....      L NET(0) DEBUG getifaddrs: IF usb1 fam=2(ipv4) flags=0x1003 UP | BAD: IF
    Fri Jul 24 18:01:03 00:00:02.118 ....      L NET(0) DEBUG getifaddrs: IF lo fam=10(ipv6) flags=0x10049 UP RUNNING | BAD: IF
    Fri Jul 24 18:01:03 00:00:02.118 ....      L NET(0) DEBUG getifaddrs: IF eth0 fam=10(ipv6) flags=0x19043 UP RUNNING | OK
    Fri Jul 24 18:01:03 00:00:02.118 ....      L NET(0) DEBUG IF IPv6 LINK-LOCAL /64 eth0
    Fri Jul 24 18:01:03 00:00:02.118 ....      L NET(0): private IPv4 <192.168.1.107> 0xc0a8016b /24 0xffffff00 eth0
    Fri Jul 24 18:01:03 00:00:02.118 ....      L NET(0): private IPv6 LINK-LOCAL  /64 ff:ff:ff:ff:ff:ff:ff:ff:00:00:00:00:00:00:00:00: eth0
    Fri Jul 24 18:01:03 00:00:02.118 ....      L NET(0) DEBUG ip4_valid=1 ip4_6_valid=0 ip6_valid=0 ip6LL_valid=1
    
    So at the end of all that we are left with two valid server private addresses: a regular ipv4 and an ipv6 link local, both on eth0.

    Now when an incoming admin/user connection is made isLocal_if_ip() attempts to do a match of the remote ip against the list of server private addresses looking for a local network match (ipv4 is checked first, then ipv6). Example:
    Fri Jul 24 18:07:26 00:06:25.182 0... 0      PWD isLocal_if_ip: flg=0x18 fam=2 socktype=1 proto=6 addrlen=16 192.168.1.3
    Fri Jul 24 18:07:26 00:06:25.182 0... 0    L PWD isLocal_if_ip: TRUE IPv4/4_6 remote_ip 192.168.1.3 ip_client 192.168.1.3/0xc0a80103 ip_server[IPv4] 192.168.1.107/0xc0a8016b nm /24 0xffffff00
    Fri Jul 24 18:07:26 00:06:25.182 0... 0      PWD kiwi SND conn #0 isLocal=1 is_local=1 auth=0 auth_kiwi=0 auth_prot=0 auth_admin=0 check_ip_against_restricted=0 restricted_ip_match=0 from 192.168.1.3
    
    Here an ipv4 remote of 192.168.1.3 matches (i.e. "isLocal_if_ip: TRUE IPv4/4_6") against the server ipv4 192.168.1.107/24.

    If you are being improperly prompted for a password on a local network then it is possible there is a bug in the password checking code (which is also very complex because of the many user-requested features it must handle, e.g. time limits). There are debug prints beginning with "PWD" that would be interesting to see in this case.
  • edited July 2020
    OK, I'm looking at my logs. The problem does indeed seem to be that local IPv6 addresses aren't recognized as local. Here's a sample log entry:

    Fri Jul 17 06:08:43 01:40:20.525 0123 [05] PWD isLocal_if_ip: FALSE IPv6 remote_ip 2605:e000:1c0e:43f7:d63d:7eff:fe5f:1e2e ip_client 2605:e000:1c0e:43f7:d63d:7eff:fe5f:1e2e ip_server[IPv6] 2605:e000:1c0e:43f7:8a3f:4aff:fe9a:2d08 nm /64

    The IPv6 address ending in 2d08 is indeed my kiwisdr's own IPv6 address. The address ending in 1e2e is that of my Linux desktop from which I am connecting. The /64 prefix width is correct.

    When I happen to come in with IPv4, everything works:
    Fri Jul 31 05:20:46 14d:00:52:23.429 .12. [00] PWD isLocal_if_ip: TRUE IPv4/4_6 remote_ip 192.168.42.99 ip_client 192.168.42.99/0xc0a82a63 ip_server[IPv4] 192.168.42.165/0xc0a82aa5 nm /24 0xffffff00
  • I added some debugging prints to your Kiwi code because the existing ones are not sufficient to determine the problem.

    Please restart your Kiwi and login locally as admin until you get the failure condition and then let me know here. Thanks.
  • Phil, is your Internet connection ipv6 multi-homed? An "ifconfig eth0" produces:
              inet6 addr: fe80::8a3f:4aff:fe9a:2d08/64 Scope:Link
              inet6 addr: 2001:470:d:aa4:8a3f:4aff:fe9a:2d08/64 Scope:Global
              inet6 addr: 2605:e000:1c0e:43f7:8a3f:4aff:fe9a:2d08/64 Scope:Global
    So, in addition to the LL, that's two separate ipv6 /64 subnets with the 8a3f:4aff:fe9a:2d08 host.

    The Kiwi code did not anticipate this kind of situation. And after some reading it seems to occur in other scenarios as well. So I'll have to amend the code to check for a local network match against more interface addresses.
  • Okay, I think I have a fix for this issue running on your Kiwi. Please give it a try and if it seems to work I'll send out a release.
  • That's correct, my network is multi-homed on IPv6. The 2605:e000 prefix is Spectrum Cable, my ISP. The 2001:470 prefix is a free IPv6-in-IPv4 tunnel provided by Hurricane Electric.

    Multihoming is a pretty basic feature of IPv6, and every host is required to implement it. Among other things, it makes automatic renumbering much easier than in IPv4. I.e., your ISP can change your prefix, and as long as they provide a changeover period during which both prefixes are valid, you often don't have to do anything at all to your own computers.
Sign In or Register to comment.