-
Notifications
You must be signed in to change notification settings - Fork 1.8k
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
GET http://localhost:9993/status X-ZT1-Auth:... fails over IPv4 but works over IPv6 #2151
Comments
Hello! Thanks for reporting. This isn't happening on my mac; both curl -4 and curl -6 work. So that's strange. Are there any error messages when zerotier is starting up? "authCheck" is around here: ZeroTierOne/service/OneService.cpp Line 1607 in 9ae8b0b
|
No, there's no error messages that I see running a |
ok I think we can see why the auth fails :D but do the numbers here mean anything to you? if (remoteAddr.ipScope() == InetAddress::IP_SCOPE_LOOPBACK) {
|
ifconfig output if that's relevant
|
Not really but they're in here ZeroTierOne/node/InetAddress.cpp Line 29 in 9ae8b0b
I'm curious what remoteAddr actually is? I think you can print it like this:
|
interesting:
something in between the IP stack (as seen by ngrep output) and zerotier turns this into a |
That's really strange. I don't think we'll be able to do a fix and release in a timely fashion. You might be able to put |
That specific pattern didn't work, in the end I used |
Seems like it to me, but I don't know the threat model, your requirements, etc... remove |
This basically broke new zerotier installs on all FreeBSD and TrueNAS systems, you can't add nodes unless find this issue. Any chance this could get addressed for 1.14? The fix is likely to be quite trivial, to add the missing match to InetAddress.cpp. In OneService.cpp#L1601-L1610 is called with these values:
According to InetAddress.hpp#L67C1-L67C75 AFAICT this is an error in InetAddress.cpp which decides that I will test on FreeBSD 13.x and 14.x again to see what I can track down, in particular what the memory representation of |
yeah lets take a look |
OK it aint pretty, but it does fix the issue... over to you c++ gurus to make it pretty/correct: diff --git a/node/InetAddress.cpp b/node/InetAddress.cpp
index da1c7294..7a786e49 100644
--- a/node/InetAddress.cpp
+++ b/node/InetAddress.cpp
@@ -112,6 +112,20 @@ InetAddress::IpScope InetAddress::ipScope() const
} break;
case AF_INET6: {
+ // Check for IPv4-mapped IPv6 addresses (::ffff::/96 prefix)
+ const struct sockaddr_in6* sa6 = reinterpret_cast<const struct sockaddr_in6*>(this);
+ if (sa6->sin6_addr.s6_addr[0] == 0 && sa6->sin6_addr.s6_addr[1] == 0 &&
+ sa6->sin6_addr.s6_addr[2] == 0 && sa6->sin6_addr.s6_addr[3] == 0 &&
+ sa6->sin6_addr.s6_addr[4] == 0 && sa6->sin6_addr.s6_addr[5] == 0 &&
+ sa6->sin6_addr.s6_addr[6] == 0 && sa6->sin6_addr.s6_addr[7] == 0 &&
+ sa6->sin6_addr.s6_addr[8] == 0 && sa6->sin6_addr.s6_addr[9] == 0 &&
+ sa6->sin6_addr.s6_addr[10] == 0xff && sa6->sin6_addr.s6_addr[11] == 0xff) {
+ // next 4 bytes should be IPv4 address 0x7f000001 / 127.0.0.1
+ uint32_t ipv4Part = *(reinterpret_cast<const uint32_t*>(&sa6->sin6_addr.s6_addr[12]));
+ if (ipv4Part == htonl(0x7f000001)) {
+ return IP_SCOPE_LOOPBACK;
+ }
+ }
const unsigned char *ip = reinterpret_cast<const unsigned char *>(reinterpret_cast<const struct sockaddr_in6 *>(this)->sin6_addr.s6_addr);
if ((ip[0] & 0xf0) == 0xf0) {
if (ip[0] == 0xff) {
diff --git a/service/OneService.cpp b/service/OneService.cpp
index b06bcb9b..8f52ce58 100644
--- a/service/OneService.cpp
+++ b/service/OneService.cpp
@@ -1697,8 +1697,14 @@ public:
bool ipAllowed = false;
bool isAuth = false;
// If localhost, allow
+ char buf[64];
+ fprintf(stderr, "remoteAddr %s\n", remoteAddr.toIpString(buf));
if (remoteAddr.ipScope() == InetAddress::IP_SCOPE_LOOPBACK) {
+ fprintf(stderr, "ALLOWED\n");
ipAllowed = true;
+ } else
+ {
+ fprintf(stderr, "DENIED\n");
}
if (!ipAllowed) { |
was this perhaps a change in the underlying httplib that passes a different form of remote address through? |
Not sure yet. Thanks for working on it. |
once there's a more appropriate patch I'll backport it to the current FreeBSD port. |
The httplib unsets the IPV6_V6ONLY socket option. This seems to make all IPv4 requests come in with the ::ffff:, as a v6 to 4 mapping thing. Making it parse ::ffff:127.0.0.1 as loopback works. But it also does the 6 to 4 thing to other ip addresses:
this patch also makes it work. Maybe we can make that a FreeBSD specific patch or something. |
cpp-httplib sets IPV6_V6ONLY to false on it's sockets. On FreeBSD, this makes all ipv4 addresses get get prefixed with ::ffff: it makes them IPv6 addresses mapped to v4. This is a partial fix for #2151. The cli will work again. Something should probably also be adjusted with the httplib. If you want to, for example, use the `allowManagementFrom` option in local.conf you will need to prefix it with "::ffff:", "::ffff:1.2.3.4" which is a little surprising and inconsistent between BSD and other OSs.
cpp-httplib sets IPV6_V6ONLY to false on it's sockets. On FreeBSD, this makes all ipv4 addresses get get prefixed with ::ffff: it makes them IPv6 addresses mapped to v4. This is a partial fix for zerotier#2151. The cli will work again. Something should probably also be adjusted with the httplib. If you want to, for example, use the `allowManagementFrom` option in local.conf you will need to prefix it with "::ffff:", "::ffff:1.2.3.4" which is a little surprising and inconsistent between BSD and other OSs.
Your improved version of my ugly hack looks great, let's roll - thanks! BTW I tested this patch and wasn't able to run Perhaps, for a dual-stack address like |
thanks, works a treat. I pulled this into FreeBSD 1.12.2 as an upstream patch. |
Please let us know
There's a regression between 1.12.0 and 1.12.1 that breaks ipv4 localhost query
via
zerotier-cli info
. I've only just noticed while adding a new node thatthis is broken.
Under v1.12.1:
But clearly the daemon is up, and listening.
We'd like to see, as under previous versions, the info.
Under v1.12.0:
authtoken.secret
hasn't changed in years on nodesRunning the same thing using tcpdump/ngrep, we see that this is basically the same as running an HTTP
GET
tohttp://localhost:9993/status
with headerX-ZT1-Auth:my_secret
so let's do that with curl:The
-v4
version should be authorized correctly, but isn't, whether viazerotier-cli
orcurl
.The text was updated successfully, but these errors were encountered: