Improved proxy server controls
This commit is contained in:
@@ -85,7 +85,7 @@ extern char *debug_logfile;
|
||||
|
||||
// NOTE: Each platform specific exposed API will be implemented in terms of zts_*
|
||||
// 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_get_proxy_server_address(const char * nwid, struct sockaddr_storage *addr);
|
||||
// ZT Service Controls
|
||||
|
||||
@@ -129,16 +129,10 @@ NetconEthernetTap::NetconEthernetTap(
|
||||
_enabled(true),
|
||||
_run(true)
|
||||
{
|
||||
sockstate = -1;
|
||||
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);
|
||||
_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);
|
||||
|
||||
lwipstack = new LWIPStack(lwipPath);
|
||||
@@ -1383,7 +1377,6 @@ void NetconEthernetTap::handleWrite(Connection *conn)
|
||||
if(buf_remaining)
|
||||
memmove(&conn->txbuf, (conn->txbuf+udp_trans_len), buf_remaining);
|
||||
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
|
||||
struct sockaddr_in * addr_in2 = (struct sockaddr_in *)conn->peer_addr;
|
||||
|
||||
@@ -151,11 +151,21 @@ namespace ZeroTier {
|
||||
throw();
|
||||
|
||||
LWIPStack *lwipstack;
|
||||
uint64_t _nwid;
|
||||
void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
|
||||
void *_arg;
|
||||
uint64_t _nwid;
|
||||
void (*_handler)(void *,uint64_t,const MAC &,const MAC &,unsigned int,unsigned int,const void *,unsigned int);
|
||||
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:
|
||||
// LWIP callbacks
|
||||
@@ -462,15 +472,6 @@ namespace ZeroTier {
|
||||
*/
|
||||
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 conn_addr;
|
||||
|
||||
@@ -64,42 +64,85 @@ void dwr(int level, const char *fmt, ... );
|
||||
|
||||
namespace ZeroTier
|
||||
{
|
||||
void NetconEthernetTap::StartProxy(const char *sockpath, const char *homepath, uint64_t nwid)
|
||||
{
|
||||
dwr(MSG_ERROR, "StartProxy()\n");
|
||||
// Look for a port file for this network's proxy server instance
|
||||
char portFile[4096];
|
||||
Utils::snprintf(portFile,sizeof(portFile),"%s/networks.d/%.16llx.port",homepath,nwid);
|
||||
std::string portStr;
|
||||
printf("Proxy(): Reading port from: %s\n", portFile);
|
||||
if(ZeroTier::OSUtils::fileExists(portFile,true))
|
||||
{
|
||||
if(ZeroTier::OSUtils::readFile(portFile, portStr)) {
|
||||
proxyListenPort = atoi(portStr.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
unsigned int randp = 0;
|
||||
Utils::getSecureRandom(&randp,sizeof(randp));
|
||||
proxyListenPort = 1000 + (randp % 1000);
|
||||
dwr(MSG_DEBUG, "Proxy(): No port specified in networks.d/%.16llx.port, randomly picking port\n", nwid);
|
||||
std::stringstream ss;
|
||||
ss << proxyListenPort;
|
||||
portStr = ss.str();
|
||||
if(!ZeroTier::OSUtils::writeFile(portFile, portStr)) {
|
||||
dwr(MSG_ERROR, "unable to write proxy port file: %s\n", portFile);
|
||||
}
|
||||
int NetconEthernetTap::getProxyServerAddress(struct sockaddr_storage *addr) {
|
||||
if(sockstate >= 0) {
|
||||
addr = &proxyServerAddress;
|
||||
return 0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sockaddr_in in4;
|
||||
memset(&in4,0,sizeof(in4));
|
||||
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_port = Utils::hton((uint16_t)proxyListenPort);
|
||||
proxyListenPhySocket = _phy.tcpListen((const struct sockaddr*)&in4,(void *)this);
|
||||
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);
|
||||
int NetconEthernetTap::getProxyServerPort() {
|
||||
struct sockaddr_in *in4;
|
||||
in4 = (struct sockaddr_in *)&proxyServerAddress;
|
||||
return in4->sin_port;
|
||||
}
|
||||
|
||||
int NetconEthernetTap::stopProxyServer()
|
||||
{
|
||||
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
|
||||
char portFile[4096];
|
||||
Utils::snprintf(portFile,sizeof(portFile),"%s/networks.d/%.16llx.port",homepath,nwid);
|
||||
std::string portStr;
|
||||
printf("Proxy(): Reading port from: %s\n", portFile);
|
||||
if(ZeroTier::OSUtils::fileExists(portFile,true))
|
||||
{
|
||||
if(ZeroTier::OSUtils::readFile(portFile, portStr)) {
|
||||
portno = atoi(portStr.c_str());
|
||||
}
|
||||
}
|
||||
else {
|
||||
unsigned int randp = 0;
|
||||
Utils::getSecureRandom(&randp,sizeof(randp));
|
||||
portno = 1000 + (randp % 1000);
|
||||
dwr(MSG_DEBUG, "Proxy(): No port specified in networks.d/%.16llx.port, randomly picking port\n", nwid);
|
||||
std::stringstream ss;
|
||||
ss << portno;
|
||||
portStr = ss.str();
|
||||
if(!ZeroTier::OSUtils::writeFile(portFile, portStr)) {
|
||||
dwr(MSG_ERROR, "unable to write proxy port file: %s\n", portFile);
|
||||
}
|
||||
}
|
||||
struct sockaddr_in in4;
|
||||
memset(&in4,0,sizeof(in4));
|
||||
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_port = Utils::hton((uint16_t)portno);
|
||||
proxyListenPhySocket = _phy.tcpListen((const struct sockaddr*)&in4,(void *)this);
|
||||
sockstate = SOCKS_OPEN;
|
||||
//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)
|
||||
|
||||
@@ -94,10 +94,49 @@ void dwr(int level, const char *fmt, ... );
|
||||
#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
|
||||
// Will also spin up a SOCKS5 proxy server if USE_SOCKS_PROXY is set
|
||||
void zts_join_network(const char * nwid) {
|
||||
LOGV("zts_join_network\n");
|
||||
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)) {
|
||||
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
|
||||
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); }
|
||||
bool zts_is_running() { return zt1Service->isRunning(); }
|
||||
@@ -145,22 +193,6 @@ bool zts_is_relayed() {
|
||||
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
|
||||
// JNI naming convention: Java_PACKAGENAME_CLASSNAME_METHODNAME
|
||||
#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
|
||||
*/
|
||||
#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) {
|
||||
if(path)
|
||||
homeDir = env->GetStringUTFChars(path, NULL);
|
||||
@@ -314,14 +349,6 @@ int zts_get_proxy_server_address(const char * nwid, struct sockaddr_storage * ad
|
||||
#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__)
|
||||
homeDir = givenHomeDir;
|
||||
localHomeDir = givenHomeDir; // Used for RPC and *can* differ from homeDir on some platforms
|
||||
|
||||
Reference in New Issue
Block a user