mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-01-29 15:43:52 +00:00
Make allow management from a local.conf parameters.
This commit is contained in:
parent
bad4b72f82
commit
890f6f0d35
11
one.cpp
11
one.cpp
@ -973,7 +973,6 @@ int main(int argc,char **argv)
|
||||
std::string homeDir;
|
||||
unsigned int port = ZT_DEFAULT_PORT;
|
||||
bool skipRootCheck = false;
|
||||
const char *allowManagementFrom = (const char *)0;
|
||||
|
||||
for(int i=1;i<argc;++i) {
|
||||
if (argv[i][0] == '-') {
|
||||
@ -987,14 +986,6 @@ int main(int argc,char **argv)
|
||||
}
|
||||
break;
|
||||
|
||||
case 'M': // allow management from this IP/bits network
|
||||
allowManagementFrom = argv[i] + 2;
|
||||
if (!strlen(allowManagementFrom)) {
|
||||
printHelp(argv[0],stdout);
|
||||
return 1;
|
||||
}
|
||||
break;
|
||||
|
||||
#ifdef __UNIX_LIKE__
|
||||
case 'd': // Run in background as daemon
|
||||
runAsDaemon = true;
|
||||
@ -1176,7 +1167,7 @@ int main(int argc,char **argv)
|
||||
unsigned int returnValue = 0;
|
||||
|
||||
for(;;) {
|
||||
zt1Service = OneService::newInstance(homeDir.c_str(),port,allowManagementFrom);
|
||||
zt1Service = OneService::newInstance(homeDir.c_str(),port);
|
||||
switch(zt1Service->run()) {
|
||||
case OneService::ONE_STILL_RUNNING: // shouldn't happen, run() won't return until done
|
||||
case OneService::ONE_NORMAL_TERMINATION:
|
||||
|
@ -514,10 +514,10 @@ public:
|
||||
|
||||
const std::string _homePath;
|
||||
BackgroundResolver _tcpFallbackResolver;
|
||||
InetAddress _allowManagementFrom;
|
||||
EmbeddedNetworkController *_controller;
|
||||
Phy<OneServiceImpl *> _phy;
|
||||
Node *_node;
|
||||
unsigned int _primaryPort;
|
||||
|
||||
// Local configuration and memo-ized static path definitions
|
||||
json _localConfig;
|
||||
@ -527,6 +527,7 @@ public:
|
||||
Hashtable< uint64_t,std::vector<InetAddress> > _v6Blacklists;
|
||||
std::vector< InetAddress > _globalV4Blacklist;
|
||||
std::vector< InetAddress > _globalV6Blacklist;
|
||||
std::vector< InetAddress > _allowManagementFrom;
|
||||
std::vector< std::string > _interfacePrefixBlacklist;
|
||||
Mutex _localConfig_m;
|
||||
|
||||
@ -612,12 +613,13 @@ public:
|
||||
|
||||
// end member variables ----------------------------------------------------
|
||||
|
||||
OneServiceImpl(const char *hp,unsigned int port,const char *allowManagementFrom) :
|
||||
OneServiceImpl(const char *hp,unsigned int port) :
|
||||
_homePath((hp) ? hp : ".")
|
||||
,_tcpFallbackResolver(ZT_TCP_FALLBACK_RELAY)
|
||||
,_controller((EmbeddedNetworkController *)0)
|
||||
,_phy(this,false,true)
|
||||
,_node((Node *)0)
|
||||
,_primaryPort(port)
|
||||
,_controlPlane((ControlPlane *)0)
|
||||
,_lastDirectReceiveFromGlobal(0)
|
||||
#ifdef ZT_TCP_FALLBACK_RELAY
|
||||
@ -637,63 +639,9 @@ public:
|
||||
#endif
|
||||
,_run(true)
|
||||
{
|
||||
if (allowManagementFrom)
|
||||
_allowManagementFrom.fromString(allowManagementFrom);
|
||||
|
||||
_ports[0] = 0;
|
||||
_ports[1] = 0;
|
||||
_ports[2] = 0;
|
||||
|
||||
// The control socket is bound to the default/static port on localhost. If we
|
||||
// can do this, we have successfully allocated a port. The binders will take
|
||||
// care of binding non-local addresses for ZeroTier traffic.
|
||||
const int portTrials = (port == 0) ? 256 : 1; // if port is 0, pick random
|
||||
for(int k=0;k<portTrials;++k) {
|
||||
if (port == 0) {
|
||||
unsigned int randp = 0;
|
||||
Utils::getSecureRandom(&randp,sizeof(randp));
|
||||
port = 20000 + (randp % 45500);
|
||||
}
|
||||
|
||||
if (_trialBind(port)) {
|
||||
struct sockaddr_in in4;
|
||||
memset(&in4,0,sizeof(in4));
|
||||
in4.sin_family = AF_INET;
|
||||
in4.sin_addr.s_addr = Utils::hton((uint32_t)((allowManagementFrom) ? 0 : 0x7f000001)); // right now we just listen for TCP @127.0.0.1
|
||||
in4.sin_port = Utils::hton((uint16_t)port);
|
||||
_v4TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in4,this);
|
||||
|
||||
struct sockaddr_in6 in6;
|
||||
memset((void *)&in6,0,sizeof(in6));
|
||||
in6.sin6_family = AF_INET6;
|
||||
in6.sin6_port = in4.sin_port;
|
||||
if (!allowManagementFrom)
|
||||
in6.sin6_addr.s6_addr[15] = 1; // IPv6 localhost == ::1
|
||||
_v6TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in6,this);
|
||||
|
||||
// We must bind one of IPv4 or IPv6 -- support either failing to support hosts that
|
||||
// have only IPv4 or only IPv6 stacks.
|
||||
if ((_v4TcpControlSocket)||(_v6TcpControlSocket)) {
|
||||
_ports[0] = port;
|
||||
break;
|
||||
} else {
|
||||
if (_v4TcpControlSocket)
|
||||
_phy.close(_v4TcpControlSocket,false);
|
||||
if (_v6TcpControlSocket)
|
||||
_phy.close(_v6TcpControlSocket,false);
|
||||
port = 0;
|
||||
}
|
||||
} else {
|
||||
port = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (_ports[0] == 0)
|
||||
throw std::runtime_error("cannot bind to local control interface port");
|
||||
|
||||
char portstr[64];
|
||||
Utils::snprintf(portstr,sizeof(portstr),"%u",_ports[0]);
|
||||
OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S + "zerotier-one.port").c_str(),std::string(portstr));
|
||||
}
|
||||
|
||||
virtual ~OneServiceImpl()
|
||||
@ -758,49 +706,7 @@ public:
|
||||
_node = new Node(this,&cb,OSUtils::now());
|
||||
}
|
||||
|
||||
// Attempt to bind to a secondary port chosen from our ZeroTier address.
|
||||
// This exists because there are buggy NATs out there that fail if more
|
||||
// than one device behind the same NAT tries to use the same internal
|
||||
// private address port number.
|
||||
_ports[1] = 20000 + ((unsigned int)_node->address() % 45500);
|
||||
for(int i=0;;++i) {
|
||||
if (i > 1000) {
|
||||
_ports[1] = 0;
|
||||
break;
|
||||
} else if (++_ports[1] >= 65536) {
|
||||
_ports[1] = 20000;
|
||||
}
|
||||
if (_trialBind(_ports[1]))
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef ZT_USE_MINIUPNPC
|
||||
// If we're running uPnP/NAT-PMP, bind a *third* port for that. We can't
|
||||
// use the other two ports for that because some NATs do really funky
|
||||
// stuff with ports that are explicitly mapped that breaks things.
|
||||
if (_ports[1]) {
|
||||
_ports[2] = _ports[1];
|
||||
for(int i=0;;++i) {
|
||||
if (i > 1000) {
|
||||
_ports[2] = 0;
|
||||
break;
|
||||
} else if (++_ports[2] >= 65536) {
|
||||
_ports[2] = 20000;
|
||||
}
|
||||
if (_trialBind(_ports[2]))
|
||||
break;
|
||||
}
|
||||
if (_ports[2]) {
|
||||
char uniqueName[64];
|
||||
Utils::snprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]);
|
||||
_portMapper = new PortMapper(_ports[2],uniqueName);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
for(int i=0;i<3;++i)
|
||||
_portsBE[i] = Utils::hton((uint16_t)_ports[i]);
|
||||
|
||||
// Read local configuration
|
||||
{
|
||||
uint64_t trustedPathIds[ZT_MAX_TRUSTED_PATHS];
|
||||
InetAddress trustedPathNetworks[ZT_MAX_TRUSTED_PATHS];
|
||||
@ -872,6 +778,103 @@ public:
|
||||
}
|
||||
applyLocalConfig();
|
||||
|
||||
// Bind TCP control socket
|
||||
const int portTrials = (_primaryPort == 0) ? 256 : 1; // if port is 0, pick random
|
||||
for(int k=0;k<portTrials;++k) {
|
||||
if (_primaryPort == 0) {
|
||||
unsigned int randp = 0;
|
||||
Utils::getSecureRandom(&randp,sizeof(randp));
|
||||
_primaryPort = 20000 + (randp % 45500);
|
||||
}
|
||||
|
||||
if (_trialBind(_primaryPort)) {
|
||||
struct sockaddr_in in4;
|
||||
memset(&in4,0,sizeof(in4));
|
||||
in4.sin_family = AF_INET;
|
||||
in4.sin_addr.s_addr = Utils::hton((uint32_t)((_allowManagementFrom.size() > 0) ? 0 : 0x7f000001)); // right now we just listen for TCP @127.0.0.1
|
||||
in4.sin_port = Utils::hton((uint16_t)_primaryPort);
|
||||
_v4TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in4,this);
|
||||
|
||||
struct sockaddr_in6 in6;
|
||||
memset((void *)&in6,0,sizeof(in6));
|
||||
in6.sin6_family = AF_INET6;
|
||||
in6.sin6_port = in4.sin_port;
|
||||
if (_allowManagementFrom.size() == 0)
|
||||
in6.sin6_addr.s6_addr[15] = 1; // IPv6 localhost == ::1
|
||||
_v6TcpControlSocket = _phy.tcpListen((const struct sockaddr *)&in6,this);
|
||||
|
||||
// We must bind one of IPv4 or IPv6 -- support either failing to support hosts that
|
||||
// have only IPv4 or only IPv6 stacks.
|
||||
if ((_v4TcpControlSocket)||(_v6TcpControlSocket)) {
|
||||
_ports[0] = _primaryPort;
|
||||
break;
|
||||
} else {
|
||||
if (_v4TcpControlSocket)
|
||||
_phy.close(_v4TcpControlSocket,false);
|
||||
if (_v6TcpControlSocket)
|
||||
_phy.close(_v6TcpControlSocket,false);
|
||||
_primaryPort = 0;
|
||||
}
|
||||
} else {
|
||||
_primaryPort = 0;
|
||||
}
|
||||
}
|
||||
if (_ports[0] == 0) {
|
||||
Mutex::Lock _l(_termReason_m);
|
||||
_termReason = ONE_UNRECOVERABLE_ERROR;
|
||||
_fatalErrorMessage = "cannot bind to local control interface port";
|
||||
return _termReason;
|
||||
}
|
||||
|
||||
// Write file containing primary port to be read by CLIs, etc.
|
||||
char portstr[64];
|
||||
Utils::snprintf(portstr,sizeof(portstr),"%u",_ports[0]);
|
||||
OSUtils::writeFile((_homePath + ZT_PATH_SEPARATOR_S + "zerotier-one.port").c_str(),std::string(portstr));
|
||||
|
||||
// Attempt to bind to a secondary port chosen from our ZeroTier address.
|
||||
// This exists because there are buggy NATs out there that fail if more
|
||||
// than one device behind the same NAT tries to use the same internal
|
||||
// private address port number.
|
||||
_ports[1] = 20000 + ((unsigned int)_node->address() % 45500);
|
||||
for(int i=0;;++i) {
|
||||
if (i > 1000) {
|
||||
_ports[1] = 0;
|
||||
break;
|
||||
} else if (++_ports[1] >= 65536) {
|
||||
_ports[1] = 20000;
|
||||
}
|
||||
if (_trialBind(_ports[1]))
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef ZT_USE_MINIUPNPC
|
||||
// If we're running uPnP/NAT-PMP, bind a *third* port for that. We can't
|
||||
// use the other two ports for that because some NATs do really funky
|
||||
// stuff with ports that are explicitly mapped that breaks things.
|
||||
if (_ports[1]) {
|
||||
_ports[2] = _ports[1];
|
||||
for(int i=0;;++i) {
|
||||
if (i > 1000) {
|
||||
_ports[2] = 0;
|
||||
break;
|
||||
} else if (++_ports[2] >= 65536) {
|
||||
_ports[2] = 20000;
|
||||
}
|
||||
if (_trialBind(_ports[2]))
|
||||
break;
|
||||
}
|
||||
if (_ports[2]) {
|
||||
char uniqueName[64];
|
||||
Utils::snprintf(uniqueName,sizeof(uniqueName),"ZeroTier/%.10llx@%u",_node->address(),_ports[2]);
|
||||
_portMapper = new PortMapper(_ports[2],uniqueName);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Populate ports in big-endian format for quick compare
|
||||
for(int i=0;i<3;++i)
|
||||
_portsBE[i] = Utils::hton((uint16_t)_ports[i]);
|
||||
|
||||
_controller = new EmbeddedNetworkController(_node,(_homePath + ZT_PATH_SEPARATOR_S + ZT_CONTROLLER_DB_PATH).c_str());
|
||||
_node->setNetconfMaster((void *)_controller);
|
||||
|
||||
@ -1218,6 +1221,7 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
_allowManagementFrom.clear();
|
||||
_interfacePrefixBlacklist.clear();
|
||||
json &settings = _localConfig["settings"];
|
||||
if (settings.is_object()) {
|
||||
@ -1236,6 +1240,15 @@ public:
|
||||
_interfacePrefixBlacklist.push_back(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
json &amf = settings["allowManagementFrom"];
|
||||
if (amf.is_array()) {
|
||||
for(unsigned long i=0;i<amf.size();++i) {
|
||||
const InetAddress nw(_jS(amf[i],""));
|
||||
if (nw)
|
||||
_allowManagementFrom.push_back(nw);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1928,7 +1941,23 @@ public:
|
||||
std::string contentType("text/plain"); // default if not changed in handleRequest()
|
||||
unsigned int scode = 404;
|
||||
|
||||
if ( ((!_allowManagementFrom)&&(tc->from.ipScope() == InetAddress::IP_SCOPE_LOOPBACK)) || (_allowManagementFrom.containsAddress(tc->from)) ) {
|
||||
bool allow;
|
||||
{
|
||||
Mutex::Lock _l(_localConfig_m);
|
||||
if (_allowManagementFrom.size() == 0) {
|
||||
allow = (tc->from.ipScope() == InetAddress::IP_SCOPE_LOOPBACK);
|
||||
} else {
|
||||
allow = false;
|
||||
for(std::vector<InetAddress>::const_iterator i(_allowManagementFrom.begin());i!=_allowManagementFrom.end();++i) {
|
||||
if (i->containsAddress(tc->from)) {
|
||||
allow = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (allow) {
|
||||
try {
|
||||
if (_controlPlane)
|
||||
scode = _controlPlane->handleRequest(tc->from,tc->parser.method,tc->url,tc->headers,tc->body,data,contentType);
|
||||
@ -2230,7 +2259,7 @@ std::string OneService::autoUpdateUrl()
|
||||
return std::string();
|
||||
}
|
||||
|
||||
OneService *OneService::newInstance(const char *hp,unsigned int port,const char *allowManagementFrom) { return new OneServiceImpl(hp,port,allowManagementFrom); }
|
||||
OneService *OneService::newInstance(const char *hp,unsigned int port) { return new OneServiceImpl(hp,port); }
|
||||
OneService::~OneService() {}
|
||||
|
||||
} // namespace ZeroTier
|
||||
|
@ -98,12 +98,8 @@ public:
|
||||
*
|
||||
* @param hp Home path
|
||||
* @param port TCP and UDP port for packets and HTTP control (if 0, pick random port)
|
||||
* @param allowManagementFrom If non-NULL, allow control from supplied IP/netmask
|
||||
*/
|
||||
static OneService *newInstance(
|
||||
const char *hp,
|
||||
unsigned int port,
|
||||
const char *allowManagementFrom = (const char *)0);
|
||||
static OneService *newInstance(const char *hp,unsigned int port);
|
||||
|
||||
virtual ~OneService();
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user