Improved proxy server controls

This commit is contained in:
Joseph Henry
2016-08-17 12:41:59 -07:00
parent 15985ebcd6
commit 6353d9b060
5 changed files with 145 additions and 81 deletions

View File

@@ -85,7 +85,7 @@ extern char *debug_logfile;
// NOTE: Each platform specific exposed API will be implemented in terms of zts_* // NOTE: Each platform specific exposed API will be implemented in terms of zts_*
// SOCKS5 Proxy Controls // SOCKS5 Proxy Controls
int zts_start_proxy_server(const char *nwid, struct sockaddr_storage *addr); int zts_start_proxy_server(const char *homepath, const char * nwid, struct sockaddr_storage * addr);
int zts_stop_proxy_server(const char *nwid); int zts_stop_proxy_server(const char *nwid);
int zts_get_proxy_server_address(const char * nwid, struct sockaddr_storage *addr); int zts_get_proxy_server_address(const char * nwid, struct sockaddr_storage *addr);
// ZT Service Controls // ZT Service Controls

View File

@@ -129,16 +129,10 @@ NetconEthernetTap::NetconEthernetTap(
_enabled(true), _enabled(true),
_run(true) _run(true)
{ {
sockstate = -1;
char sockPath[4096],lwipPath[4096]; char sockPath[4096],lwipPath[4096];
Utils::snprintf(sockPath,sizeof(sockPath),"%s%snc_%.16llx",homePath,ZT_PATH_SEPARATOR_S,_nwid,ZT_PATH_SEPARATOR_S,(unsigned long long)nwid); Utils::snprintf(sockPath,sizeof(sockPath),"%s%snc_%.16llx",homePath,ZT_PATH_SEPARATOR_S,_nwid,ZT_PATH_SEPARATOR_S,(unsigned long long)nwid);
_dev = sockPath; // in SDK mode, set device to be just the network ID _dev = sockPath; // in SDK mode, set device to be just the network ID
// Start SOCKS5 Proxy server
// For use when traditional syscall hooking isn't available (ex. some APIs on iOS and Android)
#if defined(USE_SOCKS_PROXY)
StartProxy(sockPath, _homePath.c_str(), _nwid);
#endif
Utils::snprintf(lwipPath,sizeof(lwipPath),"%s%sliblwip.so",homePath,ZT_PATH_SEPARATOR_S); Utils::snprintf(lwipPath,sizeof(lwipPath),"%s%sliblwip.so",homePath,ZT_PATH_SEPARATOR_S);
lwipstack = new LWIPStack(lwipPath); lwipstack = new LWIPStack(lwipPath);
@@ -1383,7 +1377,6 @@ void NetconEthernetTap::handleWrite(Connection *conn)
if(buf_remaining) if(buf_remaining)
memmove(&conn->txbuf, (conn->txbuf+udp_trans_len), buf_remaining); memmove(&conn->txbuf, (conn->txbuf+udp_trans_len), buf_remaining);
conn->txsz -= udp_trans_len; conn->txsz -= udp_trans_len;
int max = conn->type == SOCK_STREAM ? DEFAULT_TCP_TX_BUF_SZ : DEFAULT_UDP_TX_BUF_SZ;
#if DEBUG_LEVEL >= MSG_TRANSFER #if DEBUG_LEVEL >= MSG_TRANSFER
struct sockaddr_in * addr_in2 = (struct sockaddr_in *)conn->peer_addr; struct sockaddr_in * addr_in2 = (struct sockaddr_in *)conn->peer_addr;

View File

@@ -155,7 +155,17 @@ namespace ZeroTier {
void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int); void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
void *_arg; void *_arg;
int proxyListenPort; // --- Proxy
struct sockaddr_storage proxyServerAddress;
int sockstate; // Use as flag to determine whether proxy has been started, TODO: Rename
int proxyListenSocket;
PhySocket *proxyListenPhySocket;
int startProxyServer(const char *homepath, uint64_t nwid, struct sockaddr_storage *addr);
int stopProxyServer();
int getProxyServerAddress(struct sockaddr_storage *addr);
int getProxyServerPort();
void phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable);
// --- end Proxy
private: private:
// LWIP callbacks // LWIP callbacks
@@ -462,15 +472,6 @@ namespace ZeroTier {
*/ */
void closeConnection(PhySocket *sock); void closeConnection(PhySocket *sock);
// --- Proxy
int sockstate;
int proxyListenSocket;
PhySocket *proxyListenPhySocket;
void StartProxy(const char *sockpath, const char *homepath, uint64_t nwid);
void phyOnFileDescriptorActivity(PhySocket *sock,void **uptr,bool readable,bool writable);
// --- end Proxy
ip_addr_t convert_ip(struct sockaddr_in * addr) ip_addr_t convert_ip(struct sockaddr_in * addr)
{ {
ip_addr_t conn_addr; ip_addr_t conn_addr;

View File

@@ -64,9 +64,52 @@ void dwr(int level, const char *fmt, ... );
namespace ZeroTier namespace ZeroTier
{ {
void NetconEthernetTap::StartProxy(const char *sockpath, const char *homepath, uint64_t nwid) int NetconEthernetTap::getProxyServerAddress(struct sockaddr_storage *addr) {
if(sockstate >= 0) {
addr = &proxyServerAddress;
return 0;
}
return -1;
}
int NetconEthernetTap::getProxyServerPort() {
struct sockaddr_in *in4;
in4 = (struct sockaddr_in *)&proxyServerAddress;
return in4->sin_port;
}
int NetconEthernetTap::stopProxyServer()
{ {
dwr(MSG_ERROR, "StartProxy()\n"); dwr(MSG_DEBUG, "stopProxyServer()");
if(proxyListenPhySocket) {
_phy.close(proxyListenPhySocket);
return 0;
}
dwr(MSG_ERROR, "stopProxyServer(): Invalid proxyListenPhySocket");
return -1;
}
int NetconEthernetTap::startProxyServer(const char *homepath, uint64_t nwid, struct sockaddr_storage *addr)
{
// Address of proxy server is determined in the following order:
// - Provided address in param: addr
// - If no address, assume 127.0.0.1:<networks.d/nwid.port>
// - If no port assignment file, 127.0.0.1:RANDOM_PORT
dwr(MSG_DEBUG, "startProxyServer()\n");
int portno = -1;
if(addr) {
dwr(MSG_DEBUG, "startProxyServer(): Using provided address");
// This address pointer may come from a different memory space and might be de-allocated, so we keep a copy
memcpy(&proxyServerAddress, addr, sizeof(struct sockaddr_storage));
struct sockaddr_in *in4 = (struct sockaddr_in *)&addr;
proxyListenPhySocket = _phy.tcpListen((const struct sockaddr*)&in4,(void *)this);
sockstate = SOCKS_OPEN;
dwr(MSG_DEBUG, "SOCKS5 proxy server address for <%.16llx> is: <%s> (sock=%p)\n", nwid, inet_ntoa(in4->sin_addr), /*ntohs(in4->sin_port), */(void*)&proxyListenPhySocket);
return 0;
}
else {
dwr(MSG_DEBUG, "startProxyServer(): No address provided. Checking port file.");
// Look for a port file for this network's proxy server instance // Look for a port file for this network's proxy server instance
char portFile[4096]; char portFile[4096];
Utils::snprintf(portFile,sizeof(portFile),"%s/networks.d/%.16llx.port",homepath,nwid); Utils::snprintf(portFile,sizeof(portFile),"%s/networks.d/%.16llx.port",homepath,nwid);
@@ -75,31 +118,31 @@ namespace ZeroTier
if(ZeroTier::OSUtils::fileExists(portFile,true)) if(ZeroTier::OSUtils::fileExists(portFile,true))
{ {
if(ZeroTier::OSUtils::readFile(portFile, portStr)) { if(ZeroTier::OSUtils::readFile(portFile, portStr)) {
proxyListenPort = atoi(portStr.c_str()); portno = atoi(portStr.c_str());
} }
} }
else else {
{
unsigned int randp = 0; unsigned int randp = 0;
Utils::getSecureRandom(&randp,sizeof(randp)); Utils::getSecureRandom(&randp,sizeof(randp));
proxyListenPort = 1000 + (randp % 1000); portno = 1000 + (randp % 1000);
dwr(MSG_DEBUG, "Proxy(): No port specified in networks.d/%.16llx.port, randomly picking port\n", nwid); dwr(MSG_DEBUG, "Proxy(): No port specified in networks.d/%.16llx.port, randomly picking port\n", nwid);
std::stringstream ss; std::stringstream ss;
ss << proxyListenPort; ss << portno;
portStr = ss.str(); portStr = ss.str();
if(!ZeroTier::OSUtils::writeFile(portFile, portStr)) { if(!ZeroTier::OSUtils::writeFile(portFile, portStr)) {
dwr(MSG_ERROR, "unable to write proxy port file: %s\n", portFile); dwr(MSG_ERROR, "unable to write proxy port file: %s\n", portFile);
} }
} }
struct sockaddr_in in4; struct sockaddr_in in4;
memset(&in4,0,sizeof(in4)); memset(&in4,0,sizeof(in4));
in4.sin_family = AF_INET; in4.sin_family = AF_INET;
in4.sin_addr.s_addr = Utils::hton((uint32_t)0x00000000); // right now we just listen for TCP @0.0.0.0 in4.sin_addr.s_addr = Utils::hton((uint32_t)0x00000000); // right now we just listen for TCP @0.0.0.0
in4.sin_port = Utils::hton((uint16_t)proxyListenPort); in4.sin_port = Utils::hton((uint16_t)portno);
proxyListenPhySocket = _phy.tcpListen((const struct sockaddr*)&in4,(void *)this); proxyListenPhySocket = _phy.tcpListen((const struct sockaddr*)&in4,(void *)this);
sockstate = SOCKS_OPEN; sockstate = SOCKS_OPEN;
dwr(MSG_DEBUG, "SOCKS5 proxy server address for <%.16llx> is: <0.0.0.0:%d> (sock=%p)\n", nwid, proxyListenPort, (void*)&proxyListenPhySocket); //dwr(MSG_DEBUG, "SOCKS5 proxy server address for <%.16llx> is: <%s:%d> (sock=%p)\n", nwid, , portno, (void*)&proxyListenPhySocket);
}
return 0;
} }
void ExtractAddress(int addr_type, unsigned char *buf, struct sockaddr_in * addr) void ExtractAddress(int addr_type, unsigned char *buf, struct sockaddr_in * addr)

View File

@@ -94,10 +94,49 @@ void dwr(int level, const char *fmt, ... );
#endif #endif
int zts_start_proxy_server(const char *homepath, const char * nwid, struct sockaddr_storage * addr) {
LOGV("zts_start_proxy_server\n");
dwr(MSG_DEBUG, "zts_start_proxy_server()");
uint64_t nwid_int = strtoull(nwid, NULL, 16);
ZeroTier::NetconEthernetTap * tap = zt1Service->getTaps()[nwid_int];
if(tap) {
if(tap->startProxyServer(homepath, nwid_int, addr) < 0) {
dwr(MSG_ERROR, "zts_start_proxy_server(%s): Problem while starting server.", nwid);
return -1;
}
}
dwr(MSG_ERROR, "zts_start_proxy_server(%s): Invalid tap. Possibly incorrect NWID", nwid);
return 0;
}
int zts_stop_proxy_server(const char *nwid) {
dwr(MSG_DEBUG, "zts_stop_proxy_server()");
uint64_t nwid_int = strtoull(nwid, NULL, 16);
ZeroTier::NetconEthernetTap * tap = zt1Service->getTaps()[nwid_int];
if(tap) {
if(tap->stopProxyServer() < 0) {
dwr(MSG_ERROR, "zts_stop_proxy_server(%s): Problem while stopping server.", nwid);
return -1;
}
}
dwr(MSG_ERROR, "zts_stop_proxy_server(%s): Invalid tap. Possibly incorrect NWID", nwid);
return 0;
}
int zts_get_proxy_server_address(const char * nwid, struct sockaddr_storage * addr) {
uint64_t nwid_int = strtoull(nwid, NULL, 16);
ZeroTier::NetconEthernetTap * tap = zt1Service->getTaps()[nwid_int];
if(tap) {
tap->getProxyServerAddress(addr);
return 0;
}
return -1;
}
// Basic ZT service controls // Basic ZT service controls
// Will also spin up a SOCKS5 proxy server if USE_SOCKS_PROXY is set
void zts_join_network(const char * nwid) { void zts_join_network(const char * nwid) {
LOGV("zts_join_network\n");
std::string confFile = zt1Service->givenHomePath() + "/networks.d/" + nwid + ".conf"; std::string confFile = zt1Service->givenHomePath() + "/networks.d/" + nwid + ".conf";
dwr(MSG_ERROR, "writing conf file = %s\n", confFile.c_str());
if(!ZeroTier::OSUtils::mkdir(netDir)) { if(!ZeroTier::OSUtils::mkdir(netDir)) {
dwr(MSG_ERROR, "unable to create %s\n", netDir.c_str()); dwr(MSG_ERROR, "unable to create %s\n", netDir.c_str());
} }
@@ -106,6 +145,15 @@ void zts_join_network(const char * nwid) {
} }
// Provide the API with the RPC information // Provide the API with the RPC information
zt_init_rpc(homeDir.c_str(), nwid); zt_init_rpc(homeDir.c_str(), nwid);
// SOCKS5 Proxy server
// Default is 127.0.0.1:RANDOM_PORT
LOGV("-----USE_SOCKS_PROXY ?\n");
#if defined(USE_SOCKS_PROXY)
LOGV("-----USE_SOCKS_PROXY!\\n");
zts_start_proxy_server(homeDir.c_str(), nwid, NULL); // NULL addr for default
#endif
} }
void zts_leave_network(const char * nwid) { zt1Service->leave(nwid); } void zts_leave_network(const char * nwid) { zt1Service->leave(nwid); }
bool zts_is_running() { return zt1Service->isRunning(); } bool zts_is_running() { return zt1Service->isRunning(); }
@@ -145,22 +193,6 @@ bool zts_is_relayed() {
return false; return false;
} }
int zts_start_proxy_server(const char * nwid, struct sockaddr_storage * addr) {
//uint64_t nwid_int = strtoull(nwid, NULL, 16);
//return zt1Service->getTaps()[nwid_int]->proxyListenPort;
return 0;
}
int zts_stop_proxy_server(const char * nwid) {
//uint64_t nwid_int = strtoull(nwid, NULL, 16);
//return zt1Service->getTaps()[nwid_int]->proxyListenPort;
return 0;
}
int zts_get_proxy_server_address(const char * nwid, struct sockaddr_storage * addr) {
//uint64_t nwid_int = strtoull(nwid, NULL, 16);
//zt1Service->getTaps()[nwid_int]->proxyListenPort;
return 0;
}
// Android JNI wrapper // Android JNI wrapper
// JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME // JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME
#if defined(__ANDROID__) #if defined(__ANDROID__)
@@ -284,6 +316,9 @@ int zts_get_proxy_server_address(const char * nwid, struct sockaddr_storage * ad
* Starts a new service instance * Starts a new service instance
*/ */
#if defined(__ANDROID__) #if defined(__ANDROID__)
/* NOTE: Since on Android devices the sdcard is formatted as fat32, we can't use just any
location to set up the RPC unix domain socket. Rather we must use the application's specific
data directory given by getApplicationContext().getFilesDir() */
JNIEXPORT int JNICALL Java_ZeroTier_SDK_zt_1start_1service(JNIEnv *env, jobject thisObj, jstring path) { JNIEXPORT int JNICALL Java_ZeroTier_SDK_zt_1start_1service(JNIEnv *env, jobject thisObj, jstring path) {
if(path) if(path)
homeDir = env->GetStringUTFChars(path, NULL); homeDir = env->GetStringUTFChars(path, NULL);
@@ -314,14 +349,6 @@ int zts_get_proxy_server_address(const char * nwid, struct sockaddr_storage * ad
#endif #endif
#endif #endif
#if defined(__ANDROID__)
/* NOTE: Since on Android devices the sdcard is formatted as fat32, we can't use this
location to set up the RPC unix domain socket. Rather we must use the application's
specific data directory given by getApplicationContext().getFilesDir() */
//rpcDir = homeDir; // Take given homeDir as rpcDir
//homeDir = "/sdcard/zerotier"; // Use fat32-formatted sdcard for writing network conf & supporting files
#endif
#if defined(__APPLE__) && !defined(__IOS__) #if defined(__APPLE__) && !defined(__IOS__)
homeDir = givenHomeDir; homeDir = givenHomeDir;
localHomeDir = givenHomeDir; // Used for RPC and *can* differ from homeDir on some platforms localHomeDir = givenHomeDir; // Used for RPC and *can* differ from homeDir on some platforms