2015-11-20 01:08:38 -08:00
ZeroTier Network Containers
2015-10-27 17:38:56 -07:00
======
### Functional Overview:
2015-11-20 01:08:38 -08:00
This system exists as a dynamically-linked library, and a service/IP-stack built into ZeroTier
2015-10-27 17:38:56 -07:00
2015-11-23 05:59:05 -08:00
If you care about the technicals,
2015-10-27 17:38:56 -07:00
The intercept is compiled as a shared library and installed in some user-accessible directory. When you want to intercept
a user application you dynamically link the shared library to the application during runtime. When the application starts, the
intercept's global constructor is called which sets up a hidden pipe which is used to communicate remote procedure calls (RPC) to the host Netcon service running in the background.
2015-11-23 05:59:05 -08:00
When an RPC for a socket() is received by the Netcon service from the intercepted application, the Netcon service will ask the lwIP stack for a new PCB structure (used to represent a connection), if the system permits its allocation, it will be passed to Netcon where a PCB/socket table entry will be created. The table is used for mapping [callbacks from lwIP] and [RPCs from the intercept] to the correct connections.
2015-10-27 17:38:56 -07:00
Upon the first call to a intercept-overriden system call, a Unix-domain socket is opened between the Netcon service and the application's intercept. This socket provides us the ability to pass file descriptors of newly-created socketpairs to the intercept (used as the read/write buffer). More specifically, after the socketpair creation, one end is kept in a table entry in Netcon and one end is sent to the intercept.
### Building from Source (and Installing)
2015-11-23 06:07:48 -08:00
Build zerotier-intercept library:
2015-10-27 17:38:56 -07:00
2015-11-23 05:59:05 -08:00
make -f make-intercept.mk
2015-10-27 17:38:56 -07:00
Install:
2015-11-23 06:07:48 -08:00
make -f make-intercept.mk install
2015-10-27 17:38:56 -07:00
2015-11-23 05:59:05 -08:00
Build LWIP library:
2015-10-27 17:38:56 -07:00
2015-11-23 05:59:05 -08:00
make -f make-liblwip.mk
2015-10-27 17:38:56 -07:00
2015-11-23 06:07:48 -08:00
Run automated tests (from netcon/docker-test/ directory):
2015-10-27 17:38:56 -07:00
2015-11-23 06:07:48 -08:00
./build.sh
./test.sh
2015-10-27 17:38:56 -07:00
2015-11-23 05:59:05 -08:00
### Running
2015-10-27 17:38:56 -07:00
2015-11-23 05:59:05 -08:00
To intercept a specific application (requires an already running instance of Zerotier-One with Network Containers enabled):
2015-10-27 17:38:56 -07:00
2015-11-23 05:59:05 -08:00
zerotier-intercept my_app
2015-10-27 17:38:56 -07:00
### Compatibility
2015-10-21 16:56:39 -07:00
Network Containers have been tested with the following:
2015-11-23 05:59:05 -08:00
sshd [ WORKS as of 20151112]
2015-11-12 17:15:44 -08:00
ssh [ WORKS as of 20151112]
2015-11-12 16:57:45 -08:00
sftp [ WORKS as of 20151022]
curl [ WORKS as of 20151021]
apache (debug mode) [ WORKS as of 20150810]
2015-11-23 05:59:05 -08:00
apache (prefork MPM) [ WORKS as of 20151123] (2.4.6-31.x86-64 on Centos 7), (2.4.16-1.x84-64 on F22), (2.4.17-3.x86-64 on F22)
nginx [ WORKS as of 20151123] Broken on Centos 7, unreliable on Fedora 23
nodejs [ WORKS as of 20151123]
2015-11-12 16:57:45 -08:00
java [ WORKS as of 20151010]
MongoDB [ WORKS as of 20151028]
2015-11-23 05:59:05 -08:00
Redis-server [ WORKS as of 20151123]
2015-10-21 16:56:39 -07:00
2015-11-23 05:59:05 -08:00
Future:
2015-10-21 16:56:39 -07:00
GET many different files via HTTP (web stress)
LARGE continuous transfer (e.g. /dev/urandom all night)
Open and close many TCP connections constantly
Simulate packet loss (can be done with iptables)
Many parallel TCP transfers
Multithreaded software (e.g. apache in thread mode)
2015-11-23 05:59:05 -08:00
UDP support
2015-10-21 16:56:39 -07:00
2015-10-21 16:27:17 -07:00
2015-10-27 17:38:56 -07:00
### Extended Version Notes
2015-10-28 14:37:46 -07:00
20151028 Added MongoDB support:
- Added logic (RPC_MAP_REQ) to check whether a given AF_LOCAL socket is mapped to anything
inside the service instance.
2015-10-27 17:41:51 -07:00
20151027 Added Redis-server support:
- Added extra logic to detect socket re-issuing and consequent service-side double mapping.
Redis appears to try to set its initial listen socket to IPV6 only, this currently fails. As
a result, Redis will close the socket and re-open it. The server will now test for closures
during mapping and will eliminate any mappings to broken pipes.
20151021 Added Node.js support:
- syscall(long number, ...) is now intercepted and re-directs the __NR_accept4 call to our intercepted accept4() function
- accept() now returns -EAGAIN in the case that we cannot read a signal byte from the descriptor linked to the service. This
is because the uv__server_io() function in libuv used by Node.js looks for this return value upon failure, without it we
were observing an innfinite loop in the I/O polling code in libuv.
- accept4() now correctly sets given flags for descriptor returned by accept()
- setsockopt() was modified to return success on any call with the following conditions:
level == IPPROTO_TCP || (level == SOL_SOCKET & & option_name == SO_KEEPALIVE)
This might be unnecessary or might need a better workaround
- Careful attention should be given to how arguments are passed in the intercepted syscall() function, this differs for
32/64-bit systems
2015-10-27 17:12:32 -07:00
2015-11-04 14:45:26 -08:00