ikos
ikos copied to clipboard
ikos server doesn't listen on IPv6, resulting in hangs
In an environment created by ikos-scan, IKOS_SCAN_SERVER is set like http://localhost:8433.
On a dualstack system, localhost usually resolves to both V4 and V6 addresses. E.g. curl tries both:
% curl -v localhost:8433
* Trying ::1:8433...
* TCP_NODELAY set
* Trying 127.0.0.1:8433...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8433 (#0)
> GET / HTTP/1.1
The ikos server only listens on V4:
% doas sockstat | rg 8433
greg python3.7 37245 3 tcp4 *:8433 *:*
But the ikos-scan-cc client tries to access V6:
% doas sockstat | rg 8433
greg python3.7 7535 3 tcp6 ::1:49105 ::1:8433
and hangs. (This is on FreeBSD.)
Interestingly, there is no mention of IPv4 or IPv6 in the code.
The server is handled by http.server.HTTPServer: https://github.com/NASA-SW-VnV/ikos/blob/72c70c79fdef482b78b131218d16c6c7aa82edd8/analyzer/python/ikos/scan.py#L631
The client is urllib.request.urlopen: https://github.com/NASA-SW-VnV/ikos/blob/72c70c79fdef482b78b131218d16c6c7aa82edd8/analyzer/python/ikos/scan.py#L592
As a quick fix, try using 127.0.0.1 instead of localhost there:
https://github.com/NASA-SW-VnV/ikos/blob/72c70c79fdef482b78b131218d16c6c7aa82edd8/analyzer/python/ikos/scan.py#L902
I won't be able to commit on this project until I get the approval from my new employer.
There are two files we'd have to change: analyzer/python/ikos/view.py and analyzer/python/ikos/scan.py, since both initialize servers and both do it in the same way.
At least on linux, creating a subclass of HTTPServer that sets address_family = socket.AF_INET6 and using that with the first argument set to '::' should be enough.
@valpackett Could you please check if https://github.com/NASA-SW-VnV/ikos/pull/229 solves your issue? The PR is marked as a draft but that's just so that it's not merged accidentally before you try it.
Woah, it's been 3 years! I haven't really been using ikos lately…
Interestingly I cannot reproduce the hang, not sure what changed where, but v6 errors out on an ioctl instead of hanging and it goes to v4:
__sysctl("net.inet6.ip6.addrctlpolicy",4,0x0,0x82036ea10,0x0,0) = 0 (0x0)
__sysctl("net.inet6.ip6.addrctlpolicy",4,0x30eafd1c6500,0x82036ea10,0x0,0) = 0 (0x0)
socket(PF_INET6,SOCK_DGRAM|SOCK_CLOEXEC,IPPROTO_UDP) = 3 (0x3)
connect(3,{ AF_INET6 [::1]:1 },28) = 0 (0x0)
getsockname(3,{ AF_INET6 [::1]:13335 },0x82036e8bc) = 0 (0x0)
ioctl(3,SIOCGIFAFLAG_IN6,0x82036e8f0) ERR#6 'Device not configured'
close(3) = 0 (0x0)
socket(PF_INET,SOCK_DGRAM|SOCK_CLOEXEC,IPPROTO_UDP) = 3 (0x3)
connect(3,{ AF_INET 127.0.0.1:1 },16) = 0 (0x0)
getsockname(3,{ AF_INET 127.0.0.1:44879 },0x82036e8bc) = 0 (0x0)
close(3) = 0 (0x0)
socket(PF_INET,SOCK_STREAM|SOCK_CLOEXEC,IPPROTO_TCP) = 3 (0x3)
connect(3,{ AF_INET 127.0.0.1:8794 },16) = 0 (0x0)
setsockopt(3,IPPROTO_TCP,TCP_NODELAY,0x82036f29c,4) = 0 (0x0)
sendto(3,"POST / HTTP/1.1\r\nAccept-Encodi"...,188,0,NULL,0) = 188 (0xbc)
With #229 it does connect over v6 in the end:
connect(3,{ AF_INET 127.0.0.1:8491 },16) ERR#61 'Connection refused'
close(3) = 0 (0x0)
socket(PF_INET6,SOCK_STREAM|SOCK_CLOEXEC,IPPROTO_TCP) = 3 (0x3)
connect(3,{ AF_INET6 [::1]:8491 },28) = 0 (0x0)
setsockopt(3,IPPROTO_TCP,TCP_NODELAY,0x820244c1c,4) = 0 (0x0)
sendto(3,"POST / HTTP/1.1\r\nAccept-Encodi"...,188,0,NULL,0) = 188 (0xbc)
I'm a bit concerned about how #229 would behave on a v4-only system though.
Maybe would be better to ask @yurivict who maintains the package in FreeBSD Ports right now for more testing :) I have found an unrelated issue though.. (#230)
I'm a bit concerned about how https://github.com/NASA-SW-VnV/ikos/pull/229 would behave on a v4-only system though.
On a system with no support for IPv6, it'll give you the following error:
$ ikos-view output.db
[ERROR] Could not start the HTTP server: [Errno 97] Address family not supported by protocol
It should be trivial to catch this exception and try IPv4 as a fallback, if that (IPv4-only OSs) is a scenario we care to support.
I have updated my PR to also handle the case where the machine only supports IPv4. I have tried it with a linux machine with IPv6 enabled and with no IPv6 (disabled at kernel level during book using ipv6.disable=1 as a kernel parameter) and both cases work correctly.
Please try it @valpackett .
I intend to merge that PR and close this issue in a few days if we can't identify any cases for which it doesn't work. (I'll squash/clean the changes before I merge.)
Thanks.
I have cleaned and prepared the PR for merging. If you try it, let me know how it goes.