mirror of
https://github.com/zerotier/ZeroTierOne.git
synced 2025-04-20 17:00:49 +00:00
Root admin stuff
This commit is contained in:
parent
4303c43db7
commit
b0d222768a
@ -24,14 +24,14 @@ Licensed under the ZeroTier BSL (see LICENSE.txt)`, zerotier.CoreVersionMajor, z
|
||||
|
||||
// Help dumps help to stdout
|
||||
func Help() {
|
||||
fmt.Println(copyrightText + `
|
||||
|
||||
fmt.Println(copyrightText)
|
||||
fmt.Println(`
|
||||
Usage: zerotier [-options] <command> [-options] [command args]
|
||||
|
||||
Global Options:
|
||||
-j Output raw JSON where applicable
|
||||
-p <path> Use alternate base path
|
||||
-t <authtoken.secret path> Use secret auth token from this file
|
||||
-t <path> Use secret auth token from this file
|
||||
|
||||
Commands:
|
||||
help Show this help
|
||||
@ -40,12 +40,11 @@ Commands:
|
||||
status Show ZeroTier service status and config
|
||||
peers Show VL1 peers
|
||||
roots Show VL1 root servers
|
||||
addroot <type> [options] Add a VL1 root
|
||||
static <identity> <ip/port> [...] Add a root with a set identity and IPs
|
||||
dynamic <name> [default locator] Add a dynamic root fetched by name
|
||||
removeroot <type> [options] Remove a VL1 root
|
||||
static <identity> Remove a root with a set identity
|
||||
dynamic <name> Remove a dynamic root fetched by name
|
||||
addroot <locator> [<name>] Add a VL1 root
|
||||
removeroot <name> Remove a VL1 root
|
||||
makelocator <secret> <address> [...] Make and sign a locator
|
||||
makelocatordnskey Create a new secure DNS name and key
|
||||
makelocatordns <key> <locator> Make DNS TXT records for a locator
|
||||
networks Show joined VL2 virtual networks
|
||||
join <network ID> Join a virtual network
|
||||
leave <network ID> Leave a virtual network
|
||||
@ -71,6 +70,6 @@ Most commands require a secret token to permit control of a running ZeroTier
|
||||
service. The CLI will automatically try to read this token from the
|
||||
authtoken.secret file in the service's working directory and then from a
|
||||
file called .zerotierauth in the user's home directory. The -t option can be
|
||||
used to explicitly specify a location.
|
||||
`)
|
||||
used to explicitly specify a location.`)
|
||||
fmt.Println()
|
||||
}
|
||||
|
18
go/cmd/zerotier/cli/makelocator.go
Normal file
18
go/cmd/zerotier/cli/makelocator.go
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c)2019 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
package cli
|
||||
|
||||
// MakeLocator CLI command
|
||||
func MakeLocator(args []string) {
|
||||
}
|
18
go/cmd/zerotier/cli/makelocatordns.go
Normal file
18
go/cmd/zerotier/cli/makelocatordns.go
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c)2019 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
package cli
|
||||
|
||||
// MakeLocatorDNS CLI command
|
||||
func MakeLocatorDNS(args []string) {
|
||||
}
|
18
go/cmd/zerotier/cli/makelocatordnskey.go
Normal file
18
go/cmd/zerotier/cli/makelocatordnskey.go
Normal file
@ -0,0 +1,18 @@
|
||||
/*
|
||||
* Copyright (c)2019 ZeroTier, Inc.
|
||||
*
|
||||
* Use of this software is governed by the Business Source License included
|
||||
* in the LICENSE.TXT file in the project's root directory.
|
||||
*
|
||||
* Change Date: 2023-01-01
|
||||
*
|
||||
* On the date above, in accordance with the Business Source License, use
|
||||
* of this software will be governed by version 2.0 of the Apache License.
|
||||
*/
|
||||
/****/
|
||||
|
||||
package cli
|
||||
|
||||
// MakeLocatorDNSKey CLI command
|
||||
func MakeLocatorDNSKey(args []string) {
|
||||
}
|
@ -121,6 +121,12 @@ func main() {
|
||||
case "removeroot":
|
||||
authTokenRequired(authToken)
|
||||
cli.RemoveRoot(basePath, authToken, cmdArgs)
|
||||
case "makelocator":
|
||||
cli.MakeLocator(cmdArgs)
|
||||
case "makelocatordnskey":
|
||||
cli.MakeLocatorDNSKey(cmdArgs)
|
||||
case "makelocatordns":
|
||||
cli.MakeLocatorDNS(cmdArgs)
|
||||
case "networks", "listnetworks":
|
||||
authTokenRequired(authToken)
|
||||
cli.Networks(basePath, authToken, cmdArgs)
|
||||
|
@ -730,9 +730,9 @@ int ZT_GoLocator_makeSecureDNSName(char *name,unsigned int nameBufSize,uint8_t *
|
||||
uint8_t pub[ZT_ECC384_PUBLIC_KEY_SIZE];
|
||||
ECC384GenerateKey(pub,privateKey);
|
||||
const Str n(Locator::makeSecureDnsName(pub));
|
||||
if (n.size() >= nameBufSize)
|
||||
if (n.length() >= nameBufSize)
|
||||
return -1;
|
||||
Utils::scopy(name,sizeof(name),n.c_Str());
|
||||
Utils::scopy(name,sizeof(name),n.c_str());
|
||||
return ZT_ECC384_PRIVATE_KEY_SIZE;
|
||||
}
|
||||
|
||||
@ -775,9 +775,20 @@ int ZT_GoLocator_makeLocator(
|
||||
return s;
|
||||
}
|
||||
|
||||
int ZT_GoLocator_decodeLocator(const uint8_t *loc,unsigned int locSize,struct ZT_GoLocator_Info *info)
|
||||
int ZT_GoLocator_decodeLocator(const uint8_t *locatorBytes,unsigned int locatorSize,struct ZT_GoLocator_Info *info)
|
||||
{
|
||||
memset(info,0,sizeof(struct ZT_GoLocator_Info));
|
||||
Locator loc;
|
||||
if (!loc.deserialize(locatorBytes,locatorSize))
|
||||
return -1;
|
||||
if (!loc.verify())
|
||||
return -2;
|
||||
loc.id().toString(false,info->id);
|
||||
info->phyCount = 0;
|
||||
info->virtCount = 0;
|
||||
for(auto p=loc.phy().begin();p!=loc.phy().end();++p)
|
||||
memcpy(&(info->phy[info->phyCount++]),&(*p),sizeof(struct sockaddr_storage));
|
||||
for(auto v=loc.virt().begin();v!=loc.virt().end();++v)
|
||||
v->toString(false,info->virt[info->virtCount++]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -92,11 +92,11 @@ int ZT_GoTap_removeRoute(ZT_GoTap *tap,int targetAf,const void *targetIp,int tar
|
||||
|
||||
struct ZT_GoLocator_Info {
|
||||
char id[1024];
|
||||
struct sockaddr_storage phy[256];
|
||||
char virt[256][1024];
|
||||
unsigned int phyCount;
|
||||
unsigned int virtCount;
|
||||
}
|
||||
struct sockaddr_storage phy[256];
|
||||
char virt[256][1024];
|
||||
};
|
||||
|
||||
/* Returns length of private key stored in private key buffer on success, -1 on fail */
|
||||
int ZT_GoLocator_makeSecureDNSName(char name[256],unsigned int nameBufSize,uint8_t *privateKey,unsigned int privateKeyBufSize);
|
||||
@ -120,8 +120,8 @@ int ZT_GoLocator_makeLocator(
|
||||
const char **virtualAddresses,
|
||||
unsigned int virtualAddressCount);
|
||||
|
||||
/* Returns nonzero on success, fills info structure */
|
||||
int ZT_GoLocator_decodeLocator(const uint8_t *loc,unsigned int locSize,struct ZT_GoLocator_Info *info);
|
||||
/* Returns >0 on success, fills info structure */
|
||||
int ZT_GoLocator_decodeLocator(const uint8_t *locatorBytes,unsigned int locatorSize,struct ZT_GoLocator_Info *info);
|
||||
|
||||
/*
|
||||
* The privateKey and privateKeySize are those created by makeSecureDNSName.
|
||||
|
@ -356,6 +356,9 @@ func createAPIServer(basePath string, node *Node) (*http.Server, error) {
|
||||
if queriedID == 0 {
|
||||
apiSendObj(out, req, http.StatusBadRequest, nil)
|
||||
} else {
|
||||
var r Root
|
||||
if apiReadObj(out, req, &r) == nil {
|
||||
}
|
||||
}
|
||||
} else if req.Method == http.MethodGet || req.Method == http.MethodHead {
|
||||
roots := node.Roots()
|
||||
|
@ -20,6 +20,7 @@ func (e Err) Error() string { return (string)(e) }
|
||||
|
||||
// Simple ZeroTier Errors
|
||||
const (
|
||||
ErrInternal Err = "internal error"
|
||||
ErrNodeInitFailed Err = "unable to initialize core Node instance"
|
||||
ErrInvalidMACAddress Err = "invalid MAC address"
|
||||
ErrInvalidZeroTierAddress Err = "invalid ZeroTier address"
|
||||
@ -28,5 +29,6 @@ const (
|
||||
ErrTapInitFailed Err = "unable to create native Tap instance"
|
||||
ErrUncrecognizedIdentityType Err = "unrecognized identity type"
|
||||
ErrInvalidKey Err = "invalid key data"
|
||||
ErrInvalidSignature Err = "invalid signature"
|
||||
ErrSecretKeyRequired Err = "secret key required"
|
||||
)
|
||||
|
@ -17,7 +17,10 @@ package zerotier
|
||||
//#include "../../native/GoGlue.h"
|
||||
import "C"
|
||||
|
||||
import "unsafe"
|
||||
import (
|
||||
"encoding/json"
|
||||
"unsafe"
|
||||
)
|
||||
|
||||
// LocatorDNSSigningKey is the public (as a secure DNS name) and private keys for entering locators into DNS
|
||||
type LocatorDNSSigningKey struct {
|
||||
@ -25,6 +28,20 @@ type LocatorDNSSigningKey struct {
|
||||
PrivateKey []byte
|
||||
}
|
||||
|
||||
// NewLocatorDNSSigningKey creates a new signing key and secure DNS name for storing locators in DNS
|
||||
func NewLocatorDNSSigningKey() (*LocatorDNSSigningKey, error) {
|
||||
var nameBuf [256]C.char
|
||||
var keyBuf [64]byte
|
||||
keySize := int(C.ZT_GoLocator_makeSecureDNSName(&nameBuf[0], 256, (*C.uint8_t)(unsafe.Pointer(&keyBuf[0])), 128))
|
||||
if keySize <= 0 {
|
||||
return nil, ErrInternal
|
||||
}
|
||||
var sk LocatorDNSSigningKey
|
||||
sk.SecureDNSName = C.GoString(&nameBuf[0])
|
||||
sk.PrivateKey = keyBuf[0:keySize]
|
||||
return &sk, nil
|
||||
}
|
||||
|
||||
// Locator is a binary serialized record containing information about where a ZeroTier node is located on the network
|
||||
type Locator struct {
|
||||
// Identity is the full identity of the node being located
|
||||
@ -95,5 +112,62 @@ func NewLocator(id *Identity, virtualAddresses []*Identity, physicalAddresses []
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewLocatorFromBytes decodes a locator from its serialized byte array form
|
||||
func NewLocatorFromBytes(b []byte) (*Locator, error) {
|
||||
if len(b) == 0 {
|
||||
return nil, ErrInvalidParameter
|
||||
}
|
||||
var info C.struct_ZT_GoLocator_Info
|
||||
res := C.ZT_GoLocator_decodeLocator((*C.uint8_t)(unsafe.Pointer(&b[0])), C.uint(len(b)), &info)
|
||||
if res == -2 {
|
||||
return nil, ErrInvalidSignature
|
||||
} else if res <= 0 {
|
||||
return nil, ErrInvalidParameter
|
||||
}
|
||||
|
||||
var loc Locator
|
||||
|
||||
var err error
|
||||
loc.Identity, err = NewIdentityFromString(C.GoString(info.id))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
for i := 0; i < int(info.phyCount); i++ {
|
||||
ua := sockaddrStorageToUDPAddr(&info.phy[i])
|
||||
if ua != nil {
|
||||
loc.Physical = append(loc.Physical, &InetAddress{IP: ua.IP, Port: ua.Port})
|
||||
}
|
||||
}
|
||||
for i := 0; i < int(info.virtCount); i++ {
|
||||
id, err := NewIdentityFromString(C.GoString(info.virt[i]))
|
||||
if err == nil {
|
||||
loc.Virtual = append(loc.Virtual, id)
|
||||
}
|
||||
}
|
||||
|
||||
return &loc, nil
|
||||
}
|
||||
|
||||
// Bytes returns this locator in byte serialized format
|
||||
func (l *Locator) Bytes() []byte { return l.bytes }
|
||||
|
||||
// MarshalJSON marshals this Locator as its byte encoding
|
||||
func (l *Locator) MarshalJSON() ([]byte, error) {
|
||||
b := l.bytes
|
||||
return json.Marshal(&b)
|
||||
}
|
||||
|
||||
// UnmarshalJSON unmarshals this Locator from a byte array in JSON.
|
||||
func (l *Locator) UnmarshalJSON(j []byte) error {
|
||||
var ba []byte
|
||||
err := json.Unmarshal(j, &ba)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
tmp, err := NewLocatorFromBytes(ba)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*l = *tmp
|
||||
return nil
|
||||
}
|
||||
|
@ -558,7 +558,7 @@ func (n *Node) Roots() []*Root {
|
||||
}
|
||||
}
|
||||
roots = append(roots, &Root{
|
||||
DNSName: C.GoString(root.dnsName),
|
||||
Name: C.GoString(root.dnsName),
|
||||
Identity: id,
|
||||
Addresses: addrs,
|
||||
Preferred: (root.preferred != 0),
|
||||
@ -571,6 +571,42 @@ func (n *Node) Roots() []*Root {
|
||||
return roots
|
||||
}
|
||||
|
||||
// SetRoot sets or updates a root.
|
||||
// Name can be a DNS name (preferably secure) for DNS fetched locators or can be
|
||||
// the empty string for static roots. If the name is empty then the locator must
|
||||
// be non-nil.
|
||||
func (n *Node) SetRoot(name string, locator *Locator) error {
|
||||
if len(name) == 0 {
|
||||
if locator == nil {
|
||||
return ErrInvalidParameter
|
||||
}
|
||||
name = locator.Identity.address.String()
|
||||
}
|
||||
var lb []byte
|
||||
if locator != nil {
|
||||
lb = locator.Bytes()
|
||||
}
|
||||
var lbp unsafe.Pointer
|
||||
if len(lb) > 0 {
|
||||
lbp = unsafe.Pointer(&lb[0])
|
||||
}
|
||||
cn := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cn))
|
||||
if C.ZT_Node_setRoot(n.zn, cn, lbp, C.uint(len(lb))) != 0 {
|
||||
return ErrInternal
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// RemoveRoot removes a root.
|
||||
// For static roots the name should be the ZeroTier address.
|
||||
func (n *Node) RemoveRoot(name string) {
|
||||
cn := C.CString(name)
|
||||
defer C.free(unsafe.Pointer(cn))
|
||||
C.ZT_Node_removeRoot(n.zn, cn)
|
||||
return
|
||||
}
|
||||
|
||||
// Peers retrieves a list of current peers
|
||||
func (n *Node) Peers() []*Peer {
|
||||
var peers []*Peer
|
||||
|
@ -15,16 +15,10 @@ package zerotier
|
||||
|
||||
// Root describes a root server used to find and establish communication with other nodes.
|
||||
type Root struct {
|
||||
DNSName string
|
||||
Name string
|
||||
Identity *Identity
|
||||
Addresses []InetAddress
|
||||
Locator Locator
|
||||
Locator *Locator
|
||||
Preferred bool
|
||||
Online bool
|
||||
}
|
||||
|
||||
// Static returns true if this is a static root
|
||||
func (r *Root) Static() bool { return len(r.DNSName) == 0 }
|
||||
|
||||
// Dynamic returns true if this is a dynamic root
|
||||
func (r *Root) Dynamic() bool { return len(r.DNSName) > 0 }
|
||||
|
@ -57,7 +57,7 @@ func (w *sizeLimitWriter) trim(maxSize int, trimFactor float64, trimAtCR bool) e
|
||||
|
||||
if flen > int64(maxSize) {
|
||||
var buf [131072]byte
|
||||
trimAt := int64(float64(flen) * trimFactor)
|
||||
trimAt := int64(float64(maxSize) * trimFactor)
|
||||
if trimAt >= flen { // sanity check
|
||||
return nil
|
||||
}
|
||||
|
@ -523,13 +523,13 @@ enum ZT_Event
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* DNS name for dynamic roots or NULL for static roots
|
||||
* Name of root
|
||||
*
|
||||
* If this is a static root this will be NULL and identity
|
||||
* will never be NULL. For dynamic roots identity can be NULL
|
||||
* if the name of this root has never been properly resolved.
|
||||
* This will be a DNS name for dynamic roots. For static roots
|
||||
* it will be the ZeroTier address. The presence or absence
|
||||
* of a dot is used internally as a distinguisher.
|
||||
*/
|
||||
const char *dnsName;
|
||||
const char *name;
|
||||
|
||||
/**
|
||||
* Current public identity or NULL if not known (only possible with dynamic roots)
|
||||
|
@ -316,14 +316,6 @@ public:
|
||||
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_INVALID_TYPE;
|
||||
_ts = (int64_t)b.template at<uint64_t>(p); p += 8;
|
||||
p += _id.deserialize(b,p);
|
||||
const unsigned int signerCount = b[p++];
|
||||
if (signerCount > 1) /* only one third party signer is currently supported */
|
||||
throw ZT_EXCEPTION_INVALID_SERIALIZED_DATA_OVERFLOW;
|
||||
if (signerCount == 1) {
|
||||
p += _signedBy.deserialize(b,p);
|
||||
} else {
|
||||
_signedBy.zero();
|
||||
}
|
||||
const unsigned int physicalCount = b[p++];
|
||||
_physical.resize(physicalCount);
|
||||
for(unsigned int i=0;i<physicalCount;++i)
|
||||
|
@ -81,11 +81,11 @@ public:
|
||||
ZT_ALWAYS_INLINE Topology(const RuntimeEnvironment *renv,const Identity &myId) :
|
||||
RR(renv),
|
||||
_myIdentity(myId),
|
||||
_numConfiguredPhysicalPaths(0),
|
||||
_peers(64),
|
||||
_paths(128),
|
||||
_roots(8),
|
||||
_rootIdentities(8),
|
||||
_numConfiguredPhysicalPaths(0),
|
||||
_lastUpdatedBestRoot(0) {}
|
||||
ZT_ALWAYS_INLINE ~Topology() {}
|
||||
|
||||
@ -385,7 +385,7 @@ public:
|
||||
Locator *v = (Locator *)0;
|
||||
Hashtable< Str,Locator >::Iterator i(const_cast<Topology *>(this)->_roots);
|
||||
while (i.next(k,v)) {
|
||||
rl->roots[c].dnsName = nameBufPtr;
|
||||
rl->roots[c].name = nameBufPtr;
|
||||
const char *p = k->c_str();
|
||||
while (*p)
|
||||
*(nameBufPtr++) = *(p++);
|
||||
|
Loading…
x
Reference in New Issue
Block a user