diff options
-rwxr-xr-x | .gitignore | 1 | ||||
-rw-r--r-- | make-freebsd.mk | 12 | ||||
-rw-r--r-- | make-linux.mk | 12 | ||||
-rw-r--r-- | make-mac.mk | 4 | ||||
-rw-r--r-- | netcon/NetconEthernetTap.cpp | 4 | ||||
-rw-r--r-- | netcon/NetconEthernetTap.hpp | 4 | ||||
-rw-r--r-- | netcon/README.md | 34 | ||||
-rw-r--r-- | node/Utils.cpp | 46 | ||||
-rw-r--r-- | objects.mk | 3 | ||||
-rw-r--r-- | one.cpp | 2 | ||||
-rw-r--r-- | service/OneService.cpp | 23 |
11 files changed, 77 insertions, 68 deletions
@@ -54,6 +54,7 @@ Thumbs.db *.rpm *.autosave *.tmp +.depend node_modules cluster-geo/cluster-geo/config.js cluster-geo/cluster-geo/cache.* diff --git a/make-freebsd.mk b/make-freebsd.mk index 022540d2..7148896e 100644 --- a/make-freebsd.mk +++ b/make-freebsd.mk @@ -6,21 +6,21 @@ DEFS= LIBS= include objects.mk -OBJS+=osdep/BSDEthernetTap.o +OBJS+=osdep/BSDEthernetTap.o # "make official" is a shortcut for this ifeq ($(ZT_OFFICIAL_RELEASE),1) - DEFS+=-DZT_OFFICIAL_RELEASE + DEFS+=-DZT_OFFICIAL_RELEASE endif # Build with ZT_ENABLE_CLUSTER=1 to build with cluster support ifeq ($(ZT_ENABLE_CLUSTER),1) - DEFS+=-DZT_ENABLE_CLUSTER + DEFS+=-DZT_ENABLE_CLUSTER endif # "make debug" is a shortcut for this ifeq ($(ZT_DEBUG),1) - DEFS+=-DZT_TRACE + DEFS+=-DZT_TRACE CFLAGS+=-Wall -g -pthread $(INCLUDES) $(DEFS) LDFLAGS+= STRIP=echo @@ -38,8 +38,8 @@ CXXFLAGS+=$(CFLAGS) -fno-rtti all: one -one: $(OBJS) one.o - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(OBJS) one.o $(LIBS) +one: $(OBJS) service/OneService.o one.o + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(OBJS) service/OneService.o one.o $(LIBS) $(STRIP) zerotier-one ln -sf zerotier-one zerotier-idtool ln -sf zerotier-one zerotier-cli diff --git a/make-linux.mk b/make-linux.mk index 0ae6c367..47a860bc 100644 --- a/make-linux.mk +++ b/make-linux.mk @@ -28,13 +28,11 @@ endif #UNAME_M=$(shell $(CC) -dumpmachine | cut -d '-' -f 1) -INCLUDES=-Iext/lwip/src/include -Iext/lwip/src/include/ipv4 -Iext/lwip/src/include/ipv6 -DEFS=-DZT_ENABLE_NETCON -#CXXFLAGS+=-Wc++11-compat-deprecated-writable-strings -Wformat +INCLUDES?= +DEFS?= LDLIBS?= include objects.mk -OBJS+=osdep/LinuxEthernetTap.o netcon/NetconEthernetTap.o # "make official" is a shortcut for this ifeq ($(ZT_OFFICIAL_RELEASE),1) @@ -91,8 +89,8 @@ endif all: one -one: $(OBJS) one.o - $(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(OBJS) one.o $(LDLIBS) +one: $(OBJS) service/OneService.o one.o osdep/LinuxEthernetTap.o + $(CXX) $(CXXFLAGS) $(LDFLAGS) -o zerotier-one $(OBJS) service/OneService.o one.o osdep/LinuxEthernetTap.o $(LDLIBS) $(STRIP) zerotier-one ln -sf zerotier-one zerotier-idtool ln -sf zerotier-one zerotier-cli @@ -133,7 +131,7 @@ debug: FORCE make ZT_DEBUG=1 selftest official: FORCE - make -j 4 ZT_OFFICIAL_RELEASE=1 + make -j 4 ZT_OFFICIAL_RELEASE=1 one make ZT_OFFICIAL_RELEASE=1 installer FORCE: diff --git a/make-mac.mk b/make-mac.mk index 7c4ef907..ffaf822d 100644 --- a/make-mac.mk +++ b/make-mac.mk @@ -71,8 +71,8 @@ CXXFLAGS=$(CFLAGS) -fno-rtti all: one -one: $(OBJS) one.o - $(CXX) $(CXXFLAGS) -o zerotier-one $(OBJS) one.o $(LIBS) +one: $(OBJS) service/OneService.o one.o + $(CXX) $(CXXFLAGS) -o zerotier-one $(OBJS) service/OneService.o one.o $(LIBS) $(STRIP) zerotier-one ln -sf zerotier-one zerotier-idtool ln -sf zerotier-one zerotier-cli diff --git a/netcon/NetconEthernetTap.cpp b/netcon/NetconEthernetTap.cpp index 3f772883..f33e7ffa 100644 --- a/netcon/NetconEthernetTap.cpp +++ b/netcon/NetconEthernetTap.cpp @@ -25,8 +25,6 @@ * LLC. Start here: http://www.zerotier.com/ */ -#ifdef ZT_ENABLE_NETCON - #include <algorithm> #include <utility> #include <dlfcn.h> @@ -1551,5 +1549,3 @@ void NetconEthernetTap::handle_write(TcpConnection *conn) } } // namespace ZeroTier - -#endif // ZT_ENABLE_NETCON diff --git a/netcon/NetconEthernetTap.hpp b/netcon/NetconEthernetTap.hpp index dd51a19d..f6fdb6e1 100644 --- a/netcon/NetconEthernetTap.hpp +++ b/netcon/NetconEthernetTap.hpp @@ -28,8 +28,6 @@ #ifndef ZT_NETCONETHERNETTAP_HPP #define ZT_NETCONETHERNETTAP_HPP -#ifdef ZT_ENABLE_NETCON - #include <stdio.h> #include <stdlib.h> @@ -182,6 +180,4 @@ private: } // namespace ZeroTier -#endif // ZT_ENABLE_NETCON - #endif diff --git a/netcon/README.md b/netcon/README.md index 91e69287..e20d8a92 100644 --- a/netcon/README.md +++ b/netcon/README.md @@ -3,15 +3,17 @@ Network Containers (beta) ZeroTier Network Containers offers a microkernel-like networking paradigm for containerized applications and application-specific virtual networking. -Network Containers couples the ZeroTier core Ethernet virtualization engine with a user-space TCP/IP stack and a library that intercepts calls to the Posix network API. Our intercept library implements full binary compatibility with the standard network API, permitting servers and applications to be used without modification or recompilation. - -It can be used to run services on virtual networks without requiring the creation of kernel-mode virtual network ports or modification of system network settings and without special privileges. It's ideal for containerized microservices that are designed exclusively for use on an isolated virtual network and that are to be deployed on commodity container hosting infrastructure. With Network Containers such services can be deployed without special permissions and connected to arbitrary virtual networks without configuration changes to the host node. +Network Containers couples the ZeroTier core Ethernet virtualization engine with a user-space TCP/IP stack and a library that intercepts calls to the Posix network API. Our intercept library implements full binary compatibility with the standard network API, permitting servers and applications to be used without modification or recompilation. It can be used to run services on virtual networks without elevated privileges, special configuration of the physical host, kernel support, or any other application specific configuration. Network Containers is ideal for use with [Docker](http://http://www.docker.com), [LXC](https://linuxcontainers.org), or [Rkt](https://coreos.com/rkt/docs/latest/), allowing connectivity to a virtual network to be built into and deployed with containers without host awareness or configuration. It can also be used without containers to network-containerize applications on an ordinary VM or bare metal host. It works entirely at the library/application level and requires no special kernel extensions. -Our long term goal with network containers is to facilitate the total commoditization of the container host by allowing virtual networking without elevated privileges or host configuration. We think this will help ease the path toward commodity multi-tenant container hosting and total application portability across hosts, data centers, and cloud providers. +Tighter Docker integration using Docker's *libnetwork* API is planned for the future, allowing use with unmodified container images. In the end we plan to support two complimentary deployment scenarios with Docker: intra-container deployment without host involvement, and host deployment without container modification. The former is useful when building your own containers, while the latter is useful when using unmodified containers from Docker Hub. + +Our long term goal is to allow total commoditization of the container host by providing fully independent network virtualization. We think this will help ease the path toward commodity multi-tenant container hosting and total application portability across hosts, data centers, and cloud providers. + +[More discussion can be found in our original blog announcement.](https://www.zerotier.com/blog/?p=490) -Network Containers are currently in **beta** and are suitable for testing, experimentation, and prototyping. There are still some issues with compatibility with some applications, as documented in the compatibility matrix below. There's also some remaining work to be done on performance and overall stability before this will be ready for production use. +Network Containers is currently in **beta** and is suitable for testing, experimentation, and prototyping. There are still some issues with compatibility with some applications, as documented in the compatibility matrix below. There's also some remaining work to be done on performance and overall stability before this will be ready for production use. # Limitations and Compatibility @@ -33,12 +35,14 @@ It is *likely* to work with other things but there are no guarantees. UDP, ICMP/ # Building Network Containers -Network Containers are currently only for Linux. To build the network container host and intercept library, from the base of the ZeroTier One tree type: +Network Containers are currently only for Linux. To build the network container host, IP stack, and intercept library, from the base of the ZeroTier One tree run: make netcon make install-intercept -This will build a binary called *zerotier-netcon-service* and a library called *libzerotierintercept.so*. The former is the same as a regular ZeroTier One build except instead of creating virtual network ports using Linux's */dev/net/tun* interface, it instead creates instances of a user-space TCP/IP stack for each virtual network and provides RPC access to this stack via a Unix domain socket called */tmp/.ztnc_##NETWORK_ID##*. The latter is a library that can be loaded with the Linux *LD\_PRELOAD* environment variable or by placement into */etc/ld.so.preload* on a Linux system or container. +This will build a binary called *zerotier-netcon-service* and a library called *libzerotierintercept.so*. It will also build the IP stack as *netcon/liblwip.so*. + +The *zerotier-netcon-service* binary is almost the same as a regular ZeroTier One build except instead of creating virtual network ports using Linux's */dev/net/tun* interface, it creates instances of a user-space TCP/IP stack for each virtual network and provides RPC access to this stack via a Unix domain socket called */tmp/.ztnc_##NETWORK_ID##*. The latter is a library that can be loaded with the Linux *LD\_PRELOAD* environment variable or by placement into */etc/ld.so.preload* on a Linux system or container. The intercept library does nothing unless the *ZT\_NC\_NWID* environment variable is set. If on program launch (or fork) it detects the presence of this environment variable, it will attempt to connect to a running *zerotier-netcon-service* at the aforementioned Unix domain socket location and will intercept calls to the Posix sockets API and redirect network traffic through the virtual network. @@ -48,9 +52,10 @@ Unlike *zerotier-one*, *zerotier-netcon-service* does not need to be run with ro You don't need Docker or any other container engine to try Network Containers. A simple test can be performed in user space in your own home directory. -First, build the netcon service and intercept library as describe above. Then create a directory to act as a temporary ZeroTier home for your test netcon service instance. +First, build the netcon service and intercept library as describe above. Then create a directory to act as a temporary ZeroTier home for your test netcon service instance. You'll need to move the liblwip.so binary that was built with *make netcon* into there, since the service must be able to find it there and load it. mkdir /tmp/netcon-test-home + cp -f ./netcon/liblwip.so /tmp/netcon-test-home Now you can run the service (no sudo needed): @@ -103,6 +108,19 @@ Going to port 80 on your machine won't work. Httpd is listening, but only inside Replace *NETCON.INSTANCE.IP* with the IP address that *zerotier-netcon-service* was assigned on the virtual network. (This is the same IP you pinged in your first test.) If everything works, you should get back a copy of ZeroTier One's main README.md file. +# Installing in a Docker Container (or any other container engine) + +If it's not immediately obvious, installation into a Docker container is easy. Just install *zerotier-netcon-service*, *libzerotierintercept.so*, and *liblwip.so* into the container at an appropriate location. We suggest putting it all in */var/lib/zerotier-one* since this is the default ZeroTier home and will eliminate the need to supply a path to any of ZeroTier's services or utilities. Then, in your Docker container entry point script launch the service with *-d* to run it in the background, set the appropriate environment variables as described above, and launch your container's main application. + +The only bit of complexity is configuring which virtual network to join. ZeroTier's service automatically joins networks that have *.conf* files in *ZTHOME/networks.d* even if the *.conf* file is empty. So one way of doing this very easily is to add the following commands to your Dockerfile or container entry point script: + + mkdir -p /var/lib/zerotier-one/networks.d + touch /var/lib/zerotier-one/networks.d/8056c2e21c000001.conf + +Replace 8056c2e21c000001 with the network ID of the network you want your container to automaticlaly join. + +Now your container will automatically join the specified network on startup. Authorizing the container on a private network still requires a manual authorization step either via the ZeroTier Central web UI or the API. We're working on some ideas to automate this via bearer token auth or similar since doing this manually or with scripts for large deployments is tedious. We'll have something in this area by the time Network Containers itself is ready to be pronounced no-longer-beta. + # Unit Tests Each unit test will temporarily copy all required ZeroTier binaries into its local directory, then build the *netcon_dockerfile* and *monitor_dockerfile*. Once built, each container will be run and perform tests and monitoring specified in *netcon_entrypoint.sh* and *monitor_entrypoint.sh* diff --git a/node/Utils.cpp b/node/Utils.cpp index 10146e6c..7361c2a5 100644 --- a/node/Utils.cpp +++ b/node/Utils.cpp @@ -29,6 +29,7 @@ #include <string.h> #include <stdlib.h> #include <stdarg.h> +#include <time.h> #include <sys/stat.h> #include "Constants.hpp" @@ -149,44 +150,50 @@ unsigned int Utils::unhex(const char *hex,unsigned int maxlen,void *buf,unsigned void Utils::getSecureRandom(void *buf,unsigned int bytes) { -#ifdef __WINDOWS__ - - static HCRYPTPROV cryptProvider = NULL; static Mutex globalLock; static Salsa20 s20; + static bool s20Initialized = false; Mutex::Lock _l(globalLock); + /* Just for posterity we Salsa20 encrypt the result of whatever system + * CSPRNG we use. There have been several bugs at the OS or OS distribution + * level in the past that resulted in systematically weak or predictable + * keys due to random seeding problems. This mitigates that by grabbing + * a bit of extra entropy and further randomizing the result, and comes + * at almost no cost and with no real downside if the random source is + * good. */ + if (!s20Initialized) { + s20Initialized = true; + uint64_t s20Key[4]; + s20Key[0] = (uint64_t)time(0); // system clock + s20Key[1] = (uint64_t)buf; // address of buf + s20Key[2] = (uint64_t)s20Key; // address of s20Key[] + s20Key[3] = (uint64_t)&s20; // address of s20 + s20.init(s20Key,256,s20Key); + } + +#ifdef __WINDOWS__ + + static HCRYPTPROV cryptProvider = NULL; + if (cryptProvider == NULL) { if (!CryptAcquireContextA(&cryptProvider,NULL,NULL,PROV_RSA_FULL,CRYPT_VERIFYCONTEXT|CRYPT_SILENT)) { fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() unable to obtain WinCrypt context!\r\n"); exit(1); return; } - char s20key[32]; - if (!CryptGenRandom(cryptProvider,(DWORD)sizeof(s20key),(BYTE *)s20key)) { - fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() CryptGenRandom failed!\r\n"); - exit(1); - } - s20.init(s20key,256,s20key); } - if (!CryptGenRandom(cryptProvider,(DWORD)bytes,(BYTE *)buf)) { fprintf(stderr,"FATAL ERROR: Utils::getSecureRandom() CryptGenRandom failed!\r\n"); exit(1); } - s20.encrypt12(buf,buf,bytes); #else // not __WINDOWS__ -#ifdef __UNIX_LIKE__ - static char randomBuf[131072]; static unsigned int randomPtr = sizeof(randomBuf); static int devURandomFd = -1; - static Mutex globalLock; - - Mutex::Lock _l(globalLock); if (devURandomFd <= 0) { devURandomFd = ::open("/dev/urandom",O_RDONLY); @@ -215,12 +222,9 @@ void Utils::getSecureRandom(void *buf,unsigned int bytes) ((char *)buf)[i] = randomBuf[randomPtr++]; } -#else // not __UNIX_LIKE__ +#endif // __WINDOWS__ or not -#error No getSecureRandom() implementation available. - -#endif // __UNIX_LIKE__ -#endif // __WINDOWS__ + s20.encrypt12(buf,buf,bytes); } std::vector<std::string> Utils::split(const char *s,const char *const sep,const char *esc,const char *quot) @@ -29,5 +29,4 @@ OBJS=\ osdep/Http.o \ osdep/OSUtils.o \ service/ClusterGeoIpService.o \ - service/ControlPlane.o \ - service/OneService.o + service/ControlPlane.o @@ -1096,10 +1096,12 @@ int main(int argc,char **argv) } #ifdef __UNIX_LIKE__ +#ifndef ZT_ONE_NO_ROOT_CHECK if ((!skipRootCheck)&&(getuid() != 0)) { fprintf(stderr,"%s: must be run as root (uid 0)"ZT_EOL_S,argv[0]); return 1; } +#endif // !ZT_ONE_NO_ROOT_CHECK if (runAsDaemon) { long p = (long)fork(); if (p < 0) { diff --git a/service/OneService.cpp b/service/OneService.cpp index c3204b5d..ed60ed2d 100644 --- a/service/OneService.cpp +++ b/service/OneService.cpp @@ -92,37 +92,32 @@ class SqliteNetworkController; #endif // Include the right tap device driver for this platform -- add new platforms here -#ifdef ZT_ENABLE_NETCON +#ifdef ZT_SERVICE_NETCON +// In network containers builds, use the virtual netcon endpoint instead of a tun/tap port driver #include "../netcon/NetconEthernetTap.hpp" namespace ZeroTier { typedef NetconEthernetTap EthernetTap; } -#else -#ifdef __APPLE__ +#else // not ZT_SERVICE_NETCON so pick a tap driver +#ifdef __APPLE__ #include "../osdep/OSXEthernetTap.hpp" namespace ZeroTier { typedef OSXEthernetTap EthernetTap; } - -#endif +#endif // __APPLE__ #ifdef __LINUX__ - #include "../osdep/LinuxEthernetTap.hpp" namespace ZeroTier { typedef LinuxEthernetTap EthernetTap; } - -#endif +#endif // __LINUX__ #ifdef __WINDOWS__ - #include "../osdep/WindowsEthernetTap.hpp" namespace ZeroTier { typedef WindowsEthernetTap EthernetTap; } - -#endif +#endif // __WINDOWS__ #ifdef __FreeBSD__ - #include "../osdep/BSDEthernetTap.hpp" namespace ZeroTier { typedef BSDEthernetTap EthernetTap; } +#endif // __FreeBSD__ -#endif -#endif // ZT_ENABLE_NETCON +#endif // ZT_SERVICE_NETCON // Sanity limits for HTTP #define ZT_MAX_HTTP_MESSAGE_SIZE (1024 * 1024 * 64) |