knock
knock copied to clipboard
IPv6 is not supported under this link-layer type
Hello,
I tried to add IPv6 support to my knockd service using knockd version 0.8.
Here is my /etc/knockd.conf: [options] UseSyslog Interface = venet0
[SSH] sequence = 1234,5678,9012 seq_timeout = 5 start_command = ufw allow from %IP% to any port 22 proto tcp tcpflags = syn cmd_timeout = 10 stop_command = ufw delete allow from %IP% to any port 2 proto tcp
and ifconfig:
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10
venet0: flags=211<UP,BROADCAST,POINTOPOINT,RUNNING,NOARP> mtu 1500
inet 127.0.0.1 netmask 255.255.255.255 broadcast 0.0.0.0 destination 127.0.0.1
inet6 2a01:xxx:xxx:xxx:xxx:xxx:xxx:xxx prefixlen 128 scopeid 0x0
venet0:0: flags=211<UP,BROADCAST,POINTOPOINT,RUNNING,NOARP> mtu 1500 inet 81.yyy.yyy.yyy netmask 255.255.255.255 broadcast 81.yyy.yyy.yyy destination 81.yyy.yyy.yyy unspec 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00 txqueuelen 0 (UNSPEC)
If I try to knock via IPv6 I get the following message in syslog: knockd[23619]: IPv6 is not supported under this link-layer type
Ipv4 doesn't work neither with this configuration.
If I change the config to
[options] UseSyslog Interface = venet0:0
Ipv4 works but Ipv6 doesn't because venet0:0 is only bound to an IPv4 address.
How could I get IPv4 and IPv6 get working?
Hi @BitBlit88 ,
the problem output comes from here: https://github.com/jvinet/knock/blob/cb163f1509f57698c40a1bd8d1d6891af608a18b/src/knockd.c#L1683
That means that the sniffer detected an IPv6 IP packet and now tries to handle it. But there is an issue with setting 'ip6' which is checked in the very next line. https://github.com/jvinet/knock/blob/cb163f1509f57698c40a1bd8d1d6891af608a18b/src/knockd.c#L1684
Here it is set: https://github.com/jvinet/knock/blob/cb163f1509f57698c40a1bd8d1d6891af608a18b/src/knockd.c#L1643 So that the case of 'if(lltype == DLT_EN10MB)'. Anyhow there are two other cases where 'ip6' is not properly set in the 'elseif' cases here: https://github.com/jvinet/knock/blob/cb163f1509f57698c40a1bd8d1d6891af608a18b/src/knockd.c#L1646 and here: https://github.com/jvinet/knock/blob/cb163f1509f57698c40a1bd8d1d6891af608a18b/src/knockd.c#L1649
I guess you now have one of the ifelse-cases and thereby ip6 pointer is not properly set and knockd bails out with the error logile you have seen.
I fixed it in my fork here: https://github.com/TDFKAOlli/knock/blob/58a2ed4585af7c7bd9b19bfd82e3f2fa522c0a42/src/knockd.c#L1662 and here: https://github.com/TDFKAOlli/knock/blob/58a2ed4585af7c7bd9b19bfd82e3f2fa522c0a42/src/knockd.c#L1666 but I couldn't test it, cause I never run into those lines. Anyhow you can try to patch your version and test or create a pull request for this repository.
Hi @TDFKAOlli,
your fix works very well. But I have still the problem that either IPv4 or IPv6 works but not both together. Unfortunately my provider forces to set IPv6 on interface "venet0:0" and IPv4 on interface "venet0". I think knockd can't listen on two interfaces. The only solution I see is running two instances of knockd listening on different interfaces or some kind of network bonding.
@BitBlit88 , good to head it is working 😄 Can you create a pull request? I guess it can help others too. And yes, multiple interface support is not yet there. I thought in the past about trying to add it, but in the end it seems I didn't needed it enough to start working on it 😉 . But I guess your proposal of running two knockd processes would work.
Hey @BitBlit88 , I just read this about pcap:
pcap_open_live() is used to obtain a packet capture handle to look at packets on the network. device is a string that specifies the network device to open; on Linux systems with 2.2 or later kernels, a device argument of "any" or NULL can be used to capture packets from all interfaces.
Written here: https://www.tcpdump.org/manpages/pcap_open_live.3pcap.html
So it might work that you simply use "any" as interface in the knockd config. (Or you add a config to use any in pcap_open_live()). The drawback is, it really listens then to any interface, not only the the two interfaces you want it to listen too. But that might be o.k.
EDIT: Ah, no, one more change is needed, here: https://github.com/jvinet/knock/blob/cb163f1509f57698c40a1bd8d1d6891af608a18b/src/knockd.c#L280 This is fetching the IP-address of the interface, but checks for the interface name. I guess it should be changed so it matched either the interface name or "any" and in both cases fetches the IP-address.
Hi @TDFKAOlli,
you are great! Thanks for pointing this out.
I change the line to
if((strcmp(ifa->ifa_name, o_int) == 0 || strcmp("any", o_int) == 0) && (ifa->ifa_addr->sa_family == AF_INET || (ifa->ifa_addr->sa_family == AF_INET6 && !o_skipIpV6))) {
and modified "knockd.conf" to Interface = any
Now both IPv4 and Ipv6 works. I will cherry pick your changes with the above code and make a pull request.
No prob, came to my mind just now. Before I thought about parsing a list of interfaces and then spawning several knockds for it so to handle each interface by an own thread... This "any" is much more simpler and would do in most cases I guess. 😄