From 7073d204a896ee1980a93e263d3100b12b961296 Mon Sep 17 00:00:00 2001 From: Nathan Brown Date: Thu, 18 Mar 2021 20:37:24 -0500 Subject: [PATCH] IPv6 support for outside (udp) (#369) --- Makefile | 4 +- allow_list.go | 5 +- allow_list_test.go | 19 +- cert/Makefile | 4 +- cert/cert.pb.go | 358 +++++++++------ cert/cert.proto | 2 + cidr6_radix.go | 203 +++++++++ cidr6_radix_test.go | 134 ++++++ cidr_radix.go | 2 +- config.go | 56 ++- config_test.go | 23 + control.go | 42 +- control_test.go | 10 +- examples/config.yml | 1 + go.mod | 4 +- go.sum | 62 +++ handshake.go | 2 +- handshake_ix.go | 4 +- handshake_manager_test.go | 4 +- hostmap.go | 29 +- hostmap_test.go | 22 +- lighthouse.go | 181 ++++++-- lighthouse_test.go | 45 +- main.go | 27 +- nebula.pb.go | 936 +++++++++++++++++++++++++------------- nebula.proto | 9 +- outside.go | 4 +- ssh.go | 4 +- udp_all.go | 62 +++ udp_darwin.go | 3 +- udp_generic.go | 72 +-- udp_linux.go | 105 +---- udp_linux_32.go | 10 +- udp_linux_64.go | 10 +- 34 files changed, 1726 insertions(+), 732 deletions(-) create mode 100644 cidr6_radix.go create mode 100644 cidr6_radix_test.go create mode 100644 udp_all.go diff --git a/Makefile b/Makefile index cbd5b65..a300e6f 100644 --- a/Makefile +++ b/Makefile @@ -113,8 +113,8 @@ bench-cpu-long: proto: nebula.pb.go cert/cert.pb.go nebula.pb.go: nebula.proto .FORCE - go build github.com/golang/protobuf/protoc-gen-go - PATH="$(PWD):$(PATH)" protoc --go_out=. $< + go build google.golang.org/protobuf/cmd/protoc-gen-go + PATH="$(CURDIR):$(PATH)" protoc --go_out=. --go_opt=paths=source_relative $< rm protoc-gen-go cert/cert.pb.go: cert/cert.proto .FORCE diff --git a/allow_list.go b/allow_list.go index 223d185..d49a856 100644 --- a/allow_list.go +++ b/allow_list.go @@ -2,12 +2,13 @@ package nebula import ( "fmt" + "net" "regexp" ) type AllowList struct { // The values of this cidrTree are `bool`, signifying allow/deny - cidrTree *CIDRTree + cidrTree *CIDR6Tree // To avoid ambiguity, all rules must be true, or all rules must be false. nameRules []AllowListNameRule @@ -18,7 +19,7 @@ type AllowListNameRule struct { Allow bool } -func (al *AllowList) Allow(ip uint32) bool { +func (al *AllowList) Allow(ip net.IP) bool { if al == nil { return true } diff --git a/allow_list_test.go b/allow_list_test.go index 56d9ef8..9c03eb0 100644 --- a/allow_list_test.go +++ b/allow_list_test.go @@ -9,17 +9,26 @@ import ( ) func TestAllowList_Allow(t *testing.T) { - assert.Equal(t, true, ((*AllowList)(nil)).Allow(ip2int(net.ParseIP("1.1.1.1")))) + assert.Equal(t, true, ((*AllowList)(nil)).Allow(net.ParseIP("1.1.1.1"))) - tree := NewCIDRTree() + tree := NewCIDR6Tree() tree.AddCIDR(getCIDR("0.0.0.0/0"), true) tree.AddCIDR(getCIDR("10.0.0.0/8"), false) + tree.AddCIDR(getCIDR("10.42.42.42/32"), true) + tree.AddCIDR(getCIDR("10.42.0.0/16"), true) tree.AddCIDR(getCIDR("10.42.42.0/24"), true) + tree.AddCIDR(getCIDR("10.42.42.0/24"), false) + tree.AddCIDR(getCIDR("::1/128"), true) + tree.AddCIDR(getCIDR("::2/128"), false) al := &AllowList{cidrTree: tree} - assert.Equal(t, true, al.Allow(ip2int(net.ParseIP("1.1.1.1")))) - assert.Equal(t, false, al.Allow(ip2int(net.ParseIP("10.0.0.4")))) - assert.Equal(t, true, al.Allow(ip2int(net.ParseIP("10.42.42.42")))) + assert.Equal(t, true, al.Allow(net.ParseIP("1.1.1.1"))) + assert.Equal(t, false, al.Allow(net.ParseIP("10.0.0.4"))) + assert.Equal(t, true, al.Allow(net.ParseIP("10.42.42.42"))) + assert.Equal(t, false, al.Allow(net.ParseIP("10.42.42.41"))) + assert.Equal(t, true, al.Allow(net.ParseIP("10.42.0.1"))) + assert.Equal(t, true, al.Allow(net.ParseIP("::1"))) + assert.Equal(t, false, al.Allow(net.ParseIP("::2"))) } func TestAllowList_AllowName(t *testing.T) { diff --git a/cert/Makefile b/cert/Makefile index c1c6448..28170b6 100644 --- a/cert/Makefile +++ b/cert/Makefile @@ -2,8 +2,8 @@ GO111MODULE = on export GO111MODULE cert.pb.go: cert.proto .FORCE - go build github.com/golang/protobuf/protoc-gen-go - PATH="$(PWD):$(PATH)" protoc --go_out=. $< + go build google.golang.org/protobuf/cmd/protoc-gen-go + PATH="$(CURDIR):$(PATH)" protoc --go_out=. --go_opt=paths=source_relative $< rm protoc-gen-go .FORCE: diff --git a/cert/cert.pb.go b/cert/cert.pb.go index 02c0826..84a5fc4 100644 --- a/cert/cert.pb.go +++ b/cert/cert.pb.go @@ -1,202 +1,298 @@ // Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.14.0 // source: cert.proto package cert import ( - fmt "fmt" - proto "github.com/golang/protobuf/proto" - math "math" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) type RawNebulaCertificate struct { - Details *RawNebulaCertificateDetails `protobuf:"bytes,1,opt,name=Details,json=details,proto3" json:"Details,omitempty"` - Signature []byte `protobuf:"bytes,2,opt,name=Signature,json=signature,proto3" json:"Signature,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Details *RawNebulaCertificateDetails `protobuf:"bytes,1,opt,name=Details,proto3" json:"Details,omitempty"` + Signature []byte `protobuf:"bytes,2,opt,name=Signature,proto3" json:"Signature,omitempty"` } -func (m *RawNebulaCertificate) Reset() { *m = RawNebulaCertificate{} } -func (m *RawNebulaCertificate) String() string { return proto.CompactTextString(m) } -func (*RawNebulaCertificate) ProtoMessage() {} +func (x *RawNebulaCertificate) Reset() { + *x = RawNebulaCertificate{} + if protoimpl.UnsafeEnabled { + mi := &file_cert_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RawNebulaCertificate) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RawNebulaCertificate) ProtoMessage() {} + +func (x *RawNebulaCertificate) ProtoReflect() protoreflect.Message { + mi := &file_cert_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RawNebulaCertificate.ProtoReflect.Descriptor instead. func (*RawNebulaCertificate) Descriptor() ([]byte, []int) { - return fileDescriptor_a142e29cbef9b1cf, []int{0} + return file_cert_proto_rawDescGZIP(), []int{0} } -func (m *RawNebulaCertificate) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_RawNebulaCertificate.Unmarshal(m, b) -} -func (m *RawNebulaCertificate) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_RawNebulaCertificate.Marshal(b, m, deterministic) -} -func (m *RawNebulaCertificate) XXX_Merge(src proto.Message) { - xxx_messageInfo_RawNebulaCertificate.Merge(m, src) -} -func (m *RawNebulaCertificate) XXX_Size() int { - return xxx_messageInfo_RawNebulaCertificate.Size(m) -} -func (m *RawNebulaCertificate) XXX_DiscardUnknown() { - xxx_messageInfo_RawNebulaCertificate.DiscardUnknown(m) -} - -var xxx_messageInfo_RawNebulaCertificate proto.InternalMessageInfo - -func (m *RawNebulaCertificate) GetDetails() *RawNebulaCertificateDetails { - if m != nil { - return m.Details +func (x *RawNebulaCertificate) GetDetails() *RawNebulaCertificateDetails { + if x != nil { + return x.Details } return nil } -func (m *RawNebulaCertificate) GetSignature() []byte { - if m != nil { - return m.Signature +func (x *RawNebulaCertificate) GetSignature() []byte { + if x != nil { + return x.Signature } return nil } type RawNebulaCertificateDetails struct { - Name string `protobuf:"bytes,1,opt,name=Name,json=name,proto3" json:"Name,omitempty"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Name string `protobuf:"bytes,1,opt,name=Name,proto3" json:"Name,omitempty"` // Ips and Subnets are in big endian 32 bit pairs, 1st the ip, 2nd the mask - Ips []uint32 `protobuf:"varint,2,rep,packed,name=Ips,json=ips,proto3" json:"Ips,omitempty"` - Subnets []uint32 `protobuf:"varint,3,rep,packed,name=Subnets,json=subnets,proto3" json:"Subnets,omitempty"` - Groups []string `protobuf:"bytes,4,rep,name=Groups,json=groups,proto3" json:"Groups,omitempty"` - NotBefore int64 `protobuf:"varint,5,opt,name=NotBefore,json=notBefore,proto3" json:"NotBefore,omitempty"` - NotAfter int64 `protobuf:"varint,6,opt,name=NotAfter,json=notAfter,proto3" json:"NotAfter,omitempty"` - PublicKey []byte `protobuf:"bytes,7,opt,name=PublicKey,json=publicKey,proto3" json:"PublicKey,omitempty"` - IsCA bool `protobuf:"varint,8,opt,name=IsCA,json=isCA,proto3" json:"IsCA,omitempty"` + Ips []uint32 `protobuf:"varint,2,rep,packed,name=Ips,proto3" json:"Ips,omitempty"` + Subnets []uint32 `protobuf:"varint,3,rep,packed,name=Subnets,proto3" json:"Subnets,omitempty"` + Groups []string `protobuf:"bytes,4,rep,name=Groups,proto3" json:"Groups,omitempty"` + NotBefore int64 `protobuf:"varint,5,opt,name=NotBefore,proto3" json:"NotBefore,omitempty"` + NotAfter int64 `protobuf:"varint,6,opt,name=NotAfter,proto3" json:"NotAfter,omitempty"` + PublicKey []byte `protobuf:"bytes,7,opt,name=PublicKey,proto3" json:"PublicKey,omitempty"` + IsCA bool `protobuf:"varint,8,opt,name=IsCA,proto3" json:"IsCA,omitempty"` // sha-256 of the issuer certificate, if this field is blank the cert is self-signed - Issuer []byte `protobuf:"bytes,9,opt,name=Issuer,json=issuer,proto3" json:"Issuer,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + Issuer []byte `protobuf:"bytes,9,opt,name=Issuer,proto3" json:"Issuer,omitempty"` } -func (m *RawNebulaCertificateDetails) Reset() { *m = RawNebulaCertificateDetails{} } -func (m *RawNebulaCertificateDetails) String() string { return proto.CompactTextString(m) } -func (*RawNebulaCertificateDetails) ProtoMessage() {} +func (x *RawNebulaCertificateDetails) Reset() { + *x = RawNebulaCertificateDetails{} + if protoimpl.UnsafeEnabled { + mi := &file_cert_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *RawNebulaCertificateDetails) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*RawNebulaCertificateDetails) ProtoMessage() {} + +func (x *RawNebulaCertificateDetails) ProtoReflect() protoreflect.Message { + mi := &file_cert_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use RawNebulaCertificateDetails.ProtoReflect.Descriptor instead. func (*RawNebulaCertificateDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_a142e29cbef9b1cf, []int{1} + return file_cert_proto_rawDescGZIP(), []int{1} } -func (m *RawNebulaCertificateDetails) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_RawNebulaCertificateDetails.Unmarshal(m, b) -} -func (m *RawNebulaCertificateDetails) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_RawNebulaCertificateDetails.Marshal(b, m, deterministic) -} -func (m *RawNebulaCertificateDetails) XXX_Merge(src proto.Message) { - xxx_messageInfo_RawNebulaCertificateDetails.Merge(m, src) -} -func (m *RawNebulaCertificateDetails) XXX_Size() int { - return xxx_messageInfo_RawNebulaCertificateDetails.Size(m) -} -func (m *RawNebulaCertificateDetails) XXX_DiscardUnknown() { - xxx_messageInfo_RawNebulaCertificateDetails.DiscardUnknown(m) -} - -var xxx_messageInfo_RawNebulaCertificateDetails proto.InternalMessageInfo - -func (m *RawNebulaCertificateDetails) GetName() string { - if m != nil { - return m.Name +func (x *RawNebulaCertificateDetails) GetName() string { + if x != nil { + return x.Name } return "" } -func (m *RawNebulaCertificateDetails) GetIps() []uint32 { - if m != nil { - return m.Ips +func (x *RawNebulaCertificateDetails) GetIps() []uint32 { + if x != nil { + return x.Ips } return nil } -func (m *RawNebulaCertificateDetails) GetSubnets() []uint32 { - if m != nil { - return m.Subnets +func (x *RawNebulaCertificateDetails) GetSubnets() []uint32 { + if x != nil { + return x.Subnets } return nil } -func (m *RawNebulaCertificateDetails) GetGroups() []string { - if m != nil { - return m.Groups +func (x *RawNebulaCertificateDetails) GetGroups() []string { + if x != nil { + return x.Groups } return nil } -func (m *RawNebulaCertificateDetails) GetNotBefore() int64 { - if m != nil { - return m.NotBefore +func (x *RawNebulaCertificateDetails) GetNotBefore() int64 { + if x != nil { + return x.NotBefore } return 0 } -func (m *RawNebulaCertificateDetails) GetNotAfter() int64 { - if m != nil { - return m.NotAfter +func (x *RawNebulaCertificateDetails) GetNotAfter() int64 { + if x != nil { + return x.NotAfter } return 0 } -func (m *RawNebulaCertificateDetails) GetPublicKey() []byte { - if m != nil { - return m.PublicKey +func (x *RawNebulaCertificateDetails) GetPublicKey() []byte { + if x != nil { + return x.PublicKey } return nil } -func (m *RawNebulaCertificateDetails) GetIsCA() bool { - if m != nil { - return m.IsCA +func (x *RawNebulaCertificateDetails) GetIsCA() bool { + if x != nil { + return x.IsCA } return false } -func (m *RawNebulaCertificateDetails) GetIssuer() []byte { - if m != nil { - return m.Issuer +func (x *RawNebulaCertificateDetails) GetIssuer() []byte { + if x != nil { + return x.Issuer } return nil } -func init() { - proto.RegisterType((*RawNebulaCertificate)(nil), "cert.RawNebulaCertificate") - proto.RegisterType((*RawNebulaCertificateDetails)(nil), "cert.RawNebulaCertificateDetails") +var File_cert_proto protoreflect.FileDescriptor + +var file_cert_proto_rawDesc = []byte{ + 0x0a, 0x0a, 0x63, 0x65, 0x72, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x04, 0x63, 0x65, + 0x72, 0x74, 0x22, 0x71, 0x0a, 0x14, 0x52, 0x61, 0x77, 0x4e, 0x65, 0x62, 0x75, 0x6c, 0x61, 0x43, + 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x12, 0x3b, 0x0a, 0x07, 0x44, 0x65, + 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x21, 0x2e, 0x63, 0x65, + 0x72, 0x74, 0x2e, 0x52, 0x61, 0x77, 0x4e, 0x65, 0x62, 0x75, 0x6c, 0x61, 0x43, 0x65, 0x72, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x07, + 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x53, 0x69, 0x67, 0x6e, 0x61, + 0x74, 0x75, 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x53, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0xf9, 0x01, 0x0a, 0x1b, 0x52, 0x61, 0x77, 0x4e, 0x65, 0x62, + 0x75, 0x6c, 0x61, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x44, 0x65, + 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x10, 0x0a, 0x03, 0x49, 0x70, 0x73, + 0x18, 0x02, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x03, 0x49, 0x70, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x53, + 0x75, 0x62, 0x6e, 0x65, 0x74, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0d, 0x52, 0x07, 0x53, 0x75, + 0x62, 0x6e, 0x65, 0x74, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x18, + 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x06, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x73, 0x12, 0x1c, 0x0a, + 0x09, 0x4e, 0x6f, 0x74, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x09, 0x4e, 0x6f, 0x74, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x4e, + 0x6f, 0x74, 0x41, 0x66, 0x74, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x4e, + 0x6f, 0x74, 0x41, 0x66, 0x74, 0x65, 0x72, 0x12, 0x1c, 0x0a, 0x09, 0x50, 0x75, 0x62, 0x6c, 0x69, + 0x63, 0x4b, 0x65, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x09, 0x50, 0x75, 0x62, 0x6c, + 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x12, 0x0a, 0x04, 0x49, 0x73, 0x43, 0x41, 0x18, 0x08, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x04, 0x49, 0x73, 0x43, 0x41, 0x12, 0x16, 0x0a, 0x06, 0x49, 0x73, 0x73, + 0x75, 0x65, 0x72, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x06, 0x49, 0x73, 0x73, 0x75, 0x65, + 0x72, 0x42, 0x20, 0x5a, 0x1e, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, + 0x73, 0x6c, 0x61, 0x63, 0x6b, 0x68, 0x71, 0x2f, 0x6e, 0x65, 0x62, 0x75, 0x6c, 0x61, 0x2f, 0x63, + 0x65, 0x72, 0x74, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } -func init() { proto.RegisterFile("cert.proto", fileDescriptor_a142e29cbef9b1cf) } +var ( + file_cert_proto_rawDescOnce sync.Once + file_cert_proto_rawDescData = file_cert_proto_rawDesc +) -var fileDescriptor_a142e29cbef9b1cf = []byte{ - // 279 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x90, 0xcf, 0x4a, 0xf4, 0x30, - 0x14, 0xc5, 0xc9, 0xa4, 0x5f, 0xdb, 0xe4, 0x53, 0x90, 0x20, 0x12, 0xd4, 0x45, 0x9c, 0x55, 0x56, - 0xb3, 0xd0, 0xa5, 0xab, 0x71, 0x04, 0x29, 0x42, 0x91, 0xcc, 0x13, 0xa4, 0xf5, 0x76, 0x08, 0x74, - 0x9a, 0x9a, 0x3f, 0x88, 0x8f, 0xee, 0x4e, 0x9a, 0x4e, 0x77, 0xe2, 0xee, 0x9e, 0x5f, 0xce, 0x49, - 0x4e, 0x2e, 0xa5, 0x2d, 0xb8, 0xb0, 0x19, 0x9d, 0x0d, 0x96, 0x65, 0xd3, 0xbc, 0xfe, 0xa0, 0x97, - 0x4a, 0x7f, 0xd6, 0xd0, 0xc4, 0x5e, 0xef, 0xc0, 0x05, 0xd3, 0x99, 0x56, 0x07, 0x60, 0x8f, 0xb4, - 0x78, 0x86, 0xa0, 0x4d, 0xef, 0x39, 0x12, 0x48, 0xfe, 0xbf, 0xbf, 0xdb, 0xa4, 0xec, 0x6f, 0xe6, - 0x93, 0x51, 0x15, 0xef, 0xf3, 0xc0, 0x6e, 0x29, 0xd9, 0x9b, 0xc3, 0xa0, 0x43, 0x74, 0xc0, 0x57, - 0x02, 0xc9, 0x33, 0x45, 0xfc, 0x02, 0xd6, 0xdf, 0x88, 0xde, 0xfc, 0x71, 0x0d, 0x63, 0x34, 0xab, - 0xf5, 0x11, 0xd2, 0xbb, 0x44, 0x65, 0x83, 0x3e, 0x02, 0xbb, 0xa0, 0xb8, 0x1a, 0x3d, 0x5f, 0x09, - 0x2c, 0xcf, 0x15, 0x36, 0xa3, 0x67, 0x9c, 0x16, 0xfb, 0xd8, 0x0c, 0x10, 0x3c, 0xc7, 0x89, 0x16, - 0x7e, 0x96, 0xec, 0x8a, 0xe6, 0x2f, 0xce, 0xc6, 0xd1, 0xf3, 0x4c, 0x60, 0x49, 0x54, 0x7e, 0x48, - 0x6a, 0x6a, 0x55, 0xdb, 0xf0, 0x04, 0x9d, 0x75, 0xc0, 0xff, 0x09, 0x24, 0xb1, 0x22, 0xc3, 0x02, - 0xd8, 0x35, 0x2d, 0x6b, 0x1b, 0xb6, 0x5d, 0x00, 0xc7, 0xf3, 0x74, 0x58, 0x0e, 0x27, 0x3d, 0x25, - 0xdf, 0x62, 0xd3, 0x9b, 0xf6, 0x15, 0xbe, 0x78, 0x31, 0xff, 0x67, 0x5c, 0xc0, 0xd4, 0xb7, 0xf2, - 0xbb, 0x2d, 0x2f, 0x05, 0x92, 0xa5, 0xca, 0x8c, 0xdf, 0x6d, 0xa7, 0x0e, 0x95, 0xf7, 0x11, 0x1c, - 0x27, 0xc9, 0x9e, 0x9b, 0xa4, 0x9a, 0x3c, 0xed, 0xfe, 0xe1, 0x27, 0x00, 0x00, 0xff, 0xff, 0x2c, - 0xe3, 0x08, 0x37, 0x89, 0x01, 0x00, 0x00, +func file_cert_proto_rawDescGZIP() []byte { + file_cert_proto_rawDescOnce.Do(func() { + file_cert_proto_rawDescData = protoimpl.X.CompressGZIP(file_cert_proto_rawDescData) + }) + return file_cert_proto_rawDescData +} + +var file_cert_proto_msgTypes = make([]protoimpl.MessageInfo, 2) +var file_cert_proto_goTypes = []interface{}{ + (*RawNebulaCertificate)(nil), // 0: cert.RawNebulaCertificate + (*RawNebulaCertificateDetails)(nil), // 1: cert.RawNebulaCertificateDetails +} +var file_cert_proto_depIdxs = []int32{ + 1, // 0: cert.RawNebulaCertificate.Details:type_name -> cert.RawNebulaCertificateDetails + 1, // [1:1] is the sub-list for method output_type + 1, // [1:1] is the sub-list for method input_type + 1, // [1:1] is the sub-list for extension type_name + 1, // [1:1] is the sub-list for extension extendee + 0, // [0:1] is the sub-list for field type_name +} + +func init() { file_cert_proto_init() } +func file_cert_proto_init() { + if File_cert_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_cert_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RawNebulaCertificate); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_cert_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*RawNebulaCertificateDetails); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_cert_proto_rawDesc, + NumEnums: 0, + NumMessages: 2, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_cert_proto_goTypes, + DependencyIndexes: file_cert_proto_depIdxs, + MessageInfos: file_cert_proto_msgTypes, + }.Build() + File_cert_proto = out.File + file_cert_proto_rawDesc = nil + file_cert_proto_goTypes = nil + file_cert_proto_depIdxs = nil } diff --git a/cert/cert.proto b/cert/cert.proto index 29977c4..e135dd1 100644 --- a/cert/cert.proto +++ b/cert/cert.proto @@ -1,6 +1,8 @@ syntax = "proto3"; package cert; +option go_package = "github.com/slackhq/nebula/cert"; + //import "google/protobuf/timestamp.proto"; message RawNebulaCertificate { diff --git a/cidr6_radix.go b/cidr6_radix.go new file mode 100644 index 0000000..9e160d3 --- /dev/null +++ b/cidr6_radix.go @@ -0,0 +1,203 @@ +package nebula + +import ( + "encoding/binary" + "net" +) + +type CIDR6Tree struct { + root4 *CIDRNode + root6 *CIDRNode +} + +func NewCIDR6Tree() *CIDR6Tree { + tree := new(CIDR6Tree) + tree.root4 = &CIDRNode{} + tree.root6 = &CIDRNode{} + return tree +} + +func (tree *CIDR6Tree) AddCIDR(cidr *net.IPNet, val interface{}) { + var node, next *CIDRNode + + cidrIP, ipv4 := isIPV4(cidr.IP) + if ipv4 { + node = tree.root4 + next = tree.root4 + + } else { + node = tree.root6 + next = tree.root6 + } + + for i := 0; i < len(cidrIP); i += 4 { + ip := binary.BigEndian.Uint32(cidrIP[i : i+4]) + mask := binary.BigEndian.Uint32(cidr.Mask[i : i+4]) + bit := startbit + + // Find our last ancestor in the tree + for bit&mask != 0 { + if ip&bit != 0 { + next = node.right + } else { + next = node.left + } + + if next == nil { + break + } + + bit = bit >> 1 + node = next + } + + // Build up the rest of the tree we don't already have + for bit&mask != 0 { + next = &CIDRNode{} + next.parent = node + + if ip&bit != 0 { + node.right = next + } else { + node.left = next + } + + bit >>= 1 + node = next + } + } + + // Final node marks our cidr, set the value + node.value = val +} + +// Finds the first match, which may be the least specific +func (tree *CIDR6Tree) Contains(ip net.IP) (value interface{}) { + var node *CIDRNode + + wholeIP, ipv4 := isIPV4(ip) + if ipv4 { + node = tree.root4 + } else { + node = tree.root6 + } + + for i := 0; i < len(wholeIP); i += 4 { + ip := ip2int(wholeIP[i : i+4]) + bit := startbit + + for node != nil { + if node.value != nil { + return node.value + } + + // Check if we have reached the end and the above return did not trigger, move to the next uint32 if available + if bit == 0 { + break + } + + if ip&bit != 0 { + node = node.right + } else { + node = node.left + } + + bit >>= 1 + } + } + + // Nothing found + return +} + +// Finds the most specific match +func (tree *CIDR6Tree) MostSpecificContains(ip net.IP) (value interface{}) { + var node *CIDRNode + + wholeIP, ipv4 := isIPV4(ip) + if ipv4 { + node = tree.root4 + } else { + node = tree.root6 + } + + for i := 0; i < len(wholeIP); i += 4 { + ip := ip2int(wholeIP[i : i+4]) + bit := startbit + + for node != nil { + if node.value != nil { + value = node.value + } + + if bit == 0 { + break + } + + if ip&bit != 0 { + node = node.right + } else { + node = node.left + } + + bit >>= 1 + } + } + + return value +} + +// Finds the most specific match +func (tree *CIDR6Tree) Match(ip net.IP) (value interface{}) { + var node *CIDRNode + var bit uint32 + + wholeIP, ipv4 := isIPV4(ip) + if ipv4 { + node = tree.root4 + } else { + node = tree.root6 + } + + for i := 0; i < len(wholeIP); i += 4 { + ip := ip2int(wholeIP[i : i+4]) + bit = startbit + + for node != nil && bit > 0 { + if ip&bit != 0 { + node = node.right + } else { + node = node.left + } + + bit >>= 1 + } + } + + if bit == 0 && node != nil { + value = node.value + } + + return value +} + +func isIPV4(ip net.IP) (net.IP, bool) { + if len(ip) == net.IPv4len { + return ip, true + } + + if len(ip) == net.IPv6len && isZeros(ip[0:10]) && ip[10] == 0xff && ip[11] == 0xff { + return ip[12:16], true + } + + return ip, false +} + +func isZeros(p net.IP) bool { + for i := 0; i < len(p); i++ { + if p[i] != 0 { + return false + } + } + return true +} diff --git a/cidr6_radix_test.go b/cidr6_radix_test.go new file mode 100644 index 0000000..12b1ff6 --- /dev/null +++ b/cidr6_radix_test.go @@ -0,0 +1,134 @@ +package nebula + +import ( + "net" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestCIDR6Tree_Contains(t *testing.T) { + tree := NewCIDR6Tree() + tree.AddCIDR(getCIDR("1.0.0.0/8"), "1") + tree.AddCIDR(getCIDR("2.1.0.0/16"), "2") + tree.AddCIDR(getCIDR("3.1.1.0/24"), "3") + tree.AddCIDR(getCIDR("4.1.1.0/24"), "4a") + tree.AddCIDR(getCIDR("4.1.1.1/32"), "4b") + tree.AddCIDR(getCIDR("4.1.2.1/32"), "4c") + tree.AddCIDR(getCIDR("254.0.0.0/4"), "5") + tree.AddCIDR(getCIDR("2800::FFFF:1/128"), "a") + tree.AddCIDR(getCIDR("2800:1:2:3::0/64"), "b") + + tests := []struct { + Result interface{} + IP string + }{ + {"1", "1.0.0.0"}, + {"1", "1.255.255.255"}, + {"2", "2.1.0.0"}, + {"2", "2.1.255.255"}, + {"3", "3.1.1.0"}, + {"3", "3.1.1.255"}, + {"4a", "4.1.1.255"}, + {"4a", "4.1.1.1"}, + {"5", "240.0.0.0"}, + {"5", "255.255.255.255"}, + {nil, "239.0.0.0"}, + {nil, "4.1.2.2"}, + {"a", "2800::FFFF:1"}, + {"b", "2800:1:2:3::1"}, + {"b", "2800:1:2:3::6"}, + } + + for _, tt := range tests { + assert.Equal(t, tt.Result, tree.Contains(net.ParseIP(tt.IP))) + } + + tree = NewCIDR6Tree() + tree.AddCIDR(getCIDR("1.1.1.1/0"), "cool") + tree.AddCIDR(getCIDR("::/0"), "cool6") + assert.Equal(t, "cool", tree.Contains(net.ParseIP("0.0.0.0"))) + assert.Equal(t, "cool", tree.Contains(net.ParseIP("255.255.255.255"))) + assert.Equal(t, "cool6", tree.Contains(net.ParseIP("::"))) + assert.Equal(t, "cool6", tree.Contains(net.ParseIP("1:2:3:4:5:6:7:8"))) +} + +func TestCIDR6Tree_MostSpecificContains(t *testing.T) { + tree := NewCIDR6Tree() + tree.AddCIDR(getCIDR("1.0.0.0/8"), "1") + tree.AddCIDR(getCIDR("2.1.0.0/16"), "2") + tree.AddCIDR(getCIDR("3.1.1.0/24"), "3") + tree.AddCIDR(getCIDR("4.1.1.1/24"), "4a") + tree.AddCIDR(getCIDR("4.1.1.1/30"), "4b") + tree.AddCIDR(getCIDR("4.1.1.1/32"), "4c") + tree.AddCIDR(getCIDR("254.0.0.0/4"), "5") + tree.AddCIDR(getCIDR("1:2:0:4:5:0:0:0/64"), "6a") + tree.AddCIDR(getCIDR("1:2:0:4:5:0:0:0/80"), "6b") + tree.AddCIDR(getCIDR("1:2:0:4:5:0:0:0/96"), "6c") + + tests := []struct { + Result interface{} + IP string + }{ + {"1", "1.0.0.0"}, + {"1", "1.255.255.255"}, + {"2", "2.1.0.0"}, + {"2", "2.1.255.255"}, + {"3", "3.1.1.0"}, + {"3", "3.1.1.255"}, + {"4a", "4.1.1.255"}, + {"4b", "4.1.1.2"}, + {"4c", "4.1.1.1"}, + {"5", "240.0.0.0"}, + {"5", "255.255.255.255"}, + {"6a", "1:2:0:4:1:1:1:1"}, + {"6b", "1:2:0:4:5:1:1:1"}, + {"6c", "1:2:0:4:5:0:0:0"}, + {nil, "239.0.0.0"}, + {nil, "4.1.2.2"}, + } + + for _, tt := range tests { + assert.Equal(t, tt.Result, tree.MostSpecificContains(net.ParseIP(tt.IP))) + } + + tree = NewCIDR6Tree() + tree.AddCIDR(getCIDR("1.1.1.1/0"), "cool") + tree.AddCIDR(getCIDR("::/0"), "cool6") + assert.Equal(t, "cool", tree.MostSpecificContains(net.ParseIP("0.0.0.0"))) + assert.Equal(t, "cool", tree.MostSpecificContains(net.ParseIP("255.255.255.255"))) + assert.Equal(t, "cool6", tree.Contains(net.ParseIP("::"))) + assert.Equal(t, "cool6", tree.Contains(net.ParseIP("1:2:3:4:5:6:7:8"))) +} + +func TestCIDR6Tree_Match(t *testing.T) { + tree := NewCIDR6Tree() + tree.AddCIDR(getCIDR("4.1.1.0/32"), "1a") + tree.AddCIDR(getCIDR("4.1.1.1/32"), "1b") + tree.AddCIDR(getCIDR("1:2:3:4:5:6:7:8/128"), "2a") + tree.AddCIDR(getCIDR("1:2:3:4:5:6:7:0/128"), "2b") + + tests := []struct { + Result interface{} + IP string + }{ + {"1a", "4.1.1.0"}, + {"1b", "4.1.1.1"}, + {nil, "4.1.1.2"}, + {"2a", "1:2:3:4:5:6:7:8"}, + {"2b", "1:2:3:4:5:6:7:0"}, + {nil, "1:2:3:4:5:6:7:9"}, + } + + for _, tt := range tests { + assert.Equal(t, tt.Result, tree.Match(net.ParseIP(tt.IP))) + } + + tree = NewCIDR6Tree() + tree.AddCIDR(getCIDR("1.1.1.1/0"), "cool") + tree.AddCIDR(getCIDR("1:2:3:4:5:6:7:8/0"), "cool6") + assert.Equal(t, "cool", tree.Contains(net.ParseIP("0.0.0.0"))) + assert.Equal(t, "cool", tree.Contains(net.ParseIP("255.255.255.255"))) + assert.Equal(t, "cool6", tree.Contains(net.ParseIP("::"))) + assert.Equal(t, "cool6", tree.Contains(net.ParseIP("1:2:3:4:5:6:7:8"))) +} diff --git a/cidr_radix.go b/cidr_radix.go index a1b5750..bc8cd95 100644 --- a/cidr_radix.go +++ b/cidr_radix.go @@ -76,7 +76,7 @@ func (tree *CIDRTree) AddCIDR(cidr *net.IPNet, val interface{}) { node.value = val } -// Finds the first match, which way be the least specific +// Finds the first match, which may be the least specific func (tree *CIDRTree) Contains(ip uint32) (value interface{}) { bit := startbit node := tree.root diff --git a/config.go b/config.go index 87f42e8..a5493df 100644 --- a/config.go +++ b/config.go @@ -235,13 +235,18 @@ func (c *Config) GetAllowList(k string, allowInterfaces bool) (*AllowList, error return nil, fmt.Errorf("config `%s` has invalid type: %T", k, r) } - tree := NewCIDRTree() + tree := NewCIDR6Tree() var nameRules []AllowListNameRule - firstValue := true - allValuesMatch := true - defaultSet := false - var allValues bool + // Keep track of the rules we have added for both ipv4 and ipv6 + type allowListRules struct { + firstValue bool + allValuesMatch bool + defaultSet bool + allValues bool + } + rules4 := allowListRules{firstValue: true, allValuesMatch: true, defaultSet: false} + rules6 := allowListRules{firstValue: true, allValuesMatch: true, defaultSet: false} for rawKey, rawValue := range rawMap { rawCIDR, ok := rawKey.(string) @@ -276,31 +281,48 @@ func (c *Config) GetAllowList(k string, allowInterfaces bool) (*AllowList, error // TODO: should we error on duplicate CIDRs in the config? tree.AddCIDR(cidr, value) - if firstValue { - allValues = value - firstValue = false + maskBits, maskSize := cidr.Mask.Size() + + var rules *allowListRules + if maskSize == 32 { + rules = &rules4 } else { - if value != allValues { - allValuesMatch = false + rules = &rules6 + } + + if rules.firstValue { + rules.allValues = value + rules.firstValue = false + } else { + if value != rules.allValues { + rules.allValuesMatch = false } } - // Check if this is 0.0.0.0/0 - bits, size := cidr.Mask.Size() - if bits == 0 && size == 32 { - defaultSet = true + // Check if this is 0.0.0.0/0 or ::/0 + if maskBits == 0 { + rules.defaultSet = true } } - if !defaultSet { - if allValuesMatch { + if !rules4.defaultSet { + if rules4.allValuesMatch { _, zeroCIDR, _ := net.ParseCIDR("0.0.0.0/0") - tree.AddCIDR(zeroCIDR, !allValues) + tree.AddCIDR(zeroCIDR, !rules4.allValues) } else { return nil, fmt.Errorf("config `%s` contains both true and false rules, but no default set for 0.0.0.0/0", k) } } + if !rules6.defaultSet { + if rules6.allValuesMatch { + _, zeroCIDR, _ := net.ParseCIDR("::/0") + tree.AddCIDR(zeroCIDR, !rules6.allValues) + } else { + return nil, fmt.Errorf("config `%s` contains both true and false rules, but no default set for ::/0", k) + } + } + return &AllowList{cidrTree: tree, nameRules: nameRules}, nil } diff --git a/config_test.go b/config_test.go index dc617b4..359a2af 100644 --- a/config_test.go +++ b/config_test.go @@ -109,6 +109,16 @@ func TestConfig_GetAllowList(t *testing.T) { r, err = c.GetAllowList("allowlist", false) assert.EqualError(t, err, "config `allowlist` contains both true and false rules, but no default set for 0.0.0.0/0") + c.Settings["allowlist"] = map[interface{}]interface{}{ + "0.0.0.0/0": true, + "10.0.0.0/8": false, + "10.42.42.0/24": true, + "fd00::/8": true, + "fd00:fd00::/16": false, + } + r, err = c.GetAllowList("allowlist", false) + assert.EqualError(t, err, "config `allowlist` contains both true and false rules, but no default set for ::/0") + c.Settings["allowlist"] = map[interface{}]interface{}{ "0.0.0.0/0": true, "10.0.0.0/8": false, @@ -119,6 +129,19 @@ func TestConfig_GetAllowList(t *testing.T) { assert.NotNil(t, r) } + c.Settings["allowlist"] = map[interface{}]interface{}{ + "0.0.0.0/0": true, + "10.0.0.0/8": false, + "10.42.42.0/24": true, + "::/0": false, + "fd00::/8": true, + "fd00:fd00::/16": false, + } + r, err = c.GetAllowList("allowlist", false) + if assert.NoError(t, err) { + assert.NotNil(t, r) + } + // Test interface names c.Settings["allowlist"] = map[interface{}]interface{}{ diff --git a/control.go b/control.go index 4964164..a5df2d5 100644 --- a/control.go +++ b/control.go @@ -23,11 +23,11 @@ type ControlHostInfo struct { VpnIP net.IP `json:"vpnIp"` LocalIndex uint32 `json:"localIndex"` RemoteIndex uint32 `json:"remoteIndex"` - RemoteAddrs []udpAddr `json:"remoteAddrs"` + RemoteAddrs []*udpAddr `json:"remoteAddrs"` CachedPackets int `json:"cachedPackets"` Cert *cert.NebulaCertificate `json:"cert"` MessageCounter uint64 `json:"messageCounter"` - CurrentRemote udpAddr `json:"currentRemote"` + CurrentRemote *udpAddr `json:"currentRemote"` } // Start actually runs nebula, this is a nonblocking call. To block use Control.ShutdownBlock() @@ -38,16 +38,7 @@ func (c *Control) Start() { // Stop signals nebula to shutdown, returns after the shutdown is complete func (c *Control) Stop() { //TODO: stop tun and udp routines, the lock on hostMap effectively does that though - //TODO: this is probably better as a function in ConnectionManager or HostMap directly - c.f.hostMap.Lock() - for _, h := range c.f.hostMap.Hosts { - if h.ConnectionState.ready { - c.f.send(closeTunnel, 0, h.ConnectionState, h, h.remote, []byte{}, make([]byte, 12, 12), make([]byte, mtu)) - c.l.WithField("vpnIp", IntIp(h.hostId)).WithField("udpAddr", h.remote). - Debug("Sending close tunnel message") - } - } - c.f.hostMap.Unlock() + c.CloseAllTunnels(false) c.l.Info("Goodbye") } @@ -149,13 +140,36 @@ func (c *Control) CloseTunnel(vpnIP uint32, localOnly bool) bool { return true } +// CloseAllTunnels is just like CloseTunnel except it goes through and shuts them all down, optionally you can avoid shutting down lighthouse tunnels +// the int returned is a count of tunnels closed +func (c *Control) CloseAllTunnels(excludeLighthouses bool) (closed int) { + //TODO: this is probably better as a function in ConnectionManager or HostMap directly + c.f.hostMap.Lock() + for _, h := range c.f.hostMap.Hosts { + if excludeLighthouses { + if _, ok := c.f.lightHouse.lighthouses[h.hostId]; ok { + continue + } + } + + if h.ConnectionState.ready { + c.f.send(closeTunnel, 0, h.ConnectionState, h, h.remote, []byte{}, make([]byte, 12, 12), make([]byte, mtu)) + c.l.WithField("vpnIp", IntIp(h.hostId)).WithField("udpAddr", h.remote). + Debug("Sending close tunnel message") + closed++ + } + } + c.f.hostMap.Unlock() + return +} + func copyHostInfo(h *HostInfo) ControlHostInfo { addrs := h.RemoteUDPAddrs() chi := ControlHostInfo{ VpnIP: int2ip(h.hostId), LocalIndex: h.localIndexId, RemoteIndex: h.remoteIndexId, - RemoteAddrs: make([]udpAddr, len(addrs), len(addrs)), + RemoteAddrs: make([]*udpAddr, len(addrs), len(addrs)), CachedPackets: len(h.packetStore), MessageCounter: atomic.LoadUint64(&h.ConnectionState.atomicMessageCounter), } @@ -165,7 +179,7 @@ func copyHostInfo(h *HostInfo) ControlHostInfo { } if h.remote != nil { - chi.CurrentRemote = *h.remote + chi.CurrentRemote = h.remote.Copy() } for i, addr := range addrs { diff --git a/control_test.go b/control_test.go index ca68c75..4f6beac 100644 --- a/control_test.go +++ b/control_test.go @@ -16,15 +16,15 @@ func TestControl_GetHostInfoByVpnIP(t *testing.T) { // Special care must be taken to re-use all objects provided to the hostmap and certificate in the expectedInfo object // To properly ensure we are not exposing core memory to the caller hm := NewHostMap("test", &net.IPNet{}, make([]*net.IPNet, 0)) - remote1 := NewUDPAddr(100, 4444) - remote2 := NewUDPAddr(101, 4444) + remote1 := NewUDPAddr(int2ip(100), 4444) + remote2 := NewUDPAddr(net.ParseIP("1:2:3:4:5:6:7:8"), 4444) ipNet := net.IPNet{ IP: net.IPv4(1, 2, 3, 4), Mask: net.IPMask{255, 255, 255, 0}, } ipNet2 := net.IPNet{ - IP: net.IPv4(1, 2, 3, 5), + IP: net.ParseIP("1:2:3:4:5:6:7:8"), Mask: net.IPMask{255, 255, 255, 0}, } @@ -80,11 +80,11 @@ func TestControl_GetHostInfoByVpnIP(t *testing.T) { VpnIP: net.IPv4(1, 2, 3, 4).To4(), LocalIndex: 201, RemoteIndex: 200, - RemoteAddrs: []udpAddr{*remote1, *remote2}, + RemoteAddrs: []*udpAddr{remote1, remote2}, CachedPackets: 0, Cert: crt.Copy(), MessageCounter: 0, - CurrentRemote: *NewUDPAddr(100, 4444), + CurrentRemote: NewUDPAddr(int2ip(100), 4444), } // Make sure we don't have any unexpected fields diff --git a/examples/config.yml b/examples/config.yml index fbae07f..768742d 100644 --- a/examples/config.yml +++ b/examples/config.yml @@ -74,6 +74,7 @@ lighthouse: # Port Nebula will be listening on. The default here is 4242. For a lighthouse node, the port should be defined, # however using port 0 will dynamically assign a port and is recommended for roaming nodes. listen: + # To listen on both any ipv4 and ipv6 use "[::]" host: 0.0.0.0 port: 4242 # Sets the max number of packets to pull from the kernel for each syscall (under systems that support recvmmsg) diff --git a/go.mod b/go.mod index b2a6319..93dc132 100644 --- a/go.mod +++ b/go.mod @@ -9,7 +9,7 @@ require ( github.com/cyberdelia/go-metrics-graphite v0.0.0-20161219230853-39f87cc3b432 github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 - github.com/golang/protobuf v1.3.2 + github.com/golang/protobuf v1.5.0 github.com/imdario/mergo v0.3.8 github.com/kardianos/service v1.1.0 github.com/konsorten/go-windows-terminal-sequences v1.0.2 // indirect @@ -29,6 +29,8 @@ require ( golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 golang.org/x/sys v0.0.0-20191210023423-ac6580df4449 + google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 // indirect + google.golang.org/protobuf v1.26.0 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect gopkg.in/yaml.v2 v2.2.7 ) diff --git a/go.sum b/go.sum index aa4d26d..a9247d6 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= @@ -11,15 +13,19 @@ github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0= github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.1.0 h1:yTUvW7Vhb89inJ+8irsUqiWjh8iT6sQPZiQzI6ReGkA= github.com/cespare/xxhash/v2 v2.1.0/go.mod h1:dgIUBU3pDso/gPgZ1osOZ0iQf77oPR28Tjxl5dIMyVM= github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cyberdelia/go-metrics-graphite v0.0.0-20161219230853-39f87cc3b432 h1:M5QgkYacWj0Xs8MhpIK/5uwU02icXpEoSo9sM2aRCps= github.com/cyberdelia/go-metrics-graphite v0.0.0-20161219230853-39f87cc3b432/go.mod h1:xwIwAxMvYnVrGJPe2FKx5prTrnAjGOD8zvDOnxnrrkM= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BHsljHzVlRcyQhjrss6TZTdY2VfCqZPbv5k3iBFa2ZQ= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/noise v0.0.0-20180327030543-2492fe189ae6 h1:u/UEqS66A5ckRmS4yNpjmVH56sVtS/RfclBAYocb4as= @@ -30,14 +36,31 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs= github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1 h1:ZFgWrT+bLgsYPirOnRfKLYJLvssAegOj/hgyMFdJZe0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.3.1 h1:Xye71clBPdm5HgqGwUkwhbynsUJZhDbS20FvLhQ2izg= github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/imdario/mergo v0.3.8 h1:CGgOkSJeqMRmt0D9XLWExdT4m4F1vd3FV3VPt+0VxkQ= github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA= @@ -118,19 +141,30 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975 h1:/Tl7pH94bvbAAHBdZJT947M/+gp0+CqQXDtMRC0fseo= golang.org/x/crypto v0.0.0-20200220183623-bac4c82f6975/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553 h1:efeOvDhwQ29Dj3SdAV/MJf8oukgn+8D8WgaCaRMchF8= golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY= golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190204203706-41f3e6584952/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -145,8 +179,34 @@ golang.org/x/sys v0.0.0-20191210023423-ac6580df4449/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= @@ -158,3 +218,5 @@ gopkg.in/yaml.v2 v2.2.7 h1:VUgggvou5XRW9mHwD/yXxIYSMtY0zoKQf/v226p2nyo= gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= diff --git a/handshake.go b/handshake.go index 6ed0014..aa4cd8f 100644 --- a/handshake.go +++ b/handshake.go @@ -6,7 +6,7 @@ const ( ) func HandleIncomingHandshake(f *Interface, addr *udpAddr, packet []byte, h *Header, hostinfo *HostInfo) { - if !f.lightHouse.remoteAllowList.Allow(udp2ipInt(addr)) { + if !f.lightHouse.remoteAllowList.Allow(addr.IP) { l.WithField("udpAddr", addr).Debug("lighthouse.remote_allow_list denied incoming handshake") return } diff --git a/handshake_ix.go b/handshake_ix.go index f7310d2..5d2dd84 100644 --- a/handshake_ix.go +++ b/handshake_ix.go @@ -186,7 +186,7 @@ func ixHandshakeStage1(f *Interface, addr *udpAddr, packet []byte, h *Header) { //l.Debugln("got symmetric pairs") //hostinfo.ClearRemotes() - hostinfo.AddRemote(*addr) + hostinfo.AddRemote(addr) hostinfo.ForcePromoteBest(f.hostMap.preferredRanges) hostinfo.CreateRemoteCIDR(remoteCert) @@ -358,7 +358,7 @@ func ixHandshakeStage2(f *Interface, addr *udpAddr, hostinfo *HostInfo, packet [ ci.eKey = NewNebulaCipherState(eKey) //l.Debugln("got symmetric pairs") - hostinfo.SetRemote(*addr) + hostinfo.SetRemote(addr) hostinfo.CreateRemoteCIDR(remoteCert) f.handshakeManager.Complete(hostinfo, f) diff --git a/handshake_manager_test.go b/handshake_manager_test.go index b1e1808..712028a 100644 --- a/handshake_manager_test.go +++ b/handshake_manager_test.go @@ -140,8 +140,8 @@ func Test_NewHandshakeManagerTrigger(t *testing.T) { hi := blah.pendingHostMap.Hosts[ip] assert.Nil(t, hi.remote) - lh.addrMap = map[uint32][]udpAddr{ - ip: {*NewUDPAddrFromString("10.1.1.1:4242")}, + lh.addrMap = map[uint32][]*udpAddr{ + ip: {NewUDPAddrFromString("10.1.1.1:4242")}, } // This should trigger the hostmap to populate the hostinfo diff --git a/hostmap.go b/hostmap.go index c252f42..9435f36 100644 --- a/hostmap.go +++ b/hostmap.go @@ -303,7 +303,7 @@ func (hm *HostMap) AddRemote(vpnIp uint32, remote *udpAddr) *HostInfo { hm.Lock() i, v := hm.Hosts[vpnIp] if v { - i.AddRemote(*remote) + i.AddRemote(remote) } else { i = &HostInfo{ Remotes: []*HostInfoDest{NewHostInfoDest(remote)}, @@ -424,10 +424,11 @@ func (hm *HostMap) Punchy(conn *udpConn) { metricsTxPunchy = metrics.NilCounter{} } + b := []byte{1} for { for _, addr := range hm.PunchList() { metricsTxPunchy.Inc(1) - conn.WriteTo([]byte{1}, addr) + conn.WriteTo(b, addr) } time.Sleep(time.Second * 30) } @@ -473,7 +474,7 @@ func (i *HostInfo) TryPromoteBest(preferredRanges []*net.IPNet, ifce *Interface) if atomic.AddUint32(&i.promoteCounter, 1)&PromoteEvery == 0 { // return early if we are already on a preferred remote - rIP := udp2ip(i.remote) + rIP := i.remote.IP for _, l := range preferredRanges { if l.Contains(rIP) { return @@ -506,7 +507,7 @@ func (i *HostInfo) ForcePromoteBest(preferredRanges []*net.IPNet) { func (i *HostInfo) getBestRemote(preferredRanges []*net.IPNet) (best *udpAddr, preferred bool) { if len(i.Remotes) > 0 { for _, r := range i.Remotes { - rIP := udp2ip(r.addr) + rIP := r.addr.IP for _, l := range preferredRanges { if l.Contains(rIP) { @@ -625,8 +626,7 @@ func (i *HostInfo) GetCert() *cert.NebulaCertificate { return nil } -func (i *HostInfo) AddRemote(r udpAddr) *udpAddr { - remote := &r +func (i *HostInfo) AddRemote(remote *udpAddr) *udpAddr { //add := true for _, r := range i.Remotes { if r.addr.Equals(remote) { @@ -638,12 +638,13 @@ func (i *HostInfo) AddRemote(r udpAddr) *udpAddr { if len(i.Remotes) > MaxRemotes { i.Remotes = i.Remotes[len(i.Remotes)-MaxRemotes:] } - i.Remotes = append(i.Remotes, NewHostInfoDest(remote)) - return remote + r := NewHostInfoDest(remote) + i.Remotes = append(i.Remotes, r) + return r.addr //l.Debugf("Added remote %s for vpn ip", remote) } -func (i *HostInfo) SetRemote(remote udpAddr) { +func (i *HostInfo) SetRemote(remote *udpAddr) { i.remote = i.AddRemote(remote) } @@ -701,7 +702,7 @@ func (i *HostInfo) logger() *logrus.Entry { func NewHostInfoDest(addr *udpAddr) *HostInfoDest { i := &HostInfoDest{ - addr: addr, + addr: addr.Copy(), } return i } @@ -816,8 +817,11 @@ func localIps(allowList *AllowList) *[]net.IP { case *net.IPAddr: ip = v.IP } - if ip.To4() != nil && ip.IsLoopback() == false { - allow := allowList.Allow(ip2int(ip)) + + //TODO: Filtering out link local for now, this is probably the most correct thing + //TODO: Would be nice to filter out SLAAC MAC based ips as well + if ip.IsLoopback() == false && !ip.IsLinkLocalUnicast() { + allow := allowList.Allow(ip) l.WithField("localIp", ip).WithField("allow", allow).Debug("localAllowList.Allow") if !allow { continue @@ -831,6 +835,7 @@ func localIps(allowList *AllowList) *[]net.IP { } func PrivateIP(ip net.IP) bool { + //TODO: Private for ipv6 or just let it ride? private := false _, private24BitBlock, _ := net.ParseCIDR("10.0.0.0/8") _, private20BitBlock, _ := net.ParseCIDR("172.16.0.0/12") diff --git a/hostmap_test.go b/hostmap_test.go index f2b2abe..bbc47b5 100644 --- a/hostmap_test.go +++ b/hostmap_test.go @@ -98,7 +98,7 @@ func TestHostmap(t *testing.T) { // Promotion should ensure that the best remote is chosen (y) info.ForcePromoteBest(myNets) - assert.True(t, myNet.Contains(udp2ip(info.remote))) + assert.True(t, myNet.Contains(info.remote.IP)) } @@ -125,27 +125,29 @@ func TestHostMap_rotateRemote(t *testing.T) { assert.Nil(t, h.remote) // 1 remote, no panic - h.AddRemote(*NewUDPAddr(ip2int(net.IP{1, 1, 1, 1}), 0)) + h.AddRemote(NewUDPAddr(net.IP{1, 1, 1, 1}, 0)) h.rotateRemote() - assert.Equal(t, udp2ipInt(h.remote), ip2int(net.IP{1, 1, 1, 1})) + assert.Equal(t, h.remote.IP, net.IP{1, 1, 1, 1}) - h.AddRemote(*NewUDPAddr(ip2int(net.IP{1, 1, 1, 2}), 0)) - h.AddRemote(*NewUDPAddr(ip2int(net.IP{1, 1, 1, 3}), 0)) - h.AddRemote(*NewUDPAddr(ip2int(net.IP{1, 1, 1, 4}), 0)) + h.AddRemote(NewUDPAddr(net.IP{1, 1, 1, 2}, 0)) + h.AddRemote(NewUDPAddr(net.IP{1, 1, 1, 3}, 0)) + h.AddRemote(NewUDPAddr(net.IP{1, 1, 1, 4}, 0)) + + //TODO: ensure we are copying and not storing the slice! // Rotate through those 3 h.rotateRemote() - assert.Equal(t, udp2ipInt(h.remote), ip2int(net.IP{1, 1, 1, 2})) + assert.Equal(t, h.remote.IP, net.IP{1, 1, 1, 2}) h.rotateRemote() - assert.Equal(t, udp2ipInt(h.remote), ip2int(net.IP{1, 1, 1, 3})) + assert.Equal(t, h.remote.IP, net.IP{1, 1, 1, 3}) h.rotateRemote() - assert.Equal(t, udp2ipInt(h.remote), ip2int(net.IP{1, 1, 1, 4})) + assert.Equal(t, h.remote, &udpAddr{IP: net.IP{1, 1, 1, 4}, Port: 0}) // Finally, we should start over h.rotateRemote() - assert.Equal(t, udp2ipInt(h.remote), ip2int(net.IP{1, 1, 1, 1})) + assert.Equal(t, h.remote, &udpAddr{IP: net.IP{1, 1, 1, 1}, Port: 0}) } func BenchmarkHostmappromote2(b *testing.B) { diff --git a/lighthouse.go b/lighthouse.go index c83d59f..861fe77 100644 --- a/lighthouse.go +++ b/lighthouse.go @@ -9,6 +9,7 @@ import ( "github.com/golang/protobuf/proto" "github.com/rcrowley/go-metrics" + "github.com/sirupsen/logrus" "github.com/slackhq/nebula/cert" ) @@ -21,7 +22,7 @@ type LightHouse struct { punchConn *udpConn // Local cache of answers from light houses - addrMap map[uint32][]udpAddr + addrMap map[uint32][]*udpAddr // filters remote addresses allowed for each host // - When we are a lighthouse, this filters what addresses we store and @@ -41,7 +42,7 @@ type LightHouse struct { staticList map[uint32]struct{} lighthouses map[uint32]struct{} interval int - nebulaPort uint32 + nebulaPort uint32 // 32 bits because protobuf does not have a uint16 punchBack bool punchDelay time.Duration @@ -58,7 +59,7 @@ func NewLightHouse(amLighthouse bool, myIp uint32, ips []uint32, interval int, n h := LightHouse{ amLighthouse: amLighthouse, myIp: myIp, - addrMap: make(map[uint32][]udpAddr), + addrMap: make(map[uint32][]*udpAddr), nebulaPort: nebulaPort, lighthouses: make(map[uint32]struct{}), staticList: make(map[uint32]struct{}), @@ -106,7 +107,7 @@ func (lh *LightHouse) ValidateLHStaticEntries() error { return nil } -func (lh *LightHouse) Query(ip uint32, f EncWriter) ([]udpAddr, error) { +func (lh *LightHouse) Query(ip uint32, f EncWriter) ([]*udpAddr, error) { if !lh.IsLighthouseIP(ip) { lh.QueryServer(ip, f) } @@ -139,7 +140,7 @@ func (lh *LightHouse) QueryServer(ip uint32, f EncWriter) { } // Query our local lighthouse cached results -func (lh *LightHouse) QueryCache(ip uint32) []udpAddr { +func (lh *LightHouse) QueryCache(ip uint32) []*udpAddr { lh.RLock() if v, ok := lh.addrMap[ip]; ok { lh.RUnlock() @@ -179,7 +180,7 @@ func (lh *LightHouse) AddRemote(vpnIP uint32, toIp *udpAddr, static bool) { } } - allow := lh.remoteAllowList.Allow(udp2ipInt(toIp)) + allow := lh.remoteAllowList.Allow(toIp.IP) l.WithField("remoteIp", toIp).WithField("allow", allow).Debug("remoteAllowList.Allow") if !allow { return @@ -189,7 +190,8 @@ func (lh *LightHouse) AddRemote(vpnIP uint32, toIp *udpAddr, static bool) { if static { lh.staticList[vpnIP] = struct{}{} } - lh.addrMap[vpnIP] = append(lh.addrMap[vpnIP], *toIp) + + lh.addrMap[vpnIP] = append(lh.addrMap[vpnIP], toIp.Copy()) } func (lh *LightHouse) AddRemoteAndReset(vpnIP uint32, toIp *udpAddr) { @@ -216,12 +218,41 @@ func NewLhQueryByInt(VpnIp uint32) *NebulaMeta { } } -func NewIpAndPort(ip net.IP, port uint32) IpAndPort { - return IpAndPort{Ip: ip2int(ip), Port: port} +type ip4Or6 struct { + v4 IpAndPort + v6 Ip6AndPort } -func NewIpAndPortFromUDPAddr(addr udpAddr) IpAndPort { - return IpAndPort{Ip: udp2ipInt(&addr), Port: uint32(addr.Port)} +func NewIpAndPort(ip net.IP, port uint32) ip4Or6 { + ipp := ip4Or6{} + + if ipv4 := ip.To4(); ipv4 != nil { + ipp.v4 = IpAndPort{Port: port} + ipp.v4.Ip = ip2int(ip) + + } else { + ipp.v6 = Ip6AndPort{Port: port} + ipp.v6.Ip = make([]byte, len(ip)) + copy(ipp.v6.Ip, ip) + } + + return ipp +} + +func NewIpAndPortFromUDPAddr(addr *udpAddr) ip4Or6 { + return NewIpAndPort(addr.IP, uint32(addr.Port)) +} + +func NewUDPAddrFromLH4(ipp *IpAndPort) *udpAddr { + ip := ipp.Ip + return NewUDPAddr( + net.IPv4(byte(ip&0xff000000>>24), byte(ip&0x00ff0000>>16), byte(ip&0x0000ff00>>8), byte(ip&0x000000ff)), + uint16(ipp.Port), + ) +} + +func NewUDPAddrFromLH6(ipp *Ip6AndPort) *udpAddr { + return NewUDPAddr(ipp.Ip, uint16(ipp.Port)) } func (lh *LightHouse) LhUpdateWorker(f EncWriter) { @@ -236,20 +267,27 @@ func (lh *LightHouse) LhUpdateWorker(f EncWriter) { } func (lh *LightHouse) SendUpdate(f EncWriter) { - var ipps []*IpAndPort + var v4 []*IpAndPort + var v6 []*Ip6AndPort for _, e := range *localIps(lh.localAllowList) { // Only add IPs that aren't my VPN/tun IP if ip2int(e) != lh.myIp { ipp := NewIpAndPort(e, lh.nebulaPort) - ipps = append(ipps, &ipp) + if len(ipp.v6.Ip) > 0 { + v6 = append(v6, &ipp.v6) + } else { + v4 = append(v4, &ipp.v4) + } + } } m := &NebulaMeta{ Type: NebulaMeta_HostUpdateNotification, Details: &NebulaMetaDetails{ - VpnIp: lh.myIp, - IpAndPorts: ipps, + VpnIp: lh.myIp, + IpAndPorts: v4, + Ip6AndPorts: v6, }, } @@ -272,8 +310,8 @@ type LightHouseHandler struct { nb []byte out []byte meta *NebulaMeta - iap []IpAndPort - iapp []*IpAndPort + iap []ip4Or6 + iapp []*ip4Or6 } func (lh *LightHouse) NewRequestHandler() *LightHouseHandler { @@ -306,8 +344,8 @@ func (lhh *LightHouseHandler) resetMeta() *NebulaMeta { func (lhh *LightHouseHandler) resizeIpAndPorts(n int) { if cap(lhh.iap) < n { - lhh.iap = make([]IpAndPort, n) - lhh.iapp = make([]*IpAndPort, n) + lhh.iap = make([]ip4Or6, n) + lhh.iapp = make([]*ip4Or6, n) for i := range lhh.iap { lhh.iapp[i] = &lhh.iap[i] @@ -317,7 +355,7 @@ func (lhh *LightHouseHandler) resizeIpAndPorts(n int) { lhh.iapp = lhh.iapp[:n] } -func (lhh *LightHouseHandler) setIpAndPortsFromNetIps(ips []udpAddr) []*IpAndPort { +func (lhh *LightHouseHandler) setIpAndPortsFromNetIps(ips []*udpAddr) []*ip4Or6 { lhh.resizeIpAndPorts(len(ips)) for i, e := range ips { lhh.iap[i] = NewIpAndPortFromUDPAddr(e) @@ -363,7 +401,25 @@ func (lhh *LightHouseHandler) HandleRequest(rAddr *udpAddr, vpnIp uint32, p []by n = lhh.resetMeta() n.Type = NebulaMeta_HostQueryReply n.Details.VpnIp = reqVpnIP - n.Details.IpAndPorts = lhh.setIpAndPortsFromNetIps(ips) + + v4s := make([]*IpAndPort, 0) + v6s := make([]*Ip6AndPort, 0) + for _, v := range lhh.setIpAndPortsFromNetIps(ips) { + if len(v.v6.Ip) > 0 { + v6s = append(v6s, &v.v6) + } else { + v4s = append(v4s, &v.v4) + } + } + + if len(v4s) > 0 { + n.Details.IpAndPorts = v4s + } + + if len(v6s) > 0 { + n.Details.Ip6AndPorts = v6s + } + reply, err := proto.Marshal(n) if err != nil { l.WithError(err).WithField("vpnIp", IntIp(vpnIp)).Error("Failed to marshal lighthouse host query reply") @@ -382,7 +438,25 @@ func (lhh *LightHouseHandler) HandleRequest(rAddr *udpAddr, vpnIp uint32, p []by n = lhh.resetMeta() n.Type = NebulaMeta_HostPunchNotification n.Details.VpnIp = vpnIp - n.Details.IpAndPorts = lhh.setIpAndPortsFromNetIps(ips) + + v4s := make([]*IpAndPort, 0) + v6s := make([]*Ip6AndPort, 0) + for _, v := range lhh.setIpAndPortsFromNetIps(ips) { + if len(v.v6.Ip) > 0 { + v6s = append(v6s, &v.v6) + } else { + v4s = append(v4s, &v.v4) + } + } + + if len(v4s) > 0 { + n.Details.IpAndPorts = v4s + } + + if len(v6s) > 0 { + n.Details.Ip6AndPorts = v6s + } + reply, _ := proto.Marshal(n) lh.metricTx(NebulaMeta_HostPunchNotification, 1) f.SendMessageToVpnIp(lightHouse, 0, reqVpnIP, reply, lhh.nb, lhh.out[:0]) @@ -394,11 +468,21 @@ func (lhh *LightHouseHandler) HandleRequest(rAddr *udpAddr, vpnIp uint32, p []by if !lh.IsLighthouseIP(vpnIp) { return } + for _, a := range n.Details.IpAndPorts { - //first := n.Details.IpAndPorts[0] - ans := NewUDPAddr(a.Ip, uint16(a.Port)) - lh.AddRemote(n.Details.VpnIp, ans, false) + ans := NewUDPAddrFromLH4(a) + if ans != nil { + lh.AddRemote(n.Details.VpnIp, ans, false) + } } + + for _, a := range n.Details.Ip6AndPorts { + ans := NewUDPAddrFromLH6(a) + if ans != nil { + lh.AddRemote(n.Details.VpnIp, ans, false) + } + } + // Non-blocking attempt to trigger, skip if it would block select { case lh.handshakeTrigger <- n.Details.VpnIp: @@ -411,10 +495,21 @@ func (lhh *LightHouseHandler) HandleRequest(rAddr *udpAddr, vpnIp uint32, p []by l.WithField("vpnIp", IntIp(vpnIp)).WithField("answer", IntIp(n.Details.VpnIp)).Debugln("Host sent invalid update") return } + for _, a := range n.Details.IpAndPorts { - ans := NewUDPAddr(a.Ip, uint16(a.Port)) - lh.AddRemote(n.Details.VpnIp, ans, false) + ans := NewUDPAddrFromLH4(a) + if ans != nil { + lh.AddRemote(n.Details.VpnIp, ans, false) + } } + + for _, a := range n.Details.Ip6AndPorts { + ans := NewUDPAddrFromLH6(a) + if ans != nil { + lh.AddRemote(n.Details.VpnIp, ans, false) + } + } + case NebulaMeta_HostMovedNotification: case NebulaMeta_HostPunchNotification: if !lh.IsLighthouseIP(vpnIp) { @@ -423,15 +518,43 @@ func (lhh *LightHouseHandler) HandleRequest(rAddr *udpAddr, vpnIp uint32, p []by empty := []byte{0} for _, a := range n.Details.IpAndPorts { - vpnPeer := NewUDPAddr(a.Ip, uint16(a.Port)) + vpnPeer := NewUDPAddrFromLH4(a) + if vpnPeer == nil { + continue + } + go func() { time.Sleep(lh.punchDelay) lh.metricHolepunchTx.Inc(1) lh.punchConn.WriteTo(empty, vpnPeer) }() - l.Debugf("Punching %s on %d for %s", IntIp(a.Ip), a.Port, IntIp(n.Details.VpnIp)) + + if l.Level >= logrus.DebugLevel { + //TODO: lacking the ip we are actually punching on, old: l.Debugf("Punching %s on %d for %s", IntIp(a.Ip), a.Port, IntIp(n.Details.VpnIp)) + l.Debugf("Punching on %d for %s", a.Port, IntIp(n.Details.VpnIp)) + } } + + for _, a := range n.Details.Ip6AndPorts { + vpnPeer := NewUDPAddrFromLH6(a) + if vpnPeer == nil { + continue + } + + go func() { + time.Sleep(lh.punchDelay) + lh.metricHolepunchTx.Inc(1) + lh.punchConn.WriteTo(empty, vpnPeer) + + }() + + if l.Level >= logrus.DebugLevel { + //TODO: lacking the ip we are actually punching on, old: l.Debugf("Punching %s on %d for %s", IntIp(a.Ip), a.Port, IntIp(n.Details.VpnIp)) + l.Debugf("Punching on %d for %s", a.Port, IntIp(n.Details.VpnIp)) + } + } + // This sends a nebula test packet to the host trying to contact us. In the case // of a double nat or other difficult scenario, this may help establish // a tunnel. diff --git a/lighthouse_test.go b/lighthouse_test.go index 71a7aa2..edd4d7a 100644 --- a/lighthouse_test.go +++ b/lighthouse_test.go @@ -8,6 +8,17 @@ import ( "github.com/stretchr/testify/assert" ) +//TODO: Add a test to ensure udpAddr is copied and not reused + +func TestOldIPv4Only(t *testing.T) { + // This test ensures our new ipv6 enabled LH protobuf IpAndPorts works with the old style to enable backwards compatibility + b := []byte{8, 129, 130, 132, 80, 16, 10} + var m IpAndPort + err := proto.Unmarshal(b, &m) + assert.NoError(t, err) + assert.Equal(t, "10.1.1.1", int2ip(m.GetIp()).String()) +} + func TestNewLhQuery(t *testing.T) { myIp := net.ParseIP("192.1.1.1") myIpint := ip2int(myIp) @@ -31,24 +42,24 @@ func TestNewLhQuery(t *testing.T) { func TestNewipandportfromudpaddr(t *testing.T) { blah := NewUDPAddrFromString("1.2.2.3:12345") - meh := NewIpAndPortFromUDPAddr(*blah) - assert.Equal(t, uint32(16908803), meh.Ip) - assert.Equal(t, uint32(12345), meh.Port) + meh := NewIpAndPortFromUDPAddr(blah) + assert.Equal(t, uint32(16908803), meh.v4.Ip) + assert.Equal(t, uint32(12345), meh.v4.Port) } func TestSetipandportsfromudpaddrs(t *testing.T) { blah := NewUDPAddrFromString("1.2.2.3:12345") blah2 := NewUDPAddrFromString("9.9.9.9:47828") - group := []udpAddr{*blah, *blah2} + group := []*udpAddr{blah, blah2} var lh *LightHouse lhh := lh.NewRequestHandler() result := lhh.setIpAndPortsFromNetIps(group) - assert.IsType(t, []*IpAndPort{}, result) + assert.IsType(t, []*ip4Or6{}, result) assert.Len(t, result, 2) - assert.Equal(t, uint32(0x01020203), result[0].Ip) - assert.Equal(t, uint32(12345), result[0].Port) - assert.Equal(t, uint32(0x09090909), result[1].Ip) - assert.Equal(t, uint32(47828), result[1].Port) + assert.Equal(t, uint32(0x01020203), result[0].v4.Ip) + assert.Equal(t, uint32(12345), result[0].v4.Port) + assert.Equal(t, uint32(0x09090909), result[1].v4.Ip) + assert.Equal(t, uint32(47828), result[1].v4.Port) //t.Error(reflect.TypeOf(hah)) } @@ -60,7 +71,7 @@ func Test_lhStaticMapping(t *testing.T) { udpServer, _ := NewListener("0.0.0.0", 0, true) meh := NewLightHouse(true, 1, []uint32{ip2int(lh1IP)}, 10, 10003, udpServer, false, 1, false) - meh.AddRemote(ip2int(lh1IP), NewUDPAddr(ip2int(lh1IP), uint16(4242)), true) + meh.AddRemote(ip2int(lh1IP), NewUDPAddr(lh1IP, uint16(4242)), true) err := meh.ValidateLHStaticEntries() assert.Nil(t, err) @@ -68,7 +79,7 @@ func Test_lhStaticMapping(t *testing.T) { lh2IP := net.ParseIP(lh2) meh = NewLightHouse(true, 1, []uint32{ip2int(lh1IP), ip2int(lh2IP)}, 10, 10003, udpServer, false, 1, false) - meh.AddRemote(ip2int(lh1IP), NewUDPAddr(ip2int(lh1IP), uint16(4242)), true) + meh.AddRemote(ip2int(lh1IP), NewUDPAddr(lh1IP, uint16(4242)), true) err = meh.ValidateLHStaticEntries() assert.EqualError(t, err, "Lighthouse 10.128.0.3 does not have a static_host_map entry") } @@ -83,11 +94,11 @@ func BenchmarkLighthouseHandleRequest(b *testing.B) { hAddr := NewUDPAddrFromString("4.5.6.7:12345") hAddr2 := NewUDPAddrFromString("4.5.6.7:12346") - lh.addrMap[3] = []udpAddr{*hAddr, *hAddr2} + lh.addrMap[3] = []*udpAddr{hAddr, hAddr2} rAddr := NewUDPAddrFromString("1.2.2.3:12345") rAddr2 := NewUDPAddrFromString("1.2.2.3:12346") - lh.addrMap[2] = []udpAddr{*rAddr, *rAddr2} + lh.addrMap[2] = []*udpAddr{rAddr, rAddr2} mw := &mockEncWriter{} @@ -142,15 +153,17 @@ func Test_lhRemoteAllowList(t *testing.T) { remote1 := "10.20.0.3" remote1IP := net.ParseIP(remote1) - lh.AddRemote(ip2int(remote1IP), NewUDPAddr(ip2int(remote1IP), uint16(4242)), true) + lh.AddRemote(ip2int(remote1IP), NewUDPAddr(remote1IP, uint16(4242)), true) assert.Nil(t, lh.addrMap[ip2int(remote1IP)]) remote2 := "10.128.0.3" remote2IP := net.ParseIP(remote2) - remote2UDPAddr := NewUDPAddr(ip2int(remote2IP), uint16(4242)) + remote2UDPAddr := NewUDPAddr(remote2IP, uint16(4242)) lh.AddRemote(ip2int(remote2IP), remote2UDPAddr, true) - assert.Equal(t, remote2UDPAddr, &lh.addrMap[ip2int(remote2IP)][0]) + // Make sure the pointers are different but the contents are equal since we are using slices + assert.False(t, remote2UDPAddr == lh.addrMap[ip2int(remote2IP)][0]) + assert.Equal(t, remote2UDPAddr, lh.addrMap[ip2int(remote2IP)][0]) } //func NewLightHouse(amLighthouse bool, myIp uint32, ips []string, interval int, nebulaPort int, pc *udpConn, punchBack bool) *LightHouse { diff --git a/main.go b/main.go index dc0469d..e4c937a 100644 --- a/main.go +++ b/main.go @@ -4,8 +4,6 @@ import ( "encoding/binary" "fmt" "net" - "strconv" - "strings" "time" "github.com/sirupsen/logrus" @@ -301,28 +299,19 @@ func Main(config *Config, configTest bool, buildVersion string, logger *logrus.L vals, ok := v.([]interface{}) if ok { for _, v := range vals { - parts := strings.Split(fmt.Sprintf("%v", v), ":") - addr, err := net.ResolveIPAddr("ip", parts[0]) + ip, port, err := parseIPAndPort(fmt.Sprintf("%v", v)) if err == nil { - ip := addr.IP - port, err := strconv.Atoi(parts[1]) - if err != nil { - return nil, NewContextualError("Static host address could not be parsed", m{"vpnIp": vpnIp}, err) - } - lightHouse.AddRemote(ip2int(vpnIp), NewUDPAddr(ip2int(ip), uint16(port)), true) + lightHouse.AddRemote(ip2int(vpnIp), NewUDPAddr(ip, port), true) + } else { + return nil, NewContextualError("Static host address could not be parsed", m{"vpnIp": vpnIp}, err) } } } else { - //TODO: make this all a helper - parts := strings.Split(fmt.Sprintf("%v", v), ":") - addr, err := net.ResolveIPAddr("ip", parts[0]) + ip, port, err := parseIPAndPort(fmt.Sprintf("%v", v)) if err == nil { - ip := addr.IP - port, err := strconv.Atoi(parts[1]) - if err != nil { - return nil, NewContextualError("Static host address could not be parsed", m{"vpnIp": vpnIp}, err) - } - lightHouse.AddRemote(ip2int(vpnIp), NewUDPAddr(ip2int(ip), uint16(port)), true) + lightHouse.AddRemote(ip2int(vpnIp), NewUDPAddr(ip, port), true) + } else { + return nil, NewContextualError("Static host address could not be parsed", m{"vpnIp": vpnIp}, err) } } } diff --git a/nebula.pb.go b/nebula.pb.go index 22f7498..9ca3b1a 100644 --- a/nebula.pb.go +++ b/nebula.pb.go @@ -1,24 +1,24 @@ // Code generated by protoc-gen-go. DO NOT EDIT. +// versions: +// protoc-gen-go v1.26.0 +// protoc v3.14.0 // source: nebula.proto package nebula import ( - fmt "fmt" - proto "github.com/golang/protobuf/proto" - math "math" + protoreflect "google.golang.org/protobuf/reflect/protoreflect" + protoimpl "google.golang.org/protobuf/runtime/protoimpl" + reflect "reflect" + sync "sync" ) -// Reference imports to suppress errors if they are not otherwise used. -var _ = proto.Marshal -var _ = fmt.Errorf -var _ = math.Inf - -// This is a compile-time assertion to ensure that this generated file -// is compatible with the proto package it is being compiled against. -// A compilation error at this line likely means your copy of the -// proto package needs to be updated. -const _ = proto.ProtoPackageIsVersion3 // please upgrade the proto package +const ( + // Verify that this generated code is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion) + // Verify that runtime/protoimpl is sufficiently up-to-date. + _ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20) +) type NebulaMeta_MessageType int32 @@ -35,38 +35,59 @@ const ( NebulaMeta_PathCheckReply NebulaMeta_MessageType = 9 ) -var NebulaMeta_MessageType_name = map[int32]string{ - 0: "None", - 1: "HostQuery", - 2: "HostQueryReply", - 3: "HostUpdateNotification", - 4: "HostMovedNotification", - 5: "HostPunchNotification", - 6: "HostWhoami", - 7: "HostWhoamiReply", - 8: "PathCheck", - 9: "PathCheckReply", -} +// Enum value maps for NebulaMeta_MessageType. +var ( + NebulaMeta_MessageType_name = map[int32]string{ + 0: "None", + 1: "HostQuery", + 2: "HostQueryReply", + 3: "HostUpdateNotification", + 4: "HostMovedNotification", + 5: "HostPunchNotification", + 6: "HostWhoami", + 7: "HostWhoamiReply", + 8: "PathCheck", + 9: "PathCheckReply", + } + NebulaMeta_MessageType_value = map[string]int32{ + "None": 0, + "HostQuery": 1, + "HostQueryReply": 2, + "HostUpdateNotification": 3, + "HostMovedNotification": 4, + "HostPunchNotification": 5, + "HostWhoami": 6, + "HostWhoamiReply": 7, + "PathCheck": 8, + "PathCheckReply": 9, + } +) -var NebulaMeta_MessageType_value = map[string]int32{ - "None": 0, - "HostQuery": 1, - "HostQueryReply": 2, - "HostUpdateNotification": 3, - "HostMovedNotification": 4, - "HostPunchNotification": 5, - "HostWhoami": 6, - "HostWhoamiReply": 7, - "PathCheck": 8, - "PathCheckReply": 9, +func (x NebulaMeta_MessageType) Enum() *NebulaMeta_MessageType { + p := new(NebulaMeta_MessageType) + *p = x + return p } func (x NebulaMeta_MessageType) String() string { - return proto.EnumName(NebulaMeta_MessageType_name, int32(x)) + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } +func (NebulaMeta_MessageType) Descriptor() protoreflect.EnumDescriptor { + return file_nebula_proto_enumTypes[0].Descriptor() +} + +func (NebulaMeta_MessageType) Type() protoreflect.EnumType { + return &file_nebula_proto_enumTypes[0] +} + +func (x NebulaMeta_MessageType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use NebulaMeta_MessageType.Descriptor instead. func (NebulaMeta_MessageType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_2d65afa7693df5ef, []int{0, 0} + return file_nebula_proto_rawDescGZIP(), []int{0, 0} } type NebulaPing_MessageType int32 @@ -76,382 +97,689 @@ const ( NebulaPing_Reply NebulaPing_MessageType = 1 ) -var NebulaPing_MessageType_name = map[int32]string{ - 0: "Ping", - 1: "Reply", -} +// Enum value maps for NebulaPing_MessageType. +var ( + NebulaPing_MessageType_name = map[int32]string{ + 0: "Ping", + 1: "Reply", + } + NebulaPing_MessageType_value = map[string]int32{ + "Ping": 0, + "Reply": 1, + } +) -var NebulaPing_MessageType_value = map[string]int32{ - "Ping": 0, - "Reply": 1, +func (x NebulaPing_MessageType) Enum() *NebulaPing_MessageType { + p := new(NebulaPing_MessageType) + *p = x + return p } func (x NebulaPing_MessageType) String() string { - return proto.EnumName(NebulaPing_MessageType_name, int32(x)) + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) } +func (NebulaPing_MessageType) Descriptor() protoreflect.EnumDescriptor { + return file_nebula_proto_enumTypes[1].Descriptor() +} + +func (NebulaPing_MessageType) Type() protoreflect.EnumType { + return &file_nebula_proto_enumTypes[1] +} + +func (x NebulaPing_MessageType) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use NebulaPing_MessageType.Descriptor instead. func (NebulaPing_MessageType) EnumDescriptor() ([]byte, []int) { - return fileDescriptor_2d65afa7693df5ef, []int{3, 0} + return file_nebula_proto_rawDescGZIP(), []int{4, 0} } type NebulaMeta struct { - Type NebulaMeta_MessageType `protobuf:"varint,1,opt,name=Type,json=type,proto3,enum=nebula.NebulaMeta_MessageType" json:"Type,omitempty"` - Details *NebulaMetaDetails `protobuf:"bytes,2,opt,name=Details,json=details,proto3" json:"Details,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type NebulaMeta_MessageType `protobuf:"varint,1,opt,name=Type,proto3,enum=nebula.NebulaMeta_MessageType" json:"Type,omitempty"` + Details *NebulaMetaDetails `protobuf:"bytes,2,opt,name=Details,proto3" json:"Details,omitempty"` } -func (m *NebulaMeta) Reset() { *m = NebulaMeta{} } -func (m *NebulaMeta) String() string { return proto.CompactTextString(m) } -func (*NebulaMeta) ProtoMessage() {} +func (x *NebulaMeta) Reset() { + *x = NebulaMeta{} + if protoimpl.UnsafeEnabled { + mi := &file_nebula_proto_msgTypes[0] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NebulaMeta) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NebulaMeta) ProtoMessage() {} + +func (x *NebulaMeta) ProtoReflect() protoreflect.Message { + mi := &file_nebula_proto_msgTypes[0] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NebulaMeta.ProtoReflect.Descriptor instead. func (*NebulaMeta) Descriptor() ([]byte, []int) { - return fileDescriptor_2d65afa7693df5ef, []int{0} + return file_nebula_proto_rawDescGZIP(), []int{0} } -func (m *NebulaMeta) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_NebulaMeta.Unmarshal(m, b) -} -func (m *NebulaMeta) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_NebulaMeta.Marshal(b, m, deterministic) -} -func (m *NebulaMeta) XXX_Merge(src proto.Message) { - xxx_messageInfo_NebulaMeta.Merge(m, src) -} -func (m *NebulaMeta) XXX_Size() int { - return xxx_messageInfo_NebulaMeta.Size(m) -} -func (m *NebulaMeta) XXX_DiscardUnknown() { - xxx_messageInfo_NebulaMeta.DiscardUnknown(m) -} - -var xxx_messageInfo_NebulaMeta proto.InternalMessageInfo - -func (m *NebulaMeta) GetType() NebulaMeta_MessageType { - if m != nil { - return m.Type +func (x *NebulaMeta) GetType() NebulaMeta_MessageType { + if x != nil { + return x.Type } return NebulaMeta_None } -func (m *NebulaMeta) GetDetails() *NebulaMetaDetails { - if m != nil { - return m.Details +func (x *NebulaMeta) GetDetails() *NebulaMetaDetails { + if x != nil { + return x.Details } return nil } type NebulaMetaDetails struct { - VpnIp uint32 `protobuf:"varint,1,opt,name=VpnIp,json=vpnIp,proto3" json:"VpnIp,omitempty"` - IpAndPorts []*IpAndPort `protobuf:"bytes,2,rep,name=IpAndPorts,json=ipAndPorts,proto3" json:"IpAndPorts,omitempty"` - Counter uint32 `protobuf:"varint,3,opt,name=counter,proto3" json:"counter,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + VpnIp uint32 `protobuf:"varint,1,opt,name=VpnIp,proto3" json:"VpnIp,omitempty"` + IpAndPorts []*IpAndPort `protobuf:"bytes,2,rep,name=IpAndPorts,proto3" json:"IpAndPorts,omitempty"` + Ip6AndPorts []*Ip6AndPort `protobuf:"bytes,4,rep,name=Ip6AndPorts,proto3" json:"Ip6AndPorts,omitempty"` + Counter uint32 `protobuf:"varint,3,opt,name=counter,proto3" json:"counter,omitempty"` } -func (m *NebulaMetaDetails) Reset() { *m = NebulaMetaDetails{} } -func (m *NebulaMetaDetails) String() string { return proto.CompactTextString(m) } -func (*NebulaMetaDetails) ProtoMessage() {} +func (x *NebulaMetaDetails) Reset() { + *x = NebulaMetaDetails{} + if protoimpl.UnsafeEnabled { + mi := &file_nebula_proto_msgTypes[1] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NebulaMetaDetails) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NebulaMetaDetails) ProtoMessage() {} + +func (x *NebulaMetaDetails) ProtoReflect() protoreflect.Message { + mi := &file_nebula_proto_msgTypes[1] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NebulaMetaDetails.ProtoReflect.Descriptor instead. func (*NebulaMetaDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_2d65afa7693df5ef, []int{1} + return file_nebula_proto_rawDescGZIP(), []int{1} } -func (m *NebulaMetaDetails) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_NebulaMetaDetails.Unmarshal(m, b) -} -func (m *NebulaMetaDetails) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_NebulaMetaDetails.Marshal(b, m, deterministic) -} -func (m *NebulaMetaDetails) XXX_Merge(src proto.Message) { - xxx_messageInfo_NebulaMetaDetails.Merge(m, src) -} -func (m *NebulaMetaDetails) XXX_Size() int { - return xxx_messageInfo_NebulaMetaDetails.Size(m) -} -func (m *NebulaMetaDetails) XXX_DiscardUnknown() { - xxx_messageInfo_NebulaMetaDetails.DiscardUnknown(m) -} - -var xxx_messageInfo_NebulaMetaDetails proto.InternalMessageInfo - -func (m *NebulaMetaDetails) GetVpnIp() uint32 { - if m != nil { - return m.VpnIp +func (x *NebulaMetaDetails) GetVpnIp() uint32 { + if x != nil { + return x.VpnIp } return 0 } -func (m *NebulaMetaDetails) GetIpAndPorts() []*IpAndPort { - if m != nil { - return m.IpAndPorts +func (x *NebulaMetaDetails) GetIpAndPorts() []*IpAndPort { + if x != nil { + return x.IpAndPorts } return nil } -func (m *NebulaMetaDetails) GetCounter() uint32 { - if m != nil { - return m.Counter +func (x *NebulaMetaDetails) GetIp6AndPorts() []*Ip6AndPort { + if x != nil { + return x.Ip6AndPorts + } + return nil +} + +func (x *NebulaMetaDetails) GetCounter() uint32 { + if x != nil { + return x.Counter } return 0 } type IpAndPort struct { - Ip uint32 `protobuf:"varint,1,opt,name=Ip,json=ip,proto3" json:"Ip,omitempty"` - Port uint32 `protobuf:"varint,2,opt,name=Port,json=port,proto3" json:"Port,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ip uint32 `protobuf:"varint,1,opt,name=Ip,proto3" json:"Ip,omitempty"` + Port uint32 `protobuf:"varint,2,opt,name=Port,proto3" json:"Port,omitempty"` } -func (m *IpAndPort) Reset() { *m = IpAndPort{} } -func (m *IpAndPort) String() string { return proto.CompactTextString(m) } -func (*IpAndPort) ProtoMessage() {} +func (x *IpAndPort) Reset() { + *x = IpAndPort{} + if protoimpl.UnsafeEnabled { + mi := &file_nebula_proto_msgTypes[2] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *IpAndPort) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*IpAndPort) ProtoMessage() {} + +func (x *IpAndPort) ProtoReflect() protoreflect.Message { + mi := &file_nebula_proto_msgTypes[2] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use IpAndPort.ProtoReflect.Descriptor instead. func (*IpAndPort) Descriptor() ([]byte, []int) { - return fileDescriptor_2d65afa7693df5ef, []int{2} + return file_nebula_proto_rawDescGZIP(), []int{2} } -func (m *IpAndPort) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_IpAndPort.Unmarshal(m, b) -} -func (m *IpAndPort) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_IpAndPort.Marshal(b, m, deterministic) -} -func (m *IpAndPort) XXX_Merge(src proto.Message) { - xxx_messageInfo_IpAndPort.Merge(m, src) -} -func (m *IpAndPort) XXX_Size() int { - return xxx_messageInfo_IpAndPort.Size(m) -} -func (m *IpAndPort) XXX_DiscardUnknown() { - xxx_messageInfo_IpAndPort.DiscardUnknown(m) -} - -var xxx_messageInfo_IpAndPort proto.InternalMessageInfo - -func (m *IpAndPort) GetIp() uint32 { - if m != nil { - return m.Ip +func (x *IpAndPort) GetIp() uint32 { + if x != nil { + return x.Ip } return 0 } -func (m *IpAndPort) GetPort() uint32 { - if m != nil { - return m.Port +func (x *IpAndPort) GetPort() uint32 { + if x != nil { + return x.Port + } + return 0 +} + +type Ip6AndPort struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Ip []byte `protobuf:"bytes,1,opt,name=Ip,proto3" json:"Ip,omitempty"` + Port uint32 `protobuf:"varint,2,opt,name=Port,proto3" json:"Port,omitempty"` +} + +func (x *Ip6AndPort) Reset() { + *x = Ip6AndPort{} + if protoimpl.UnsafeEnabled { + mi := &file_nebula_proto_msgTypes[3] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *Ip6AndPort) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*Ip6AndPort) ProtoMessage() {} + +func (x *Ip6AndPort) ProtoReflect() protoreflect.Message { + mi := &file_nebula_proto_msgTypes[3] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use Ip6AndPort.ProtoReflect.Descriptor instead. +func (*Ip6AndPort) Descriptor() ([]byte, []int) { + return file_nebula_proto_rawDescGZIP(), []int{3} +} + +func (x *Ip6AndPort) GetIp() []byte { + if x != nil { + return x.Ip + } + return nil +} + +func (x *Ip6AndPort) GetPort() uint32 { + if x != nil { + return x.Port } return 0 } type NebulaPing struct { - Type NebulaPing_MessageType `protobuf:"varint,1,opt,name=Type,json=type,proto3,enum=nebula.NebulaPing_MessageType" json:"Type,omitempty"` - Time uint64 `protobuf:"varint,2,opt,name=Time,json=time,proto3" json:"Time,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Type NebulaPing_MessageType `protobuf:"varint,1,opt,name=Type,proto3,enum=nebula.NebulaPing_MessageType" json:"Type,omitempty"` + Time uint64 `protobuf:"varint,2,opt,name=Time,proto3" json:"Time,omitempty"` } -func (m *NebulaPing) Reset() { *m = NebulaPing{} } -func (m *NebulaPing) String() string { return proto.CompactTextString(m) } -func (*NebulaPing) ProtoMessage() {} +func (x *NebulaPing) Reset() { + *x = NebulaPing{} + if protoimpl.UnsafeEnabled { + mi := &file_nebula_proto_msgTypes[4] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NebulaPing) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NebulaPing) ProtoMessage() {} + +func (x *NebulaPing) ProtoReflect() protoreflect.Message { + mi := &file_nebula_proto_msgTypes[4] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NebulaPing.ProtoReflect.Descriptor instead. func (*NebulaPing) Descriptor() ([]byte, []int) { - return fileDescriptor_2d65afa7693df5ef, []int{3} + return file_nebula_proto_rawDescGZIP(), []int{4} } -func (m *NebulaPing) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_NebulaPing.Unmarshal(m, b) -} -func (m *NebulaPing) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_NebulaPing.Marshal(b, m, deterministic) -} -func (m *NebulaPing) XXX_Merge(src proto.Message) { - xxx_messageInfo_NebulaPing.Merge(m, src) -} -func (m *NebulaPing) XXX_Size() int { - return xxx_messageInfo_NebulaPing.Size(m) -} -func (m *NebulaPing) XXX_DiscardUnknown() { - xxx_messageInfo_NebulaPing.DiscardUnknown(m) -} - -var xxx_messageInfo_NebulaPing proto.InternalMessageInfo - -func (m *NebulaPing) GetType() NebulaPing_MessageType { - if m != nil { - return m.Type +func (x *NebulaPing) GetType() NebulaPing_MessageType { + if x != nil { + return x.Type } return NebulaPing_Ping } -func (m *NebulaPing) GetTime() uint64 { - if m != nil { - return m.Time +func (x *NebulaPing) GetTime() uint64 { + if x != nil { + return x.Time } return 0 } type NebulaHandshake struct { - Details *NebulaHandshakeDetails `protobuf:"bytes,1,opt,name=Details,json=details,proto3" json:"Details,omitempty"` - Hmac []byte `protobuf:"bytes,2,opt,name=Hmac,json=hmac,proto3" json:"Hmac,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Details *NebulaHandshakeDetails `protobuf:"bytes,1,opt,name=Details,proto3" json:"Details,omitempty"` + Hmac []byte `protobuf:"bytes,2,opt,name=Hmac,proto3" json:"Hmac,omitempty"` } -func (m *NebulaHandshake) Reset() { *m = NebulaHandshake{} } -func (m *NebulaHandshake) String() string { return proto.CompactTextString(m) } -func (*NebulaHandshake) ProtoMessage() {} +func (x *NebulaHandshake) Reset() { + *x = NebulaHandshake{} + if protoimpl.UnsafeEnabled { + mi := &file_nebula_proto_msgTypes[5] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NebulaHandshake) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NebulaHandshake) ProtoMessage() {} + +func (x *NebulaHandshake) ProtoReflect() protoreflect.Message { + mi := &file_nebula_proto_msgTypes[5] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NebulaHandshake.ProtoReflect.Descriptor instead. func (*NebulaHandshake) Descriptor() ([]byte, []int) { - return fileDescriptor_2d65afa7693df5ef, []int{4} + return file_nebula_proto_rawDescGZIP(), []int{5} } -func (m *NebulaHandshake) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_NebulaHandshake.Unmarshal(m, b) -} -func (m *NebulaHandshake) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_NebulaHandshake.Marshal(b, m, deterministic) -} -func (m *NebulaHandshake) XXX_Merge(src proto.Message) { - xxx_messageInfo_NebulaHandshake.Merge(m, src) -} -func (m *NebulaHandshake) XXX_Size() int { - return xxx_messageInfo_NebulaHandshake.Size(m) -} -func (m *NebulaHandshake) XXX_DiscardUnknown() { - xxx_messageInfo_NebulaHandshake.DiscardUnknown(m) -} - -var xxx_messageInfo_NebulaHandshake proto.InternalMessageInfo - -func (m *NebulaHandshake) GetDetails() *NebulaHandshakeDetails { - if m != nil { - return m.Details +func (x *NebulaHandshake) GetDetails() *NebulaHandshakeDetails { + if x != nil { + return x.Details } return nil } -func (m *NebulaHandshake) GetHmac() []byte { - if m != nil { - return m.Hmac +func (x *NebulaHandshake) GetHmac() []byte { + if x != nil { + return x.Hmac } return nil } type NebulaHandshakeDetails struct { - Cert []byte `protobuf:"bytes,1,opt,name=Cert,json=cert,proto3" json:"Cert,omitempty"` - InitiatorIndex uint32 `protobuf:"varint,2,opt,name=InitiatorIndex,json=initiatorIndex,proto3" json:"InitiatorIndex,omitempty"` - ResponderIndex uint32 `protobuf:"varint,3,opt,name=ResponderIndex,json=responderIndex,proto3" json:"ResponderIndex,omitempty"` - Cookie uint64 `protobuf:"varint,4,opt,name=Cookie,json=cookie,proto3" json:"Cookie,omitempty"` - Time uint64 `protobuf:"varint,5,opt,name=Time,json=time,proto3" json:"Time,omitempty"` - XXX_NoUnkeyedLiteral struct{} `json:"-"` - XXX_unrecognized []byte `json:"-"` - XXX_sizecache int32 `json:"-"` + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Cert []byte `protobuf:"bytes,1,opt,name=Cert,proto3" json:"Cert,omitempty"` + InitiatorIndex uint32 `protobuf:"varint,2,opt,name=InitiatorIndex,proto3" json:"InitiatorIndex,omitempty"` + ResponderIndex uint32 `protobuf:"varint,3,opt,name=ResponderIndex,proto3" json:"ResponderIndex,omitempty"` + Cookie uint64 `protobuf:"varint,4,opt,name=Cookie,proto3" json:"Cookie,omitempty"` + Time uint64 `protobuf:"varint,5,opt,name=Time,proto3" json:"Time,omitempty"` } -func (m *NebulaHandshakeDetails) Reset() { *m = NebulaHandshakeDetails{} } -func (m *NebulaHandshakeDetails) String() string { return proto.CompactTextString(m) } -func (*NebulaHandshakeDetails) ProtoMessage() {} +func (x *NebulaHandshakeDetails) Reset() { + *x = NebulaHandshakeDetails{} + if protoimpl.UnsafeEnabled { + mi := &file_nebula_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *NebulaHandshakeDetails) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*NebulaHandshakeDetails) ProtoMessage() {} + +func (x *NebulaHandshakeDetails) ProtoReflect() protoreflect.Message { + mi := &file_nebula_proto_msgTypes[6] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use NebulaHandshakeDetails.ProtoReflect.Descriptor instead. func (*NebulaHandshakeDetails) Descriptor() ([]byte, []int) { - return fileDescriptor_2d65afa7693df5ef, []int{5} + return file_nebula_proto_rawDescGZIP(), []int{6} } -func (m *NebulaHandshakeDetails) XXX_Unmarshal(b []byte) error { - return xxx_messageInfo_NebulaHandshakeDetails.Unmarshal(m, b) -} -func (m *NebulaHandshakeDetails) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) { - return xxx_messageInfo_NebulaHandshakeDetails.Marshal(b, m, deterministic) -} -func (m *NebulaHandshakeDetails) XXX_Merge(src proto.Message) { - xxx_messageInfo_NebulaHandshakeDetails.Merge(m, src) -} -func (m *NebulaHandshakeDetails) XXX_Size() int { - return xxx_messageInfo_NebulaHandshakeDetails.Size(m) -} -func (m *NebulaHandshakeDetails) XXX_DiscardUnknown() { - xxx_messageInfo_NebulaHandshakeDetails.DiscardUnknown(m) -} - -var xxx_messageInfo_NebulaHandshakeDetails proto.InternalMessageInfo - -func (m *NebulaHandshakeDetails) GetCert() []byte { - if m != nil { - return m.Cert +func (x *NebulaHandshakeDetails) GetCert() []byte { + if x != nil { + return x.Cert } return nil } -func (m *NebulaHandshakeDetails) GetInitiatorIndex() uint32 { - if m != nil { - return m.InitiatorIndex +func (x *NebulaHandshakeDetails) GetInitiatorIndex() uint32 { + if x != nil { + return x.InitiatorIndex } return 0 } -func (m *NebulaHandshakeDetails) GetResponderIndex() uint32 { - if m != nil { - return m.ResponderIndex +func (x *NebulaHandshakeDetails) GetResponderIndex() uint32 { + if x != nil { + return x.ResponderIndex } return 0 } -func (m *NebulaHandshakeDetails) GetCookie() uint64 { - if m != nil { - return m.Cookie +func (x *NebulaHandshakeDetails) GetCookie() uint64 { + if x != nil { + return x.Cookie } return 0 } -func (m *NebulaHandshakeDetails) GetTime() uint64 { - if m != nil { - return m.Time +func (x *NebulaHandshakeDetails) GetTime() uint64 { + if x != nil { + return x.Time } return 0 } -func init() { - proto.RegisterEnum("nebula.NebulaMeta_MessageType", NebulaMeta_MessageType_name, NebulaMeta_MessageType_value) - proto.RegisterEnum("nebula.NebulaPing_MessageType", NebulaPing_MessageType_name, NebulaPing_MessageType_value) - proto.RegisterType((*NebulaMeta)(nil), "nebula.NebulaMeta") - proto.RegisterType((*NebulaMetaDetails)(nil), "nebula.NebulaMetaDetails") - proto.RegisterType((*IpAndPort)(nil), "nebula.IpAndPort") - proto.RegisterType((*NebulaPing)(nil), "nebula.NebulaPing") - proto.RegisterType((*NebulaHandshake)(nil), "nebula.NebulaHandshake") - proto.RegisterType((*NebulaHandshakeDetails)(nil), "nebula.NebulaHandshakeDetails") +var File_nebula_proto protoreflect.FileDescriptor + +var file_nebula_proto_rawDesc = []byte{ + 0x0a, 0x0c, 0x6e, 0x65, 0x62, 0x75, 0x6c, 0x61, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x06, + 0x6e, 0x65, 0x62, 0x75, 0x6c, 0x61, 0x22, 0xcc, 0x02, 0x0a, 0x0a, 0x4e, 0x65, 0x62, 0x75, 0x6c, + 0x61, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x32, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x6e, 0x65, 0x62, 0x75, 0x6c, 0x61, 0x2e, 0x4e, 0x65, 0x62, + 0x75, 0x6c, 0x61, 0x4d, 0x65, 0x74, 0x61, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x44, 0x65, 0x74, + 0x61, 0x69, 0x6c, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x19, 0x2e, 0x6e, 0x65, 0x62, + 0x75, 0x6c, 0x61, 0x2e, 0x4e, 0x65, 0x62, 0x75, 0x6c, 0x61, 0x4d, 0x65, 0x74, 0x61, 0x44, 0x65, + 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x07, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x22, 0xd4, + 0x01, 0x0a, 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, + 0x0a, 0x04, 0x4e, 0x6f, 0x6e, 0x65, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x48, 0x6f, 0x73, 0x74, + 0x51, 0x75, 0x65, 0x72, 0x79, 0x10, 0x01, 0x12, 0x12, 0x0a, 0x0e, 0x48, 0x6f, 0x73, 0x74, 0x51, + 0x75, 0x65, 0x72, 0x79, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x48, + 0x6f, 0x73, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0x03, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x6f, 0x73, 0x74, 0x4d, + 0x6f, 0x76, 0x65, 0x64, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x10, 0x04, 0x12, 0x19, 0x0a, 0x15, 0x48, 0x6f, 0x73, 0x74, 0x50, 0x75, 0x6e, 0x63, 0x68, 0x4e, + 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x10, 0x05, 0x12, 0x0e, 0x0a, + 0x0a, 0x48, 0x6f, 0x73, 0x74, 0x57, 0x68, 0x6f, 0x61, 0x6d, 0x69, 0x10, 0x06, 0x12, 0x13, 0x0a, + 0x0f, 0x48, 0x6f, 0x73, 0x74, 0x57, 0x68, 0x6f, 0x61, 0x6d, 0x69, 0x52, 0x65, 0x70, 0x6c, 0x79, + 0x10, 0x07, 0x12, 0x0d, 0x0a, 0x09, 0x50, 0x61, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x10, + 0x08, 0x12, 0x12, 0x0a, 0x0e, 0x50, 0x61, 0x74, 0x68, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x52, 0x65, + 0x70, 0x6c, 0x79, 0x10, 0x09, 0x22, 0xac, 0x01, 0x0a, 0x11, 0x4e, 0x65, 0x62, 0x75, 0x6c, 0x61, + 0x4d, 0x65, 0x74, 0x61, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x56, + 0x70, 0x6e, 0x49, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x56, 0x70, 0x6e, 0x49, + 0x70, 0x12, 0x31, 0x0a, 0x0a, 0x49, 0x70, 0x41, 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x73, 0x18, + 0x02, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x6e, 0x65, 0x62, 0x75, 0x6c, 0x61, 0x2e, 0x49, + 0x70, 0x41, 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x0a, 0x49, 0x70, 0x41, 0x6e, 0x64, 0x50, + 0x6f, 0x72, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x0b, 0x49, 0x70, 0x36, 0x41, 0x6e, 0x64, 0x50, 0x6f, + 0x72, 0x74, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x6e, 0x65, 0x62, 0x75, + 0x6c, 0x61, 0x2e, 0x49, 0x70, 0x36, 0x41, 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x52, 0x0b, 0x49, + 0x70, 0x36, 0x41, 0x6e, 0x64, 0x50, 0x6f, 0x72, 0x74, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x07, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x65, 0x72, 0x22, 0x2f, 0x0a, 0x09, 0x49, 0x70, 0x41, 0x6e, 0x64, 0x50, 0x6f, 0x72, + 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x02, 0x49, + 0x70, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, + 0x04, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x30, 0x0a, 0x0a, 0x49, 0x70, 0x36, 0x41, 0x6e, 0x64, 0x50, + 0x6f, 0x72, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x49, 0x70, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, + 0x02, 0x49, 0x70, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x78, 0x0a, 0x0a, 0x4e, 0x65, 0x62, 0x75, 0x6c, + 0x61, 0x50, 0x69, 0x6e, 0x67, 0x12, 0x32, 0x0a, 0x04, 0x54, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0e, 0x32, 0x1e, 0x2e, 0x6e, 0x65, 0x62, 0x75, 0x6c, 0x61, 0x2e, 0x4e, 0x65, 0x62, + 0x75, 0x6c, 0x61, 0x50, 0x69, 0x6e, 0x67, 0x2e, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, + 0x79, 0x70, 0x65, 0x52, 0x04, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x69, 0x6d, + 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x54, 0x69, 0x6d, 0x65, 0x22, 0x22, 0x0a, + 0x0b, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x08, 0x0a, 0x04, + 0x50, 0x69, 0x6e, 0x67, 0x10, 0x00, 0x12, 0x09, 0x0a, 0x05, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x10, + 0x01, 0x22, 0x5f, 0x0a, 0x0f, 0x4e, 0x65, 0x62, 0x75, 0x6c, 0x61, 0x48, 0x61, 0x6e, 0x64, 0x73, + 0x68, 0x61, 0x6b, 0x65, 0x12, 0x38, 0x0a, 0x07, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6e, 0x65, 0x62, 0x75, 0x6c, 0x61, 0x2e, 0x4e, + 0x65, 0x62, 0x75, 0x6c, 0x61, 0x48, 0x61, 0x6e, 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x44, 0x65, + 0x74, 0x61, 0x69, 0x6c, 0x73, 0x52, 0x07, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x12, + 0x0a, 0x04, 0x48, 0x6d, 0x61, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x48, 0x6d, + 0x61, 0x63, 0x22, 0xa8, 0x01, 0x0a, 0x16, 0x4e, 0x65, 0x62, 0x75, 0x6c, 0x61, 0x48, 0x61, 0x6e, + 0x64, 0x73, 0x68, 0x61, 0x6b, 0x65, 0x44, 0x65, 0x74, 0x61, 0x69, 0x6c, 0x73, 0x12, 0x12, 0x0a, + 0x04, 0x43, 0x65, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x04, 0x43, 0x65, 0x72, + 0x74, 0x12, 0x26, 0x0a, 0x0e, 0x49, 0x6e, 0x69, 0x74, 0x69, 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, + 0x64, 0x65, 0x78, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x49, 0x6e, 0x69, 0x74, 0x69, + 0x61, 0x74, 0x6f, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x12, 0x26, 0x0a, 0x0e, 0x52, 0x65, 0x73, + 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, 0x78, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0d, 0x52, 0x0e, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x64, 0x65, 0x72, 0x49, 0x6e, 0x64, 0x65, + 0x78, 0x12, 0x16, 0x0a, 0x06, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x04, 0x52, 0x06, 0x43, 0x6f, 0x6f, 0x6b, 0x69, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x54, 0x69, 0x6d, + 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x54, 0x69, 0x6d, 0x65, 0x42, 0x1b, 0x5a, + 0x19, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x73, 0x6c, 0x61, 0x63, + 0x6b, 0x68, 0x71, 0x2f, 0x6e, 0x65, 0x62, 0x75, 0x6c, 0x61, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x33, } -func init() { proto.RegisterFile("nebula.proto", fileDescriptor_2d65afa7693df5ef) } +var ( + file_nebula_proto_rawDescOnce sync.Once + file_nebula_proto_rawDescData = file_nebula_proto_rawDesc +) -var fileDescriptor_2d65afa7693df5ef = []byte{ - // 491 bytes of a gzipped FileDescriptorProto - 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x7c, 0x53, 0x41, 0x6f, 0xda, 0x4c, - 0x10, 0x8d, 0x61, 0x81, 0x30, 0x80, 0xe3, 0xcc, 0xf7, 0x15, 0x91, 0x1e, 0xaa, 0xc8, 0x87, 0x8a, - 0x13, 0x55, 0xc9, 0xa5, 0xd7, 0x8a, 0x1e, 0xe0, 0x00, 0xa2, 0x56, 0xda, 0x1e, 0xab, 0x8d, 0x3d, - 0x8d, 0x57, 0xe0, 0xdd, 0x95, 0xbd, 0xa0, 0xf0, 0x8f, 0xfa, 0x63, 0x7a, 0xec, 0x0f, 0xaa, 0x76, - 0x0d, 0xa6, 0x84, 0xa8, 0xb7, 0x7d, 0xf3, 0xde, 0xcc, 0x8e, 0xdf, 0x5b, 0x43, 0x57, 0xd2, 0xc3, - 0x66, 0xcd, 0x47, 0x3a, 0x57, 0x46, 0x61, 0xb3, 0x44, 0xe1, 0xaf, 0x1a, 0xc0, 0xc2, 0x1d, 0xe7, - 0x64, 0x38, 0x8e, 0x81, 0xdd, 0xef, 0x34, 0x0d, 0xbc, 0x5b, 0x6f, 0xe8, 0x8f, 0xdf, 0x8c, 0xf6, - 0x3d, 0x47, 0xc5, 0x68, 0x4e, 0x45, 0xc1, 0x1f, 0xc9, 0xaa, 0x22, 0x66, 0x76, 0x9a, 0xf0, 0x0e, - 0x5a, 0x9f, 0xc8, 0x70, 0xb1, 0x2e, 0x06, 0xb5, 0x5b, 0x6f, 0xd8, 0x19, 0xdf, 0x9c, 0xb7, 0xed, - 0x05, 0x51, 0x2b, 0x29, 0x0f, 0xe1, 0x6f, 0x0f, 0x3a, 0x7f, 0x8d, 0xc2, 0x4b, 0x60, 0x0b, 0x25, - 0x29, 0xb8, 0xc0, 0x1e, 0xb4, 0xa7, 0xaa, 0x30, 0x9f, 0x37, 0x94, 0xef, 0x02, 0x0f, 0x11, 0xfc, - 0x0a, 0x46, 0xa4, 0xd7, 0xbb, 0xa0, 0x86, 0xaf, 0xa1, 0x6f, 0x6b, 0x5f, 0x74, 0xc2, 0x0d, 0x2d, - 0x94, 0x11, 0x3f, 0x44, 0xcc, 0x8d, 0x50, 0x32, 0xa8, 0xe3, 0x0d, 0xbc, 0xb2, 0xdc, 0x5c, 0x6d, - 0x29, 0x39, 0xa1, 0xd8, 0x81, 0x5a, 0x6e, 0x64, 0x9c, 0x9e, 0x50, 0x0d, 0xf4, 0x01, 0x2c, 0xf5, - 0x2d, 0x55, 0x3c, 0x13, 0x41, 0x13, 0xff, 0x83, 0xab, 0x23, 0x2e, 0xaf, 0x6d, 0xd9, 0xcd, 0x96, - 0xdc, 0xa4, 0x93, 0x94, 0xe2, 0x55, 0x70, 0x69, 0x37, 0xab, 0x60, 0x29, 0x69, 0x87, 0x5b, 0xb8, - 0x3e, 0xfb, 0x68, 0xfc, 0x1f, 0x1a, 0x5f, 0xb5, 0x9c, 0x69, 0xe7, 0x6a, 0x2f, 0x6a, 0x6c, 0x2d, - 0xc0, 0xf7, 0x00, 0x33, 0xfd, 0x51, 0x26, 0x4b, 0x95, 0x1b, 0xeb, 0x5c, 0x7d, 0xd8, 0x19, 0x5f, - 0x1f, 0x9c, 0xab, 0x98, 0x08, 0x44, 0x25, 0xc2, 0x01, 0xb4, 0x62, 0xb5, 0x91, 0x86, 0xf2, 0x41, - 0xdd, 0x8d, 0x3a, 0xc0, 0xf0, 0x1d, 0xb4, 0xab, 0x16, 0xf4, 0xa1, 0x56, 0x5d, 0x56, 0x13, 0x1a, - 0x11, 0x98, 0xad, 0xbb, 0x74, 0x7a, 0x11, 0xd3, 0x2a, 0x37, 0xe1, 0xd3, 0x21, 0xf6, 0xa5, 0x90, - 0x8f, 0xff, 0x8e, 0xdd, 0x2a, 0x5e, 0x88, 0x1d, 0x81, 0xdd, 0x8b, 0x8c, 0xdc, 0x54, 0x16, 0x31, - 0x23, 0x32, 0x0a, 0xc3, 0xb3, 0x50, 0x6d, 0x73, 0x70, 0x81, 0x6d, 0x68, 0x94, 0x16, 0x79, 0xe1, - 0x77, 0xb8, 0x2a, 0xe7, 0x4e, 0xb9, 0x4c, 0x8a, 0x94, 0xaf, 0x08, 0x3f, 0x1c, 0x5f, 0x90, 0xe7, - 0x5e, 0xd0, 0xb3, 0x0d, 0x2a, 0xe5, 0xf3, 0x67, 0x64, 0x97, 0x98, 0x66, 0x3c, 0x76, 0x4b, 0x74, - 0x23, 0x96, 0x66, 0x3c, 0x0e, 0x7f, 0x7a, 0xd0, 0x7f, 0xb9, 0xcf, 0xca, 0x27, 0x94, 0x1b, 0x77, - 0x4b, 0x37, 0x62, 0x31, 0xe5, 0x06, 0xdf, 0x82, 0x3f, 0x93, 0xc2, 0x08, 0x6e, 0x54, 0x3e, 0x93, - 0x09, 0x3d, 0xed, 0x7d, 0xf2, 0xc5, 0x49, 0xd5, 0xea, 0x22, 0x2a, 0xb4, 0x92, 0x09, 0xed, 0x75, - 0x65, 0x06, 0x7e, 0x7e, 0x52, 0xc5, 0x3e, 0x34, 0x27, 0x4a, 0xad, 0x04, 0x0d, 0x98, 0x73, 0xa6, - 0x19, 0x3b, 0x54, 0xf9, 0xd5, 0x38, 0xfa, 0xf5, 0xd0, 0x74, 0x3f, 0xe3, 0xdd, 0x9f, 0x00, 0x00, - 0x00, 0xff, 0xff, 0x65, 0xc6, 0x25, 0x44, 0x9c, 0x03, 0x00, 0x00, +func file_nebula_proto_rawDescGZIP() []byte { + file_nebula_proto_rawDescOnce.Do(func() { + file_nebula_proto_rawDescData = protoimpl.X.CompressGZIP(file_nebula_proto_rawDescData) + }) + return file_nebula_proto_rawDescData +} + +var file_nebula_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_nebula_proto_msgTypes = make([]protoimpl.MessageInfo, 7) +var file_nebula_proto_goTypes = []interface{}{ + (NebulaMeta_MessageType)(0), // 0: nebula.NebulaMeta.MessageType + (NebulaPing_MessageType)(0), // 1: nebula.NebulaPing.MessageType + (*NebulaMeta)(nil), // 2: nebula.NebulaMeta + (*NebulaMetaDetails)(nil), // 3: nebula.NebulaMetaDetails + (*IpAndPort)(nil), // 4: nebula.IpAndPort + (*Ip6AndPort)(nil), // 5: nebula.Ip6AndPort + (*NebulaPing)(nil), // 6: nebula.NebulaPing + (*NebulaHandshake)(nil), // 7: nebula.NebulaHandshake + (*NebulaHandshakeDetails)(nil), // 8: nebula.NebulaHandshakeDetails +} +var file_nebula_proto_depIdxs = []int32{ + 0, // 0: nebula.NebulaMeta.Type:type_name -> nebula.NebulaMeta.MessageType + 3, // 1: nebula.NebulaMeta.Details:type_name -> nebula.NebulaMetaDetails + 4, // 2: nebula.NebulaMetaDetails.IpAndPorts:type_name -> nebula.IpAndPort + 5, // 3: nebula.NebulaMetaDetails.Ip6AndPorts:type_name -> nebula.Ip6AndPort + 1, // 4: nebula.NebulaPing.Type:type_name -> nebula.NebulaPing.MessageType + 8, // 5: nebula.NebulaHandshake.Details:type_name -> nebula.NebulaHandshakeDetails + 6, // [6:6] is the sub-list for method output_type + 6, // [6:6] is the sub-list for method input_type + 6, // [6:6] is the sub-list for extension type_name + 6, // [6:6] is the sub-list for extension extendee + 0, // [0:6] is the sub-list for field type_name +} + +func init() { file_nebula_proto_init() } +func file_nebula_proto_init() { + if File_nebula_proto != nil { + return + } + if !protoimpl.UnsafeEnabled { + file_nebula_proto_msgTypes[0].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NebulaMeta); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_nebula_proto_msgTypes[1].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NebulaMetaDetails); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_nebula_proto_msgTypes[2].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*IpAndPort); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_nebula_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Ip6AndPort); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_nebula_proto_msgTypes[4].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NebulaPing); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_nebula_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NebulaHandshake); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_nebula_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*NebulaHandshakeDetails); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + } + type x struct{} + out := protoimpl.TypeBuilder{ + File: protoimpl.DescBuilder{ + GoPackagePath: reflect.TypeOf(x{}).PkgPath(), + RawDescriptor: file_nebula_proto_rawDesc, + NumEnums: 2, + NumMessages: 7, + NumExtensions: 0, + NumServices: 0, + }, + GoTypes: file_nebula_proto_goTypes, + DependencyIndexes: file_nebula_proto_depIdxs, + EnumInfos: file_nebula_proto_enumTypes, + MessageInfos: file_nebula_proto_msgTypes, + }.Build() + File_nebula_proto = out.File + file_nebula_proto_rawDesc = nil + file_nebula_proto_goTypes = nil + file_nebula_proto_depIdxs = nil } diff --git a/nebula.proto b/nebula.proto index 75994c0..181d7f5 100644 --- a/nebula.proto +++ b/nebula.proto @@ -1,6 +1,8 @@ syntax = "proto3"; package nebula; +option go_package = "github.com/slackhq/nebula"; + message NebulaMeta { enum MessageType { None = 0; @@ -20,11 +22,10 @@ message NebulaMeta { NebulaMetaDetails Details = 2; } - message NebulaMetaDetails { - uint32 VpnIp = 1; repeated IpAndPort IpAndPorts = 2; + repeated Ip6AndPort Ip6AndPorts = 4; uint32 counter = 3; } @@ -33,6 +34,10 @@ message IpAndPort { uint32 Port = 2; } +message Ip6AndPort { + bytes Ip = 1; + uint32 Port = 2; +} message NebulaPing { enum MessageType { diff --git a/outside.go b/outside.go index ec3b74f..c199157 100644 --- a/outside.go +++ b/outside.go @@ -142,7 +142,7 @@ func (f *Interface) closeTunnel(hostInfo *HostInfo) { func (f *Interface) handleHostRoaming(hostinfo *HostInfo, addr *udpAddr) { if hostDidRoam(hostinfo.remote, addr) { - if !f.lightHouse.remoteAllowList.Allow(udp2ipInt(addr)) { + if !f.lightHouse.remoteAllowList.Allow(addr.IP) { hostinfo.logger().WithField("newAddr", addr).Debug("lighthouse.remote_allow_list denied roaming") return } @@ -159,7 +159,7 @@ func (f *Interface) handleHostRoaming(hostinfo *HostInfo, addr *udpAddr) { hostinfo.lastRoam = time.Now() remoteCopy := *hostinfo.remote hostinfo.lastRoamRemote = &remoteCopy - hostinfo.SetRemote(*addr) + hostinfo.SetRemote(addr) if f.lightHouse.amLighthouse { f.lightHouse.AddRemote(hostinfo.hostId, addr, false) } diff --git a/ssh.go b/ssh.go index aff63ef..25badf3 100644 --- a/ssh.go +++ b/ssh.go @@ -562,7 +562,7 @@ func sshCreateTunnel(ifce *Interface, fs interface{}, a []string, w sshd.StringW hostInfo = ifce.handshakeManager.AddVpnIP(vpnIp) if addr != nil { - hostInfo.SetRemote(*addr) + hostInfo.SetRemote(addr) } ifce.getOrHandshake(vpnIp) @@ -604,7 +604,7 @@ func sshChangeRemote(ifce *Interface, fs interface{}, a []string, w sshd.StringW return w.WriteLine(fmt.Sprintf("Could not find tunnel for vpn ip: %v", a[0])) } - hostInfo.SetRemote(*addr) + hostInfo.SetRemote(addr) return w.WriteLine("Changed") } diff --git a/udp_all.go b/udp_all.go new file mode 100644 index 0000000..0798dab --- /dev/null +++ b/udp_all.go @@ -0,0 +1,62 @@ +package nebula + +import ( + "encoding/json" + "fmt" + "net" + "strconv" +) + +type udpAddr struct { + IP net.IP + Port uint16 +} + +func NewUDPAddr(ip net.IP, port uint16) *udpAddr { + addr := udpAddr{IP: make([]byte, len(ip)), Port: port} + copy(addr.IP, ip) + return &addr +} + +func NewUDPAddrFromString(s string) *udpAddr { + ip, port, err := parseIPAndPort(s) + //TODO: handle err + _ = err + return &udpAddr{IP: ip, Port: port} +} + +func (ua *udpAddr) Equals(t *udpAddr) bool { + if t == nil || ua == nil { + return t == nil && ua == nil + } + return ua.IP.Equal(t.IP) && ua.Port == t.Port +} + +func (ua *udpAddr) String() string { + return net.JoinHostPort(ua.IP.String(), fmt.Sprintf("%v", ua.Port)) +} + +func (ua *udpAddr) MarshalJSON() ([]byte, error) { + return json.Marshal(m{"ip": ua.IP, "port": ua.Port}) +} + +func (ua *udpAddr) Copy() *udpAddr { + nu := udpAddr{ + Port: ua.Port, + IP: make(net.IP, len(ua.IP)), + } + + copy(nu.IP, ua.IP) + return &nu +} + +func parseIPAndPort(s string) (net.IP, uint16, error) { + rIp, sPort, err := net.SplitHostPort(s) + if err != nil { + return nil, 0, err + } + + iPort, err := strconv.Atoi(sPort) + ip := net.ParseIP(rIp) + return ip, uint16(iPort), nil +} diff --git a/udp_darwin.go b/udp_darwin.go index 4f7c0b2..52506b5 100644 --- a/udp_darwin.go +++ b/udp_darwin.go @@ -28,6 +28,7 @@ func NewListenConfig(multi bool) net.ListenConfig { return controlErr } } + return nil }, } @@ -39,5 +40,5 @@ func (u *udpConn) Rebind() error { return err } - return syscall.SetsockoptInt(int(file.Fd()), unix.IPPROTO_IP, unix.IP_BOUND_IF, 0) + return syscall.SetsockoptInt(int(file.Fd()), unix.IPPROTO_IPV6, unix.IPV6_BOUND_IF, 0) } diff --git a/udp_generic.go b/udp_generic.go index 2de6e29..492a695 100644 --- a/udp_generic.go +++ b/udp_generic.go @@ -7,48 +7,17 @@ package nebula import ( "context" - "encoding/binary" "fmt" "net" - "strconv" - "strings" ) -type udpAddr struct { - net.UDPAddr -} - type udpConn struct { *net.UDPConn } -func NewUDPAddr(ip uint32, port uint16) *udpAddr { - return &udpAddr{ - UDPAddr: net.UDPAddr{ - IP: int2ip(ip), - Port: int(port), - }, - } -} - -func NewUDPAddrFromString(s string) *udpAddr { - p := strings.Split(s, ":") - if len(p) < 2 { - return nil - } - - port, _ := strconv.Atoi(p[1]) - return &udpAddr{ - UDPAddr: net.UDPAddr{ - IP: net.ParseIP(p[0]), - Port: port, - }, - } -} - func NewListener(ip string, port int, multi bool) (*udpConn, error) { lc := NewListenConfig(multi) - pc, err := lc.ListenPacket(context.TODO(), "udp4", fmt.Sprintf("%s:%d", ip, port)) + pc, err := lc.ListenPacket(context.TODO(), "udp", fmt.Sprintf("%s:%d", ip, port)) if err != nil { return nil, err } @@ -58,26 +27,8 @@ func NewListener(ip string, port int, multi bool) (*udpConn, error) { return nil, fmt.Errorf("Unexpected PacketConn: %T %#v", pc, pc) } -func (ua *udpAddr) Equals(t *udpAddr) bool { - if t == nil || ua == nil { - return t == nil && ua == nil - } - return ua.IP.Equal(t.IP) && ua.Port == t.Port -} - -func (ua *udpAddr) Copy() udpAddr { - nu := udpAddr{net.UDPAddr{ - Port: ua.Port, - Zone: ua.Zone, - IP: make(net.IP, len(ua.IP)), - }} - - copy(nu.IP, ua.IP) - return nu -} - func (uc *udpConn) WriteTo(b []byte, addr *udpAddr) error { - _, err := uc.UDPConn.WriteToUDP(b, &addr.UDPAddr) + _, err := uc.UDPConn.WriteToUDP(b, &net.UDPAddr{IP: addr.IP, Port: int(addr.Port)}) return err } @@ -86,7 +37,11 @@ func (uc *udpConn) LocalAddr() (*udpAddr, error) { switch v := a.(type) { case *net.UDPAddr: - return &udpAddr{UDPAddr: *v}, nil + addr := &udpAddr{IP: make([]byte, len(v.IP))} + copy(addr.IP, v.IP) + addr.Port = uint16(v.Port) + return addr, nil + default: return nil, fmt.Errorf("LocalAddr returned: %#v", a) } @@ -110,7 +65,7 @@ func (u *udpConn) ListenOut(f *Interface, q int) { buffer := make([]byte, mtu) header := &Header{} fwPacket := &FirewallPacket{} - udpAddr := &udpAddr{} + udpAddr := &udpAddr{IP: make([]byte, 16)} nb := make([]byte, 12, 12) lhh := f.lightHouse.NewRequestHandler() @@ -125,19 +80,12 @@ func (u *udpConn) ListenOut(f *Interface, q int) { continue } - udpAddr.UDPAddr = *rua + udpAddr.IP = rua.IP + udpAddr.Port = uint16(rua.Port) f.readOutsidePackets(udpAddr, plaintext[:0], buffer[:n], header, fwPacket, lhh, nb, q, conntrackCache.Get()) } } -func udp2ip(addr *udpAddr) net.IP { - return addr.IP -} - -func udp2ipInt(addr *udpAddr) uint32 { - return binary.BigEndian.Uint32(addr.IP.To4()) -} - func hostDidRoam(addr *udpAddr, newaddr *udpAddr) bool { return !addr.Equals(newaddr) } diff --git a/udp_linux.go b/udp_linux.go index dbdad2c..764b21a 100644 --- a/udp_linux.go +++ b/udp_linux.go @@ -4,11 +4,8 @@ package nebula import ( "encoding/binary" - "encoding/json" "fmt" "net" - "strconv" - "strings" "syscall" "unsafe" @@ -22,38 +19,6 @@ type udpConn struct { sysFd int } -type udpAddr struct { - IP uint32 - Port uint16 -} - -func NewUDPAddr(ip uint32, port uint16) *udpAddr { - return &udpAddr{IP: ip, Port: port} -} - -func NewUDPAddrFromString(s string) *udpAddr { - p := strings.Split(s, ":") - if len(p) < 2 { - return nil - } - - port, _ := strconv.Atoi(p[1]) - return &udpAddr{ - IP: ip2int(net.ParseIP(p[0])), - Port: uint16(port), - } -} - -type rawSockaddr struct { - Family uint16 - Data [14]uint8 -} - -type rawSockaddrAny struct { - Addr rawSockaddr - Pad [96]int8 -} - var x int // From linux/sock_diag.h @@ -75,7 +40,7 @@ type _SK_MEMINFO [_SK_MEMINFO_VARS]uint32 func NewListener(ip string, port int, multi bool) (*udpConn, error) { syscall.ForkLock.RLock() - fd, err := unix.Socket(unix.AF_INET, unix.SOCK_DGRAM, unix.IPPROTO_UDP) + fd, err := unix.Socket(unix.AF_INET6, unix.SOCK_DGRAM, unix.IPPROTO_UDP) if err == nil { unix.CloseOnExec(fd) } @@ -86,8 +51,8 @@ func NewListener(ip string, port int, multi bool) (*udpConn, error) { return nil, fmt.Errorf("unable to open socket: %s", err) } - var lip [4]byte - copy(lip[:], net.ParseIP(ip).To4()) + var lip [16]byte + copy(lip[:], net.ParseIP(ip)) if multi { if err = unix.SetsockoptInt(fd, unix.SOL_SOCKET, unix.SO_REUSEPORT, 1); err != nil { @@ -95,7 +60,8 @@ func NewListener(ip string, port int, multi bool) (*udpConn, error) { } } - if err = unix.Bind(fd, &unix.SockaddrInet4{Addr: lip, Port: port}); err != nil { + //TODO: support multiple listening IPs (for limiting ipv6) + if err = unix.Bind(fd, &unix.SockaddrInet6{Addr: lip, Port: port}); err != nil { return nil, fmt.Errorf("unable to bind to socket: %s", err) } @@ -111,10 +77,6 @@ func (u *udpConn) Rebind() error { return nil } -func (ua *udpAddr) Copy() udpAddr { - return *ua -} - func (u *udpConn) SetRecvBuffer(n int) error { return unix.SetsockoptInt(u.sysFd, unix.SOL_SOCKET, unix.SO_RCVBUFFORCE, n) } @@ -132,7 +94,7 @@ func (u *udpConn) GetSendBuffer() (int, error) { } func (u *udpConn) LocalAddr() (*udpAddr, error) { - var rsa rawSockaddrAny + var rsa unix.RawSockaddrAny var rLen = unix.SizeofSockaddrAny _, _, err := unix.Syscall( @@ -148,12 +110,24 @@ func (u *udpConn) LocalAddr() (*udpAddr, error) { addr := &udpAddr{} if rsa.Addr.Family == unix.AF_INET { + pp := (*unix.RawSockaddrInet4)(unsafe.Pointer(&rsa)) addr.Port = uint16(rsa.Addr.Data[0])<<8 + uint16(rsa.Addr.Data[1]) - addr.IP = uint32(rsa.Addr.Data[2])<<24 + uint32(rsa.Addr.Data[3])<<16 + uint32(rsa.Addr.Data[4])<<8 + uint32(rsa.Addr.Data[5]) + copy(addr.IP, pp.Addr[:]) + + } else if rsa.Addr.Family == unix.AF_INET6 { + //TODO: this cast sucks and we can do better + pp := (*unix.RawSockaddrInet6)(unsafe.Pointer(&rsa)) + addr.Port = uint16(rsa.Addr.Data[0])<<8 + uint16(rsa.Addr.Data[1]) + copy(addr.IP, pp.Addr[:]) + } else { addr.Port = 0 - addr.IP = 0 + addr.IP = []byte{} } + + //TODO: Just use this instead? + //a, b := unix.Getsockname(u.sysFd) + return addr, nil } @@ -185,9 +159,8 @@ func (u *udpConn) ListenOut(f *Interface, q int) { //metric.Update(int64(n)) for i := 0; i < n; i++ { - udpAddr.IP = binary.BigEndian.Uint32(names[i][4:8]) + udpAddr.IP = names[i][8:24] udpAddr.Port = binary.BigEndian.Uint16(names[i][2:4]) - f.readOutsidePackets(udpAddr, plaintext[:0], buffers[i][:msgs[i].Len], header, fwPacket, lhh, nb, q, conntrackCache.Get()) } } @@ -235,18 +208,13 @@ func (u *udpConn) ReadMulti(msgs []rawMessage) (int, error) { } func (u *udpConn) WriteTo(b []byte, addr *udpAddr) error { - var rsa unix.RawSockaddrInet4 - //TODO: sometimes addr is nil! - rsa.Family = unix.AF_INET + var rsa unix.RawSockaddrInet6 + rsa.Family = unix.AF_INET6 p := (*[2]byte)(unsafe.Pointer(&rsa.Port)) p[0] = byte(addr.Port >> 8) p[1] = byte(addr.Port) - - rsa.Addr[0] = byte(addr.IP & 0xff000000 >> 24) - rsa.Addr[1] = byte(addr.IP & 0x00ff0000 >> 16) - rsa.Addr[2] = byte(addr.IP & 0x0000ff00 >> 8) - rsa.Addr[3] = byte(addr.IP & 0x000000ff) + copy(rsa.Addr[:], addr.IP) for { _, _, err := unix.Syscall6( @@ -256,7 +224,7 @@ func (u *udpConn) WriteTo(b []byte, addr *udpAddr) error { uintptr(len(b)), uintptr(0), uintptr(unsafe.Pointer(&rsa)), - uintptr(unix.SizeofSockaddrInet4), + uintptr(unix.SizeofSockaddrInet6), ) if err != 0 { @@ -342,29 +310,6 @@ func NewUDPStatsEmitter(udpConns []*udpConn) func() { } } -func (ua *udpAddr) Equals(t *udpAddr) bool { - if t == nil || ua == nil { - return t == nil && ua == nil - } - return ua.IP == t.IP && ua.Port == t.Port -} - -func (ua *udpAddr) String() string { - return fmt.Sprintf("%s:%v", int2ip(ua.IP), ua.Port) -} - -func (ua *udpAddr) MarshalJSON() ([]byte, error) { - return json.Marshal(m{"ip": int2ip(ua.IP), "port": ua.Port}) -} - -func udp2ip(addr *udpAddr) net.IP { - return int2ip(addr.IP) -} - -func udp2ipInt(addr *udpAddr) uint32 { - return addr.IP -} - func hostDidRoam(addr *udpAddr, newaddr *udpAddr) bool { return !addr.Equals(newaddr) } diff --git a/udp_linux_32.go b/udp_linux_32.go index 752b529..0b2f6b1 100644 --- a/udp_linux_32.go +++ b/udp_linux_32.go @@ -4,7 +4,9 @@ package nebula -import "unsafe" +import ( + "golang.org/x/sys/unix" +) type iovec struct { Base *byte @@ -33,17 +35,17 @@ func (u *udpConn) PrepareRawMessages(n int) ([]rawMessage, [][]byte, [][]byte) { for i := range msgs { buffers[i] = make([]byte, mtu) - names[i] = make([]byte, 0x1c) //TODO = sizeofSockaddrInet6 + names[i] = make([]byte, unix.SizeofSockaddrInet6) //TODO: this is still silly, no need for an array vs := []iovec{ - {Base: (*byte)(unsafe.Pointer(&buffers[i][0])), Len: uint32(len(buffers[i]))}, + {Base: &buffers[i][0], Len: uint32(len(buffers[i]))}, } msgs[i].Hdr.Iov = &vs[0] msgs[i].Hdr.Iovlen = uint32(len(vs)) - msgs[i].Hdr.Name = (*byte)(unsafe.Pointer(&names[i][0])) + msgs[i].Hdr.Name = &names[i][0] msgs[i].Hdr.Namelen = uint32(len(names[i])) } diff --git a/udp_linux_64.go b/udp_linux_64.go index 4d65d5a..faeda69 100644 --- a/udp_linux_64.go +++ b/udp_linux_64.go @@ -4,7 +4,9 @@ package nebula -import "unsafe" +import ( + "golang.org/x/sys/unix" +) type iovec struct { Base *byte @@ -36,17 +38,17 @@ func (u *udpConn) PrepareRawMessages(n int) ([]rawMessage, [][]byte, [][]byte) { for i := range msgs { buffers[i] = make([]byte, mtu) - names[i] = make([]byte, 0x1c) //TODO = sizeofSockaddrInet6 + names[i] = make([]byte, unix.SizeofSockaddrInet6) //TODO: this is still silly, no need for an array vs := []iovec{ - {Base: (*byte)(unsafe.Pointer(&buffers[i][0])), Len: uint64(len(buffers[i]))}, + {Base: &buffers[i][0], Len: uint64(len(buffers[i]))}, } msgs[i].Hdr.Iov = &vs[0] msgs[i].Hdr.Iovlen = uint64(len(vs)) - msgs[i].Hdr.Name = (*byte)(unsafe.Pointer(&names[i][0])) + msgs[i].Hdr.Name = &names[i][0] msgs[i].Hdr.Namelen = uint32(len(names[i])) }