From 3d85a615fb9a50e193eac5320522be409408a3c3 Mon Sep 17 00:00:00 2001 From: Adam Ierymenko Date: Tue, 28 Oct 2014 14:17:39 -0700 Subject: [PATCH] NULL dereference on still-initializing node bug fix in status query commands, and doc updates. --- README.md | 52 +++++++++++++++++++++++++++++++++++-------- include/ZeroTierOne.h | 5 +++++ node/Node.cpp | 23 +++++++++++++++---- testnet.cpp | 16 ++++++++----- 4 files changed, 77 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index e0a5839d7..e12e652cb 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,52 @@ -ZeroTier One - Ethernet Virtualization +ZeroTier One - Planetary Scale Software Defined Networking ====== -ZeroTier One is an ethernet virtualization engine. It creates virtual LANs of almost unlimited size that span physical network boundaries. +ZeroTier One is an ethernet virtualization engine. It creates virtual switched LANs of almost unlimited size that span physical network boundaries. To the operating system these behave just like ordinary Ethernet ports. Everything just works, even as your computer moves around or your physical Internet link changes. -The underlying protocol is peer to peer with managed anchor points ("supernodes") for instant-on communication, assisted NAT traversal, and relaying for users who cannot make P2P connections. All unicast packets are encrypted end-to-end using private keys that only you control. Multicast and broadcast work as they would on a normal LAN, except that traffic is throttled and intelligently prioritized on large networks to stay within bandwidth limits while preserving essential functionality (multicast triage algorithm). Its behavior is not unlike some enterprise-grade intelligent ethernet switches designed for huge wired networks such as university LANs. +It's intended to replace conventional hub-and-spoke VPNs, provide provider-neutral secure private backplane networks to multi-data-center and hybrid cloud deployments, and much more. -[Visit ZeroTier Networks on the web](https://www.zerotier.com/) for more information. Follow the [ZeroTier blog](https://www.zerotier.com/blog/) and the [GitHub project](https://github.com/zerotier/ZeroTierOne) to stay up to date. See the GitHub-hosted wiki (sidebar) for technical info and help for various platforms. +ZeroTier uses a peer to peer network with managed anchor points ("supernodes"). These are operated by ZeroTier Networks, and are free to use. They provides instant "zero configuration" startup, NAT traversal assistance, relaying in cases where NAT traversal doesn't work, and a trusted root authority for looking up peer public keys (identities). The supernodes run the same open-source software as regular nodes, are geographically distributed across three continents, and have remained stable for over a year. [This blog post](http://adamierymenko.com/decentralization-i-want-to-believe/) discusses the design rationale in some detail. -Auto-updating binary packages that install easily [can be found here.](https://www.zerotier.com/download.html) Packages for popular Linux distributions that neatly wrap the Linux installer/uninstaller are coming soon. If you want to build from source, clone this repository and see BUILDING.txt and RUNNING.txt. If you build manually you'll have to update manually. +ZeroTier One encrypts all traffic end-to-end with keys that only you control. Even when traffic is traversing our network we cannot decrypt it. It's not, however, a "strong privacy" tool since it would still be possible for us (or your ISP or anyone else in between) to observe "meta-data" about your traffic. If you need *that* level of anonymity, we recommend [Tor](https://www.torproject.org) or something similar. Onion routing is the only technology we're aware of that is capable of delivering that level of end-to-end privacy protection. -Once you are up and running, you can [create an account on the network control panel](https://www.zerotier.com/networks.html) if you want to create a private network or you can join [Earth](https://www.zerotier.com/earth.html) by running (on Linux and Mac) `sudo ./zerotier-cli join 8056c2e21c000001`. (Earth is a public virtual network, meaning that it has no access control and allows anyone to join. Make sure your system is up to date and you have no unprotected network services listening.) +At the moment the ZeroTier wire protocol is only documented in the source (start with the comments in Packet.hpp), but more formal documentation is planned for the near future. Encapsulation overhead is comparable to IPSec or OpenVPN. -Note: If UDP traffic over port 9993 (at a minimum) is not permitted by your local or network firewall(s), ZeroTier One will fall back to TCP tunneling to supernodes over port 443 and will not be able to make direct NAT-t connections to other peers. This fallback mode slows things down considerably. If you're getting very poor performance check your firewall settings. You can see if fallback mode is active by checking for outbound TCP connections from the zerotier-one process to port 443 on five or six hosts in the zerotier.com domain. (See Defaults.cpp for a list of these hosts.) +[Visit ZeroTier Networks on the web](https://www.zerotier.com/) for more information. Follow the [ZeroTier blog](https://www.zerotier.com/blog/), [Twitter feed](https://twitter.com/ZeroTier) and the main [GitHub project](https://github.com/zerotier/ZeroTierOne) to stay up to date. See the GitHub-hosted wiki (sidebar) for more technical info and help for various platforms. There's also a [support portal](https://www.zerotier.com/support/) for more general information. -Most users will use IPv4 and/or IPv6 over ZeroTier One, but since it virtualizes at the ethernet (layer 2) level it can technically host almost any protocol. Users have made classic multiplayer games work over IPX, for example. Services like DHCP and IPv6 NDP for link-local addresses can work automatically. +### Getting Started -The service is free for public networks and for managed private networks up to ten users. The code is open source and is licensed under the GNU GPL v3 (not LGPL). If you'd like to embed it in a closed-source commercial product, please e-mail [contact@zerotier.com](mailto:contact@zerotier.com) to discuss licensing. +Auto-updating binary packages that install easily [can be found here](https://www.zerotier.com/download.html) for officially supported platforms. Packages for popular Linux distributions that neatly wrap the Linux installer/uninstaller are coming soon. + +If you want to build from source, clone this repository and see BUILDING.txt and RUNNING.txt. If you build manually you'll have to update manually, and we recommend doing so often as development is progressing very rapidly. (Protocol is pretty stable but you might miss out on new features or experience performance degradation if you're too far behind.) + +Once you are up and running, you have several options. + +ZeroTier provides ZeroTier One for free, but to help finance development and operations we have a [user-friendly freemium control panel on the web](https://www.zerotier.com/admin.html). This control panel lets you quickly and easily create your own networks, and the operation of their controller node(s) is left to us. Public networks created on our site are free, and private networks are free for up to ten devices. After that there is a monthly charge. + +You *only* need an account on our site if you want to use the control panel found there. Joining networks requires no account. To get authorized on a private network, just send your device's 10-digit ID to the network's administrator and they can add you. + +Public networks, as the name implies, can be joined without getting authorization from anyone. All you need is their 16-digit network ID. A public network called [Earth](https://www.zerotier.com/earth.html) (8056c2e21c000001) exists for everyone, but be sure your device is adequately secured and up to date before joining. + +Alternatively, you can run your own network configuration controller. This lets you run any network for free. To do this, start with the netconf-service/ subfolder of this project. You'll need to do a bit of system administration work and manually populate a Redis database, but it's not terribly hard if you're into that kind of thing. + +More products and services will be forthcoming. + +### Basic Troubleshooting + +For about 95% of users, it just works. + +If you are running a local system firewall, we recommend adding a rule permitting UDP port 9993 inbound and outbound. The binary Windows installer takes care of this for Windows' built-in firewall, but other platforms and third party firewall software may need this for optimal performance. + +ZeroTier One peers will automatically locate each other and communicate directly over a local wired LAN *if UDP port 9993 inbound is open*. If that port is filtered, they won't be able to see each others' LAN announcement packets. If you're experiencing poor performance between devices on the same physical network, check their firewall settings. Without LAN auto-location peers must attempt "loopback" NAT traversal, which sometimes fails and in any case requires that every packet traverse your external router twice. + +Users behind certain types of firewalls and "symmetric" NAT devices may not able able to connect to external peers directly at all. ZeroTier has limited support for port prediction and will *attempt* to traverse symmetric NATs, but this doesn't always work. If P2P connectivity fails you'll be bouncing UDP packets off our relay servers resulting in slower performance. Some NAT router(s) have a configurable NAT mode, and setting this to "full cone" will eliminate this problem. If you do this you may also see a magical improvement for things like VoIP phones, Skype, BitTorrent, WebRTC, certain games, etc., since all of these use NAT traversal techniques similar to ours. + +If you're interested, there's a [technical deep dive about NAT traversal on our blog](https://www.zerotier.com/blog/?p=226). A troubleshooting tool to help you diagnose NAT issues is planned for the future as are uPnP/IGD/NAT-PMP and IPv6 transport. + +If a firewall between you and the Internet blocks ZeroTier's UDP traffic, you will fall back to last-resort TCP tunneling to supernodes over port 443 (https impersonation). This will work almost anywhere but is *slow*. If performance seems just terrible, this is the first thing to check. + +Some Windows users have reported a [https://github.com/zerotier/ZeroTierOne/issues/107](problem with the TAP device driver). From user reports this seems to occur on Windows systems that have not been updated through Windows Update. While we have a fix planned, we **really** recommend keeping your system up to date for security reasons. Frankly we're a bit torn on this one. If this is truly the cause, perhaps ZeroTier failing to work on unpatched Windows systems is a feature not a bug. + +More help can be found in the [GitHub wiki](https://github.com/zerotier/ZeroTierOne/wiki) and the [customer support portal / knowledge base](https://www.zerotier.com/support/). + +The ZeroTier source code is open source and is licensed under the GNU GPL v3 (not LGPL). If you'd like to embed it in a closed-source commercial product or appliance, please e-mail [contact@zerotier.com](mailto:contact@zerotier.com) to discuss licensing. diff --git a/include/ZeroTierOne.h b/include/ZeroTierOne.h index 0a7c79847..8d54953a3 100644 --- a/include/ZeroTierOne.h +++ b/include/ZeroTierOne.h @@ -93,6 +93,11 @@ struct ZT1_Node_Status * True if running; all other fields are technically undefined if this is false */ bool running; + + /** + * True if initialization is complete + */ + bool initialized; }; /** diff --git a/node/Node.cpp b/node/Node.cpp index 7ca435aea..0758535e8 100644 --- a/node/Node.cpp +++ b/node/Node.cpp @@ -702,9 +702,9 @@ bool Node::online() throw() { _NodeImpl *impl = (_NodeImpl *)_impl; - if (!impl->running) - return false; RuntimeEnvironment *RR = (RuntimeEnvironment *)&(impl->renv); + if ((!RR)||(!RR->initialized)) + return false; uint64_t now = Utils::now(); uint64_t since = RR->timeOfLastResynchronize; std::vector< SharedPtr > snp(RR->topology->supernodePeers()); @@ -753,7 +753,8 @@ void Node::join(uint64_t nwid) { _NodeImpl *impl = (_NodeImpl *)_impl; RuntimeEnvironment *RR = (RuntimeEnvironment *)&(impl->renv); - RR->nc->join(nwid); + if ((RR)&&(RR->initialized)) + RR->nc->join(nwid); } void Node::leave(uint64_t nwid) @@ -761,7 +762,8 @@ void Node::leave(uint64_t nwid) { _NodeImpl *impl = (_NodeImpl *)_impl; RuntimeEnvironment *RR = (RuntimeEnvironment *)&(impl->renv); - RR->nc->leave(nwid); + if ((RR)&&(RR->initialized)) + RR->nc->leave(nwid); } struct GatherPeerStatistics @@ -785,6 +787,9 @@ void Node::status(ZT1_Node_Status *status) memset(status,0,sizeof(ZT1_Node_Status)); + if ((!RR)||(!RR->initialized)) + return; + Utils::scopy(status->publicIdentity,sizeof(status->publicIdentity),RR->identity.toString(false).c_str()); RR->identity.address().toString(status->address,sizeof(status->address)); status->rawAddress = RR->identity.address().toInt(); @@ -807,6 +812,7 @@ void Node::status(ZT1_Node_Status *status) status->online = online(); status->running = impl->running; + status->initialized = true; } struct CollectPeersAndPaths @@ -824,6 +830,9 @@ ZT1_Node_PeerList *Node::listPeers() _NodeImpl *impl = (_NodeImpl *)_impl; RuntimeEnvironment *RR = (RuntimeEnvironment *)&(impl->renv); + if ((!RR)||(!RR->initialized)) + return (ZT1_Node_PeerList *)0; + CollectPeersAndPaths pp; RR->topology->eachPeer(pp); std::sort(pp.data.begin(),pp.data.end(),SortPeersAndPathsInAscendingAddressOrder()); @@ -910,6 +919,9 @@ ZT1_Node_Network *Node::getNetworkStatus(uint64_t nwid) _NodeImpl *impl = (_NodeImpl *)_impl; RuntimeEnvironment *RR = (RuntimeEnvironment *)&(impl->renv); + if ((!RR)||(!RR->initialized)) + return (ZT1_Node_Network *)0; + SharedPtr network(RR->nc->network(nwid)); if (!network) return (ZT1_Node_Network *)0; @@ -950,6 +962,9 @@ ZT1_Node_NetworkList *Node::listNetworks() _NodeImpl *impl = (_NodeImpl *)_impl; RuntimeEnvironment *RR = (RuntimeEnvironment *)&(impl->renv); + if ((!RR)||(!RR->initialized)) + return (ZT1_Node_NetworkList *)0; + std::vector< SharedPtr > networks(RR->nc->networks()); std::vector< SharedPtr > nconfs(networks.size()); std::vector< std::set > ipsv(networks.size()); diff --git a/testnet.cpp b/testnet.cpp index 605d89452..b6f6572b6 100644 --- a/testnet.cpp +++ b/testnet.cpp @@ -278,12 +278,14 @@ static void doList(const std::vector &cmd) ZT1_Node_Status status; for(std::map< Address,SimNode * >::iterator n(nodes.begin());n!=nodes.end();++n) { n->second->node.status(&status); - printf("%s %c %s (%u peers, %u direct links)"ZT_EOL_S, - n->first.toString().c_str(), - n->second->supernode ? 'S' : 'N', - (status.online ? "ONLINE" : "OFFLINE"), - status.knownPeers, - status.directlyConnectedPeers); + if (status.initialized) { + printf("%s %c %s (%u peers, %u direct links)"ZT_EOL_S, + n->first.toString().c_str(), + n->second->supernode ? 'S' : 'N', + (status.online ? "ONLINE" : "OFFLINE"), + status.knownPeers, + status.directlyConnectedPeers); + } else printf("%s ? INITIALIZING (0 peers, 0 direct links)"ZT_EOL_S,n->first.toString().c_str()); } } @@ -571,6 +573,8 @@ static void doUnicast(const std::vector &cmd) } } } + + printf("---------- sent %u, received %u"ZT_EOL_S,(unsigned int)sentPairs.size(),(unsigned int)receivedPairs.size()); } int main(int argc,char **argv)