mirror of
https://github.com/slackhq/nebula.git
synced 2025-11-23 17:04:25 +01:00
Compare commits
5 Commits
mutex-debu
...
jay.wren-l
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2400e2392b | ||
|
|
18279ed17b | ||
|
|
c7fb3ad9cf | ||
|
|
d4a7df3083 | ||
|
|
e83a1c6c84 |
2
.github/workflows/smoke.yml
vendored
2
.github/workflows/smoke.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
|||||||
check-latest: true
|
check-latest: true
|
||||||
|
|
||||||
- name: build
|
- name: build
|
||||||
run: make bin-docker CGO_ENABLED=1 BUILD_ARGS="-race -tags=mutex_debug"
|
run: make bin-docker CGO_ENABLED=1 BUILD_ARGS=-race
|
||||||
|
|
||||||
- name: setup docker image
|
- name: setup docker image
|
||||||
working-directory: ./.github/workflows/smoke
|
working-directory: ./.github/workflows/smoke
|
||||||
|
|||||||
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
|||||||
run: make test
|
run: make test
|
||||||
|
|
||||||
- name: End 2 end
|
- name: End 2 end
|
||||||
run: make e2e-mutex-debug TEST_LOGS=1 TEST_FLAGS=-v
|
run: make e2evv
|
||||||
|
|
||||||
- name: Build test mobile
|
- name: Build test mobile
|
||||||
run: make build-test-mobile
|
run: make build-test-mobile
|
||||||
|
|||||||
4
Makefile
4
Makefile
@@ -63,9 +63,6 @@ ALL = $(ALL_LINUX) \
|
|||||||
e2e:
|
e2e:
|
||||||
$(TEST_ENV) go test -tags=e2e_testing -count=1 $(TEST_FLAGS) ./e2e
|
$(TEST_ENV) go test -tags=e2e_testing -count=1 $(TEST_FLAGS) ./e2e
|
||||||
|
|
||||||
e2e-mutex-debug:
|
|
||||||
$(TEST_ENV) go test -tags=mutex_debug,e2e_testing -count=1 $(TEST_FLAGS) ./e2e
|
|
||||||
|
|
||||||
e2ev: TEST_FLAGS += -v
|
e2ev: TEST_FLAGS += -v
|
||||||
e2ev: e2e
|
e2ev: e2e
|
||||||
|
|
||||||
@@ -218,7 +215,6 @@ ifeq ($(words $(MAKECMDGOALS)),1)
|
|||||||
@$(MAKE) service ${.DEFAULT_GOAL} --no-print-directory
|
@$(MAKE) service ${.DEFAULT_GOAL} --no-print-directory
|
||||||
endif
|
endif
|
||||||
|
|
||||||
bin-docker: BUILD_ARGS = -tags=mutex_debug
|
|
||||||
bin-docker: bin build/linux-amd64/nebula build/linux-amd64/nebula-cert
|
bin-docker: bin build/linux-amd64/nebula build/linux-amd64/nebula-cert
|
||||||
|
|
||||||
smoke-docker: bin-docker
|
smoke-docker: bin-docker
|
||||||
|
|||||||
@@ -25,14 +25,14 @@ func TestNewAllowListFromConfig(t *testing.T) {
|
|||||||
c.Settings["allowlist"] = map[string]any{
|
c.Settings["allowlist"] = map[string]any{
|
||||||
"192.168.0.0/16": "abc",
|
"192.168.0.0/16": "abc",
|
||||||
}
|
}
|
||||||
r, err = newAllowListFromConfig(c, "allowlist", nil)
|
_, err = newAllowListFromConfig(c, "allowlist", nil)
|
||||||
require.EqualError(t, err, "config `allowlist` has invalid value (type string): abc")
|
require.EqualError(t, err, "config `allowlist` has invalid value (type string): abc")
|
||||||
|
|
||||||
c.Settings["allowlist"] = map[string]any{
|
c.Settings["allowlist"] = map[string]any{
|
||||||
"192.168.0.0/16": true,
|
"192.168.0.0/16": true,
|
||||||
"10.0.0.0/8": false,
|
"10.0.0.0/8": false,
|
||||||
}
|
}
|
||||||
r, err = newAllowListFromConfig(c, "allowlist", nil)
|
_, err = newAllowListFromConfig(c, "allowlist", nil)
|
||||||
require.EqualError(t, err, "config `allowlist` contains both true and false rules, but no default set for 0.0.0.0/0")
|
require.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[string]any{
|
c.Settings["allowlist"] = map[string]any{
|
||||||
@@ -42,7 +42,7 @@ func TestNewAllowListFromConfig(t *testing.T) {
|
|||||||
"fd00::/8": true,
|
"fd00::/8": true,
|
||||||
"fd00:fd00::/16": false,
|
"fd00:fd00::/16": false,
|
||||||
}
|
}
|
||||||
r, err = newAllowListFromConfig(c, "allowlist", nil)
|
_, err = newAllowListFromConfig(c, "allowlist", nil)
|
||||||
require.EqualError(t, err, "config `allowlist` contains both true and false rules, but no default set for ::/0")
|
require.EqualError(t, err, "config `allowlist` contains both true and false rules, but no default set for ::/0")
|
||||||
|
|
||||||
c.Settings["allowlist"] = map[string]any{
|
c.Settings["allowlist"] = map[string]any{
|
||||||
@@ -75,7 +75,7 @@ func TestNewAllowListFromConfig(t *testing.T) {
|
|||||||
`docker.*`: "foo",
|
`docker.*`: "foo",
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
lr, err := NewLocalAllowListFromConfig(c, "allowlist")
|
_, err = NewLocalAllowListFromConfig(c, "allowlist")
|
||||||
require.EqualError(t, err, "config `allowlist.interfaces` has invalid value (type string): foo")
|
require.EqualError(t, err, "config `allowlist.interfaces` has invalid value (type string): foo")
|
||||||
|
|
||||||
c.Settings["allowlist"] = map[string]any{
|
c.Settings["allowlist"] = map[string]any{
|
||||||
@@ -84,7 +84,7 @@ func TestNewAllowListFromConfig(t *testing.T) {
|
|||||||
`eth.*`: true,
|
`eth.*`: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
lr, err = NewLocalAllowListFromConfig(c, "allowlist")
|
_, err = NewLocalAllowListFromConfig(c, "allowlist")
|
||||||
require.EqualError(t, err, "config `allowlist.interfaces` values must all be the same true/false value")
|
require.EqualError(t, err, "config `allowlist.interfaces` values must all be the same true/false value")
|
||||||
|
|
||||||
c.Settings["allowlist"] = map[string]any{
|
c.Settings["allowlist"] = map[string]any{
|
||||||
@@ -92,7 +92,7 @@ func TestNewAllowListFromConfig(t *testing.T) {
|
|||||||
`docker.*`: false,
|
`docker.*`: false,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
lr, err = NewLocalAllowListFromConfig(c, "allowlist")
|
lr, err := NewLocalAllowListFromConfig(c, "allowlist")
|
||||||
if assert.NoError(t, err) {
|
if assert.NoError(t, err) {
|
||||||
assert.NotNil(t, lr)
|
assert.NotNil(t, lr)
|
||||||
}
|
}
|
||||||
|
|||||||
10
bits.go
10
bits.go
@@ -18,7 +18,7 @@ type Bits struct {
|
|||||||
func NewBits(bits uint64) *Bits {
|
func NewBits(bits uint64) *Bits {
|
||||||
return &Bits{
|
return &Bits{
|
||||||
length: bits,
|
length: bits,
|
||||||
bits: make([]bool, bits, bits),
|
bits: make([]bool, bits),
|
||||||
current: 0,
|
current: 0,
|
||||||
lostCounter: metrics.GetOrRegisterCounter("network.packets.lost", nil),
|
lostCounter: metrics.GetOrRegisterCounter("network.packets.lost", nil),
|
||||||
dupeCounter: metrics.GetOrRegisterCounter("network.packets.duplicate", nil),
|
dupeCounter: metrics.GetOrRegisterCounter("network.packets.duplicate", nil),
|
||||||
@@ -28,7 +28,7 @@ func NewBits(bits uint64) *Bits {
|
|||||||
|
|
||||||
func (b *Bits) Check(l logrus.FieldLogger, i uint64) bool {
|
func (b *Bits) Check(l logrus.FieldLogger, i uint64) bool {
|
||||||
// If i is the next number, return true.
|
// If i is the next number, return true.
|
||||||
if i > b.current || (i == 0 && b.firstSeen == false && b.current < b.length) {
|
if i > b.current || (i == 0 && !b.firstSeen && b.current < b.length) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -51,7 +51,7 @@ func (b *Bits) Update(l *logrus.Logger, i uint64) bool {
|
|||||||
// If i is the next number, return true and update current.
|
// If i is the next number, return true and update current.
|
||||||
if i == b.current+1 {
|
if i == b.current+1 {
|
||||||
// Report missed packets, we can only understand what was missed after the first window has been gone through
|
// Report missed packets, we can only understand what was missed after the first window has been gone through
|
||||||
if i > b.length && b.bits[i%b.length] == false {
|
if i > b.length && !b.bits[i%b.length] {
|
||||||
b.lostCounter.Inc(1)
|
b.lostCounter.Inc(1)
|
||||||
}
|
}
|
||||||
b.bits[i%b.length] = true
|
b.bits[i%b.length] = true
|
||||||
@@ -104,7 +104,7 @@ func (b *Bits) Update(l *logrus.Logger, i uint64) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Allow for the 0 packet to come in within the first window
|
// Allow for the 0 packet to come in within the first window
|
||||||
if i == 0 && b.firstSeen == false && b.current < b.length {
|
if i == 0 && !b.firstSeen && b.current < b.length {
|
||||||
b.firstSeen = true
|
b.firstSeen = true
|
||||||
b.bits[i%b.length] = true
|
b.bits[i%b.length] = true
|
||||||
return true
|
return true
|
||||||
@@ -122,7 +122,7 @@ func (b *Bits) Update(l *logrus.Logger, i uint64) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if b.bits[i%b.length] == true {
|
if b.bits[i%b.length] {
|
||||||
if l.Level >= logrus.DebugLevel {
|
if l.Level >= logrus.DebugLevel {
|
||||||
l.WithField("receiveWindow", m{"accepted": false, "currentCounter": b.current, "incomingCounter": i, "reason": "old duplicate"}).
|
l.WithField("receiveWindow", m{"accepted": false, "currentCounter": b.current, "incomingCounter": i, "reason": "old duplicate"}).
|
||||||
Debug("Receive window")
|
Debug("Receive window")
|
||||||
|
|||||||
@@ -20,8 +20,6 @@ import (
|
|||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
const publicKeyLen = 32
|
|
||||||
|
|
||||||
type certificateV1 struct {
|
type certificateV1 struct {
|
||||||
details detailsV1
|
details detailsV1
|
||||||
signature []byte
|
signature []byte
|
||||||
|
|||||||
@@ -113,14 +113,14 @@ func TestCertificateV2_MarshalJSON(t *testing.T) {
|
|||||||
signature: []byte("1234567890abcedf1234567890abcedf1234567890abcedf1234567890abcedf"),
|
signature: []byte("1234567890abcedf1234567890abcedf1234567890abcedf1234567890abcedf"),
|
||||||
}
|
}
|
||||||
|
|
||||||
b, err := nc.MarshalJSON()
|
_, err := nc.MarshalJSON()
|
||||||
require.ErrorIs(t, err, ErrMissingDetails)
|
require.ErrorIs(t, err, ErrMissingDetails)
|
||||||
|
|
||||||
rd, err := nc.details.Marshal()
|
rd, err := nc.details.Marshal()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
nc.rawDetails = rd
|
nc.rawDetails = rd
|
||||||
b, err = nc.MarshalJSON()
|
b, err := nc.MarshalJSON()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.JSONEq(
|
assert.JSONEq(
|
||||||
t,
|
t,
|
||||||
@@ -174,8 +174,9 @@ func TestCertificateV2_VerifyPrivateKey(t *testing.T) {
|
|||||||
require.ErrorIs(t, err, ErrInvalidPrivateKey)
|
require.ErrorIs(t, err, ErrInvalidPrivateKey)
|
||||||
|
|
||||||
c, _, priv, _ = NewTestCert(Version2, Curve_P256, ca2, caKey2, "test", time.Time{}, time.Time{}, nil, nil, nil)
|
c, _, priv, _ = NewTestCert(Version2, Curve_P256, ca2, caKey2, "test", time.Time{}, time.Time{}, nil, nil, nil)
|
||||||
rawPriv, b, curve, err = UnmarshalPrivateKeyFromPEM(priv)
|
_, _, curve, err = UnmarshalPrivateKeyFromPEM(priv)
|
||||||
|
assert.Equal(t, err, nil)
|
||||||
|
assert.Equal(t, curve, Curve_P256)
|
||||||
err = c.VerifyPrivateKey(Curve_P256, priv[:16])
|
err = c.VerifyPrivateKey(Curve_P256, priv[:16])
|
||||||
require.ErrorIs(t, err, ErrInvalidPrivateKey)
|
require.ErrorIs(t, err, ErrInvalidPrivateKey)
|
||||||
|
|
||||||
@@ -261,6 +262,7 @@ func TestCertificateV2_marshalForSigningStability(t *testing.T) {
|
|||||||
assert.Equal(t, expectedRawDetails, db)
|
assert.Equal(t, expectedRawDetails, db)
|
||||||
|
|
||||||
expectedForSigning, err := hex.DecodeString(expectedRawDetailsStr + "00313233343536373839306162636564666768696a313233343536373839306162")
|
expectedForSigning, err := hex.DecodeString(expectedRawDetailsStr + "00313233343536373839306162636564666768696a313233343536373839306162")
|
||||||
|
require.NoError(t, err)
|
||||||
b, err := nc.marshalForSigning()
|
b, err := nc.marshalForSigning()
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.Equal(t, expectedForSigning, b)
|
assert.Equal(t, expectedForSigning, b)
|
||||||
|
|||||||
@@ -227,6 +227,9 @@ func UnmarshalNebulaEncryptedData(b []byte) (*NebulaEncryptedData, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func unmarshalArgon2Parameters(params *RawNebulaArgon2Parameters) (*Argon2Parameters, error) {
|
func unmarshalArgon2Parameters(params *RawNebulaArgon2Parameters) (*Argon2Parameters, error) {
|
||||||
|
// Are we testing the compilers types here?
|
||||||
|
// No value of int32 is lewss than math.MinInt32.
|
||||||
|
// By definition these checks can never be true.
|
||||||
if params.Version < math.MinInt32 || params.Version > math.MaxInt32 {
|
if params.Version < math.MinInt32 || params.Version > math.MaxInt32 {
|
||||||
return nil, fmt.Errorf("Argon2Parameters Version must be at least %d and no more than %d", math.MinInt32, math.MaxInt32)
|
return nil, fmt.Errorf("Argon2Parameters Version must be at least %d and no more than %d", math.MinInt32, math.MaxInt32)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,12 +72,14 @@ qrlJ69wer3ZUHFXA
|
|||||||
require.EqualError(t, err, "key was not 64 bytes, is invalid ed25519 private key")
|
require.EqualError(t, err, "key was not 64 bytes, is invalid ed25519 private key")
|
||||||
assert.Nil(t, k)
|
assert.Nil(t, k)
|
||||||
assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
|
assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
|
||||||
|
assert.Equal(t, curve, Curve_CURVE25519)
|
||||||
|
|
||||||
// Fail due to invalid banner
|
// Fail due to invalid banner
|
||||||
curve, k, rest, err = DecryptAndUnmarshalSigningPrivateKey(passphrase, rest)
|
curve, k, rest, err = DecryptAndUnmarshalSigningPrivateKey(passphrase, rest)
|
||||||
require.EqualError(t, err, "bytes did not contain a proper nebula encrypted Ed25519/ECDSA private key banner")
|
require.EqualError(t, err, "bytes did not contain a proper nebula encrypted Ed25519/ECDSA private key banner")
|
||||||
assert.Nil(t, k)
|
assert.Nil(t, k)
|
||||||
assert.Equal(t, rest, invalidPem)
|
assert.Equal(t, rest, invalidPem)
|
||||||
|
assert.Equal(t, curve, Curve_CURVE25519)
|
||||||
|
|
||||||
// Fail due to ivalid PEM format, because
|
// Fail due to ivalid PEM format, because
|
||||||
// it's missing the requisite pre-encapsulation boundary.
|
// it's missing the requisite pre-encapsulation boundary.
|
||||||
@@ -85,12 +87,14 @@ qrlJ69wer3ZUHFXA
|
|||||||
require.EqualError(t, err, "input did not contain a valid PEM encoded block")
|
require.EqualError(t, err, "input did not contain a valid PEM encoded block")
|
||||||
assert.Nil(t, k)
|
assert.Nil(t, k)
|
||||||
assert.Equal(t, rest, invalidPem)
|
assert.Equal(t, rest, invalidPem)
|
||||||
|
assert.Equal(t, curve, Curve_CURVE25519)
|
||||||
|
|
||||||
// Fail due to invalid passphrase
|
// Fail due to invalid passphrase
|
||||||
curve, k, rest, err = DecryptAndUnmarshalSigningPrivateKey([]byte("invalid passphrase"), privKey)
|
curve, k, rest, err = DecryptAndUnmarshalSigningPrivateKey([]byte("invalid passphrase"), privKey)
|
||||||
require.EqualError(t, err, "invalid passphrase or corrupt private key")
|
require.EqualError(t, err, "invalid passphrase or corrupt private key")
|
||||||
assert.Nil(t, k)
|
assert.Nil(t, k)
|
||||||
assert.Equal(t, []byte{}, rest)
|
assert.Equal(t, []byte{}, rest)
|
||||||
|
assert.Equal(t, curve, Curve_CURVE25519)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestEncryptAndMarshalSigningPrivateKey(t *testing.T) {
|
func TestEncryptAndMarshalSigningPrivateKey(t *testing.T) {
|
||||||
|
|||||||
@@ -21,6 +21,9 @@ func NewTestCaCert(version Version, curve Curve, before, after time.Time, networ
|
|||||||
switch curve {
|
switch curve {
|
||||||
case Curve_CURVE25519:
|
case Curve_CURVE25519:
|
||||||
pub, priv, err = ed25519.GenerateKey(rand.Reader)
|
pub, priv, err = ed25519.GenerateKey(rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
case Curve_P256:
|
case Curve_P256:
|
||||||
privk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
privk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -97,12 +97,14 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|||||||
// Fail due to short key
|
// Fail due to short key
|
||||||
k, rest, curve, err = UnmarshalSigningPrivateKeyFromPEM(rest)
|
k, rest, curve, err = UnmarshalSigningPrivateKeyFromPEM(rest)
|
||||||
assert.Nil(t, k)
|
assert.Nil(t, k)
|
||||||
|
assert.Equal(t, Curve_CURVE25519, curve)
|
||||||
assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
|
assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
|
||||||
require.EqualError(t, err, "key was not 64 bytes, is invalid Ed25519 private key")
|
require.EqualError(t, err, "key was not 64 bytes, is invalid Ed25519 private key")
|
||||||
|
|
||||||
// Fail due to invalid banner
|
// Fail due to invalid banner
|
||||||
k, rest, curve, err = UnmarshalSigningPrivateKeyFromPEM(rest)
|
k, rest, curve, err = UnmarshalSigningPrivateKeyFromPEM(rest)
|
||||||
assert.Nil(t, k)
|
assert.Nil(t, k)
|
||||||
|
assert.Equal(t, Curve_CURVE25519, curve)
|
||||||
assert.Equal(t, rest, invalidPem)
|
assert.Equal(t, rest, invalidPem)
|
||||||
require.EqualError(t, err, "bytes did not contain a proper Ed25519/ECDSA private key banner")
|
require.EqualError(t, err, "bytes did not contain a proper Ed25519/ECDSA private key banner")
|
||||||
|
|
||||||
@@ -110,6 +112,7 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
|
|||||||
// it's missing the requisite pre-encapsulation boundary.
|
// it's missing the requisite pre-encapsulation boundary.
|
||||||
k, rest, curve, err = UnmarshalSigningPrivateKeyFromPEM(rest)
|
k, rest, curve, err = UnmarshalSigningPrivateKeyFromPEM(rest)
|
||||||
assert.Nil(t, k)
|
assert.Nil(t, k)
|
||||||
|
assert.Equal(t, Curve_CURVE25519, curve)
|
||||||
assert.Equal(t, rest, invalidPem)
|
assert.Equal(t, rest, invalidPem)
|
||||||
require.EqualError(t, err, "input did not contain a valid PEM encoded block")
|
require.EqualError(t, err, "input did not contain a valid PEM encoded block")
|
||||||
}
|
}
|
||||||
@@ -159,12 +162,14 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
|
|||||||
// Fail due to short key
|
// Fail due to short key
|
||||||
k, rest, curve, err = UnmarshalPrivateKeyFromPEM(rest)
|
k, rest, curve, err = UnmarshalPrivateKeyFromPEM(rest)
|
||||||
assert.Nil(t, k)
|
assert.Nil(t, k)
|
||||||
|
assert.Equal(t, Curve_CURVE25519, curve)
|
||||||
assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
|
assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
|
||||||
require.EqualError(t, err, "key was not 32 bytes, is invalid CURVE25519 private key")
|
require.EqualError(t, err, "key was not 32 bytes, is invalid CURVE25519 private key")
|
||||||
|
|
||||||
// Fail due to invalid banner
|
// Fail due to invalid banner
|
||||||
k, rest, curve, err = UnmarshalPrivateKeyFromPEM(rest)
|
k, rest, curve, err = UnmarshalPrivateKeyFromPEM(rest)
|
||||||
assert.Nil(t, k)
|
assert.Nil(t, k)
|
||||||
|
assert.Equal(t, Curve_CURVE25519, curve)
|
||||||
assert.Equal(t, rest, invalidPem)
|
assert.Equal(t, rest, invalidPem)
|
||||||
require.EqualError(t, err, "bytes did not contain a proper private key banner")
|
require.EqualError(t, err, "bytes did not contain a proper private key banner")
|
||||||
|
|
||||||
@@ -172,6 +177,7 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
|
|||||||
// it's missing the requisite pre-encapsulation boundary.
|
// it's missing the requisite pre-encapsulation boundary.
|
||||||
k, rest, curve, err = UnmarshalPrivateKeyFromPEM(rest)
|
k, rest, curve, err = UnmarshalPrivateKeyFromPEM(rest)
|
||||||
assert.Nil(t, k)
|
assert.Nil(t, k)
|
||||||
|
assert.Equal(t, Curve_CURVE25519, curve)
|
||||||
assert.Equal(t, rest, invalidPem)
|
assert.Equal(t, rest, invalidPem)
|
||||||
require.EqualError(t, err, "input did not contain a valid PEM encoded block")
|
require.EqualError(t, err, "input did not contain a valid PEM encoded block")
|
||||||
}
|
}
|
||||||
@@ -275,12 +281,14 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
|
|||||||
// Fail due to short key
|
// Fail due to short key
|
||||||
k, rest, curve, err = UnmarshalPublicKeyFromPEM(rest)
|
k, rest, curve, err = UnmarshalPublicKeyFromPEM(rest)
|
||||||
assert.Nil(t, k)
|
assert.Nil(t, k)
|
||||||
|
assert.Equal(t, Curve_CURVE25519, curve)
|
||||||
assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
|
assert.Equal(t, rest, appendByteSlices(invalidBanner, invalidPem))
|
||||||
require.EqualError(t, err, "key was not 32 bytes, is invalid CURVE25519 public key")
|
require.EqualError(t, err, "key was not 32 bytes, is invalid CURVE25519 public key")
|
||||||
|
|
||||||
// Fail due to invalid banner
|
// Fail due to invalid banner
|
||||||
k, rest, curve, err = UnmarshalPublicKeyFromPEM(rest)
|
k, rest, curve, err = UnmarshalPublicKeyFromPEM(rest)
|
||||||
assert.Nil(t, k)
|
assert.Nil(t, k)
|
||||||
|
assert.Equal(t, Curve_CURVE25519, curve)
|
||||||
require.EqualError(t, err, "bytes did not contain a proper public key banner")
|
require.EqualError(t, err, "bytes did not contain a proper public key banner")
|
||||||
assert.Equal(t, rest, invalidPem)
|
assert.Equal(t, rest, invalidPem)
|
||||||
|
|
||||||
@@ -288,6 +296,7 @@ AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
|
|||||||
// it's missing the requisite pre-encapsulation boundary.
|
// it's missing the requisite pre-encapsulation boundary.
|
||||||
k, rest, curve, err = UnmarshalPublicKeyFromPEM(rest)
|
k, rest, curve, err = UnmarshalPublicKeyFromPEM(rest)
|
||||||
assert.Nil(t, k)
|
assert.Nil(t, k)
|
||||||
|
assert.Equal(t, Curve_CURVE25519, curve)
|
||||||
assert.Equal(t, rest, invalidPem)
|
assert.Equal(t, rest, invalidPem)
|
||||||
require.EqualError(t, err, "input did not contain a valid PEM encoded block")
|
require.EqualError(t, err, "input did not contain a valid PEM encoded block")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@ func TestCertificateV1_Sign(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub, priv, err := ed25519.GenerateKey(rand.Reader)
|
pub, priv, err := ed25519.GenerateKey(rand.Reader)
|
||||||
|
require.NoError(t, err)
|
||||||
c, err := tbs.Sign(&certificateV1{details: detailsV1{notBefore: before, notAfter: after}}, Curve_CURVE25519, priv)
|
c, err := tbs.Sign(&certificateV1{details: detailsV1{notBefore: before, notAfter: after}}, Curve_CURVE25519, priv)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
assert.NotNil(t, c)
|
assert.NotNil(t, c)
|
||||||
|
|||||||
@@ -22,6 +22,9 @@ func NewTestCaCert(version cert.Version, curve cert.Curve, before, after time.Ti
|
|||||||
switch curve {
|
switch curve {
|
||||||
case cert.Curve_CURVE25519:
|
case cert.Curve_CURVE25519:
|
||||||
pub, priv, err = ed25519.GenerateKey(rand.Reader)
|
pub, priv, err = ed25519.GenerateKey(rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
case cert.Curve_P256:
|
case cert.Curve_P256:
|
||||||
privk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
privk, err := ecdsa.GenerateKey(elliptic.P256(), rand.Reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -81,7 +81,7 @@ func parseArgonParameters(memory uint, parallelism uint, iterations uint) (*cert
|
|||||||
return cert.NewArgon2Parameters(uint32(memory), uint8(parallelism), uint32(iterations)), nil
|
return cert.NewArgon2Parameters(uint32(memory), uint8(parallelism), uint32(iterations)), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ca(args []string, out io.Writer, errOut io.Writer, pr PasswordReader) error {
|
func ca(args []string, out io.Writer, _ io.Writer, pr PasswordReader) error {
|
||||||
cf := newCaFlags()
|
cf := newCaFlags()
|
||||||
err := cf.set.Parse(args)
|
err := cf.set.Parse(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ func newKeygenFlags() *keygenFlags {
|
|||||||
return &cf
|
return &cf
|
||||||
}
|
}
|
||||||
|
|
||||||
func keygen(args []string, out io.Writer, errOut io.Writer) error {
|
func keygen(args []string, _ io.Writer, _ io.Writer) error {
|
||||||
cf := newKeygenFlags()
|
cf := newKeygenFlags()
|
||||||
err := cf.set.Parse(args)
|
err := cf.set.Parse(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package main
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
@@ -77,7 +76,7 @@ func assertHelpError(t *testing.T, err error, msg string) {
|
|||||||
case *helpError:
|
case *helpError:
|
||||||
// good
|
// good
|
||||||
default:
|
default:
|
||||||
t.Fatal(fmt.Sprintf("err was not a helpError: %q, expected %q", err, msg))
|
t.Fatalf("err was not a helpError: %q, expected %q", err, msg)
|
||||||
}
|
}
|
||||||
|
|
||||||
require.EqualError(t, err, msg)
|
require.EqualError(t, err, msg)
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ func p11Supported() bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func p11Flag(set *flag.FlagSet) *string {
|
func p11Flag(_ *flag.FlagSet) *string {
|
||||||
var ret = ""
|
var ret = ""
|
||||||
return &ret
|
return &ret
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/skip2/go-qrcode"
|
"github.com/skip2/go-qrcode"
|
||||||
"github.com/slackhq/nebula/cert"
|
"github.com/slackhq/nebula/cert"
|
||||||
@@ -29,7 +29,7 @@ func newPrintFlags() *printFlags {
|
|||||||
return &pf
|
return &pf
|
||||||
}
|
}
|
||||||
|
|
||||||
func printCert(args []string, out io.Writer, errOut io.Writer) error {
|
func printCert(args []string, out io.Writer, _ io.Writer) error {
|
||||||
pf := newPrintFlags()
|
pf := newPrintFlags()
|
||||||
err := pf.set.Parse(args)
|
err := pf.set.Parse(args)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -72,7 +72,7 @@ func printCert(args []string, out io.Writer, errOut io.Writer) error {
|
|||||||
qrBytes = append(qrBytes, b...)
|
qrBytes = append(qrBytes, b...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if rawCert == nil || len(rawCert) == 0 || strings.TrimSpace(string(rawCert)) == "" {
|
if len(rawCert) == 0 || len(bytes.TrimSpace(rawCert)) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/slackhq/nebula/cert"
|
"github.com/slackhq/nebula/cert"
|
||||||
@@ -52,7 +52,7 @@ func verify(args []string, out io.Writer, errOut io.Writer) error {
|
|||||||
return fmt.Errorf("error while adding ca cert to pool: %w", err)
|
return fmt.Errorf("error while adding ca cert to pool: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if rawCACert == nil || len(rawCACert) == 0 || strings.TrimSpace(string(rawCACert)) == "" {
|
if len(rawCACert) == 0 || len(bytes.TrimSpace(rawCACert)) == 0 {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ func Test_verify(t *testing.T) {
|
|||||||
crt, _ := NewTestCert(ca, caPriv, "test-cert", time.Now().Add(time.Hour*-1), time.Now().Add(time.Hour), nil, nil, nil)
|
crt, _ := NewTestCert(ca, caPriv, "test-cert", time.Now().Add(time.Hour*-1), time.Now().Add(time.Hour), nil, nil, nil)
|
||||||
// Slightly evil hack to modify the certificate after it was sealed to generate an invalid signature
|
// Slightly evil hack to modify the certificate after it was sealed to generate an invalid signature
|
||||||
pub := crt.PublicKey()
|
pub := crt.PublicKey()
|
||||||
for i, _ := range pub {
|
for i := range pub {
|
||||||
pub[i] = 0
|
pub[i] = 0
|
||||||
}
|
}
|
||||||
b, _ = crt.MarshalPEM()
|
b, _ = crt.MarshalPEM()
|
||||||
|
|||||||
@@ -51,10 +51,7 @@ func (p *program) Stop(s service.Service) error {
|
|||||||
|
|
||||||
func fileExists(filename string) bool {
|
func fileExists(filename string) bool {
|
||||||
_, err := os.Stat(filename)
|
_, err := os.Stat(filename)
|
||||||
if os.IsNotExist(err) {
|
return !os.IsNotExist(err)
|
||||||
return false
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func doService(configPath *string, configTest *bool, build string, serviceFlag *string) {
|
func doService(configPath *string, configTest *bool, build string, serviceFlag *string) {
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ func (c *C) Load(path string) error {
|
|||||||
|
|
||||||
func (c *C) LoadString(raw string) error {
|
func (c *C) LoadString(raw string) error {
|
||||||
if raw == "" {
|
if raw == "" {
|
||||||
return errors.New("Empty configuration")
|
return errors.New("empty configuration")
|
||||||
}
|
}
|
||||||
return c.parseRaw([]byte(raw))
|
return c.parseRaw([]byte(raw))
|
||||||
}
|
}
|
||||||
@@ -243,7 +243,7 @@ func (c *C) GetInt(k string, d int) int {
|
|||||||
// GetUint32 will get the uint32 for k or return the default d if not found or invalid
|
// GetUint32 will get the uint32 for k or return the default d if not found or invalid
|
||||||
func (c *C) GetUint32(k string, d uint32) uint32 {
|
func (c *C) GetUint32(k string, d uint32) uint32 {
|
||||||
r := c.GetInt(k, int(d))
|
r := c.GetInt(k, int(d))
|
||||||
if uint64(r) > uint64(math.MaxUint32) {
|
if r < 0 || uint64(r) > uint64(math.MaxUint32) {
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
return uint32(r)
|
return uint32(r)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/rcrowley/go-metrics"
|
"github.com/rcrowley/go-metrics"
|
||||||
@@ -27,14 +28,14 @@ const (
|
|||||||
|
|
||||||
type connectionManager struct {
|
type connectionManager struct {
|
||||||
in map[uint32]struct{}
|
in map[uint32]struct{}
|
||||||
inLock syncRWMutex
|
inLock *sync.RWMutex
|
||||||
|
|
||||||
out map[uint32]struct{}
|
out map[uint32]struct{}
|
||||||
outLock syncRWMutex
|
outLock *sync.RWMutex
|
||||||
|
|
||||||
// relayUsed holds which relay localIndexs are in use
|
// relayUsed holds which relay localIndexs are in use
|
||||||
relayUsed map[uint32]struct{}
|
relayUsed map[uint32]struct{}
|
||||||
relayUsedLock syncRWMutex
|
relayUsedLock *sync.RWMutex
|
||||||
|
|
||||||
hostMap *HostMap
|
hostMap *HostMap
|
||||||
trafficTimer *LockingTimerWheel[uint32]
|
trafficTimer *LockingTimerWheel[uint32]
|
||||||
@@ -59,12 +60,12 @@ func newConnectionManager(ctx context.Context, l *logrus.Logger, intf *Interface
|
|||||||
nc := &connectionManager{
|
nc := &connectionManager{
|
||||||
hostMap: intf.hostMap,
|
hostMap: intf.hostMap,
|
||||||
in: make(map[uint32]struct{}),
|
in: make(map[uint32]struct{}),
|
||||||
inLock: newSyncRWMutex("connection-manager-in"),
|
inLock: &sync.RWMutex{},
|
||||||
out: make(map[uint32]struct{}),
|
out: make(map[uint32]struct{}),
|
||||||
outLock: newSyncRWMutex("connection-manager-out"),
|
outLock: &sync.RWMutex{},
|
||||||
relayUsed: make(map[uint32]struct{}),
|
relayUsed: make(map[uint32]struct{}),
|
||||||
relayUsedLock: newSyncRWMutex("connection-manager-relay-used"),
|
relayUsedLock: &sync.RWMutex{},
|
||||||
trafficTimer: NewLockingTimerWheel[uint32]("connection-manager-timer", time.Millisecond*500, max),
|
trafficTimer: NewLockingTimerWheel[uint32](time.Millisecond*500, max),
|
||||||
intf: intf,
|
intf: intf,
|
||||||
pendingDeletion: make(map[uint32]struct{}),
|
pendingDeletion: make(map[uint32]struct{}),
|
||||||
checkInterval: checkInterval,
|
checkInterval: checkInterval,
|
||||||
@@ -153,7 +154,7 @@ func (n *connectionManager) Run(ctx context.Context) {
|
|||||||
defer clockSource.Stop()
|
defer clockSource.Stop()
|
||||||
|
|
||||||
p := []byte("")
|
p := []byte("")
|
||||||
nb := make([]byte, 12, 12)
|
nb := make([]byte, 12)
|
||||||
out := make([]byte, mtu)
|
out := make([]byte, mtu)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@@ -354,7 +355,7 @@ func (n *connectionManager) makeTrafficDecision(localIndex uint32, now time.Time
|
|||||||
decision = tryRehandshake
|
decision = tryRehandshake
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
if n.shouldSwapPrimary(hostinfo, primary) {
|
if n.shouldSwapPrimary(hostinfo) {
|
||||||
decision = swapPrimary
|
decision = swapPrimary
|
||||||
} else {
|
} else {
|
||||||
// migrate the relays to the primary, if in use.
|
// migrate the relays to the primary, if in use.
|
||||||
@@ -383,7 +384,7 @@ func (n *connectionManager) makeTrafficDecision(localIndex uint32, now time.Time
|
|||||||
}
|
}
|
||||||
|
|
||||||
decision := doNothing
|
decision := doNothing
|
||||||
if hostinfo != nil && hostinfo.ConnectionState != nil && mainHostInfo {
|
if hostinfo.ConnectionState != nil && mainHostInfo {
|
||||||
if !outTraffic {
|
if !outTraffic {
|
||||||
// If we aren't sending or receiving traffic then its an unused tunnel and we don't to test the tunnel.
|
// If we aren't sending or receiving traffic then its an unused tunnel and we don't to test the tunnel.
|
||||||
// Just maintain NAT state if configured to do so.
|
// Just maintain NAT state if configured to do so.
|
||||||
@@ -420,7 +421,7 @@ func (n *connectionManager) makeTrafficDecision(localIndex uint32, now time.Time
|
|||||||
return decision, hostinfo, nil
|
return decision, hostinfo, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (n *connectionManager) shouldSwapPrimary(current, primary *HostInfo) bool {
|
func (n *connectionManager) shouldSwapPrimary(current *HostInfo) bool {
|
||||||
// The primary tunnel is the most recent handshake to complete locally and should work entirely fine.
|
// The primary tunnel is the most recent handshake to complete locally and should work entirely fine.
|
||||||
// If we are here then we have multiple tunnels for a host pair and neither side believes the same tunnel is primary.
|
// If we are here then we have multiple tunnels for a host pair and neither side believes the same tunnel is primary.
|
||||||
// Let's sort this out.
|
// Let's sort this out.
|
||||||
@@ -497,7 +498,7 @@ func (n *connectionManager) tryRehandshake(hostinfo *HostInfo) {
|
|||||||
cs := n.intf.pki.getCertState()
|
cs := n.intf.pki.getCertState()
|
||||||
curCrt := hostinfo.ConnectionState.myCert
|
curCrt := hostinfo.ConnectionState.myCert
|
||||||
myCrt := cs.getCertificate(curCrt.Version())
|
myCrt := cs.getCertificate(curCrt.Version())
|
||||||
if curCrt.Version() >= cs.defaultVersion && bytes.Equal(curCrt.Signature(), myCrt.Signature()) == true {
|
if curCrt.Version() >= cs.initiatingVersion && bytes.Equal(curCrt.Signature(), myCrt.Signature()) {
|
||||||
// The current tunnel is using the latest certificate and version, no need to rehandshake.
|
// The current tunnel is using the latest certificate and version, no need to rehandshake.
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ func Test_NewConnectionManagerTest(t *testing.T) {
|
|||||||
hostMap.preferredRanges.Store(&preferredRanges)
|
hostMap.preferredRanges.Store(&preferredRanges)
|
||||||
|
|
||||||
cs := &CertState{
|
cs := &CertState{
|
||||||
defaultVersion: cert.Version1,
|
initiatingVersion: cert.Version1,
|
||||||
privateKey: []byte{},
|
privateKey: []byte{},
|
||||||
v1Cert: &dummyCert{version: cert.Version1},
|
v1Cert: &dummyCert{version: cert.Version1},
|
||||||
v1HandshakeBytes: []byte{},
|
v1HandshakeBytes: []byte{},
|
||||||
@@ -69,7 +69,7 @@ func Test_NewConnectionManagerTest(t *testing.T) {
|
|||||||
punchy := NewPunchyFromConfig(l, config.NewC(l))
|
punchy := NewPunchyFromConfig(l, config.NewC(l))
|
||||||
nc := newConnectionManager(ctx, l, ifce, 5, 10, punchy)
|
nc := newConnectionManager(ctx, l, ifce, 5, 10, punchy)
|
||||||
p := []byte("")
|
p := []byte("")
|
||||||
nb := make([]byte, 12, 12)
|
nb := make([]byte, 12)
|
||||||
out := make([]byte, mtu)
|
out := make([]byte, mtu)
|
||||||
|
|
||||||
// Add an ip we have established a connection w/ to hostmap
|
// Add an ip we have established a connection w/ to hostmap
|
||||||
@@ -126,7 +126,7 @@ func Test_NewConnectionManagerTest2(t *testing.T) {
|
|||||||
hostMap.preferredRanges.Store(&preferredRanges)
|
hostMap.preferredRanges.Store(&preferredRanges)
|
||||||
|
|
||||||
cs := &CertState{
|
cs := &CertState{
|
||||||
defaultVersion: cert.Version1,
|
initiatingVersion: cert.Version1,
|
||||||
privateKey: []byte{},
|
privateKey: []byte{},
|
||||||
v1Cert: &dummyCert{version: cert.Version1},
|
v1Cert: &dummyCert{version: cert.Version1},
|
||||||
v1HandshakeBytes: []byte{},
|
v1HandshakeBytes: []byte{},
|
||||||
@@ -151,7 +151,7 @@ func Test_NewConnectionManagerTest2(t *testing.T) {
|
|||||||
punchy := NewPunchyFromConfig(l, config.NewC(l))
|
punchy := NewPunchyFromConfig(l, config.NewC(l))
|
||||||
nc := newConnectionManager(ctx, l, ifce, 5, 10, punchy)
|
nc := newConnectionManager(ctx, l, ifce, 5, 10, punchy)
|
||||||
p := []byte("")
|
p := []byte("")
|
||||||
nb := make([]byte, 12, 12)
|
nb := make([]byte, 12)
|
||||||
out := make([]byte, mtu)
|
out := make([]byte, mtu)
|
||||||
|
|
||||||
// Add an ip we have established a connection w/ to hostmap
|
// Add an ip we have established a connection w/ to hostmap
|
||||||
@@ -241,7 +241,7 @@ func Test_NewConnectionManagerTest_DisconnectInvalid(t *testing.T) {
|
|||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
cachedPeerCert, err := ncp.VerifyCertificate(now.Add(time.Second), peerCert)
|
cachedPeerCert, err := ncp.VerifyCertificate(now.Add(time.Second), peerCert)
|
||||||
|
require.NoError(t, err)
|
||||||
cs := &CertState{
|
cs := &CertState{
|
||||||
privateKey: []byte{},
|
privateKey: []byte{},
|
||||||
v1Cert: &dummyCert{},
|
v1Cert: &dummyCert{},
|
||||||
|
|||||||
@@ -4,6 +4,7 @@ import (
|
|||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
|
|
||||||
"github.com/flynn/noise"
|
"github.com/flynn/noise"
|
||||||
@@ -23,7 +24,7 @@ type ConnectionState struct {
|
|||||||
initiator bool
|
initiator bool
|
||||||
messageCounter atomic.Uint64
|
messageCounter atomic.Uint64
|
||||||
window *Bits
|
window *Bits
|
||||||
writeLock syncMutex
|
writeLock sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConnectionState(l *logrus.Logger, cs *CertState, crt cert.Certificate, initiator bool, pattern noise.HandshakePattern) (*ConnectionState, error) {
|
func NewConnectionState(l *logrus.Logger, cs *CertState, crt cert.Certificate, initiator bool, pattern noise.HandshakePattern) (*ConnectionState, error) {
|
||||||
@@ -75,8 +76,6 @@ func NewConnectionState(l *logrus.Logger, cs *CertState, crt cert.Certificate, i
|
|||||||
initiator: initiator,
|
initiator: initiator,
|
||||||
window: b,
|
window: b,
|
||||||
myCert: crt,
|
myCert: crt,
|
||||||
|
|
||||||
writeLock: newSyncMutex("connection-state-write"),
|
|
||||||
}
|
}
|
||||||
// always start the counter from 2, as packet 1 and packet 2 are handshake packets.
|
// always start the counter from 2, as packet 1 and packet 2 are handshake packets.
|
||||||
ci.messageCounter.Add(2)
|
ci.messageCounter.Add(2)
|
||||||
|
|||||||
@@ -215,7 +215,7 @@ func (c *Control) CloseTunnel(vpnIp netip.Addr, localOnly bool) bool {
|
|||||||
hostInfo.ConnectionState,
|
hostInfo.ConnectionState,
|
||||||
hostInfo,
|
hostInfo,
|
||||||
[]byte{},
|
[]byte{},
|
||||||
make([]byte, 12, 12),
|
make([]byte, 12),
|
||||||
make([]byte, mtu),
|
make([]byte, mtu),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -231,7 +231,7 @@ func (c *Control) CloseAllTunnels(excludeLighthouses bool) (closed int) {
|
|||||||
if excludeLighthouses && c.f.lightHouse.IsAnyLighthouseAddr(h.vpnAddrs) {
|
if excludeLighthouses && c.f.lightHouse.IsAnyLighthouseAddr(h.vpnAddrs) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.f.send(header.CloseTunnel, 0, h.ConnectionState, h, []byte{}, make([]byte, 12, 12), make([]byte, mtu))
|
c.f.send(header.CloseTunnel, 0, h.ConnectionState, h, []byte{}, make([]byte, 12), make([]byte, mtu))
|
||||||
c.f.closeTunnel(h)
|
c.f.closeTunnel(h)
|
||||||
|
|
||||||
c.l.WithField("vpnAddrs", h.vpnAddrs).WithField("udpAddr", h.remote).
|
c.l.WithField("vpnAddrs", h.vpnAddrs).WithField("udpAddr", h.remote).
|
||||||
@@ -282,9 +282,7 @@ func copyHostInfo(h *HostInfo, preferredRanges []netip.Prefix) ControlHostInfo {
|
|||||||
CurrentRemote: h.remote,
|
CurrentRemote: h.remote,
|
||||||
}
|
}
|
||||||
|
|
||||||
for i, a := range h.vpnAddrs {
|
copy(chi.VpnAddrs, h.vpnAddrs)
|
||||||
chi.VpnAddrs[i] = a
|
|
||||||
}
|
|
||||||
|
|
||||||
if h.ConnectionState != nil {
|
if h.ConnectionState != nil {
|
||||||
chi.MessageCounter = h.ConnectionState.messageCounter.Load()
|
chi.MessageCounter = h.ConnectionState.messageCounter.Load()
|
||||||
|
|||||||
@@ -27,12 +27,10 @@ func TestControl_GetHostInfoByVpnIp(t *testing.T) {
|
|||||||
|
|
||||||
ipNet := net.IPNet{
|
ipNet := net.IPNet{
|
||||||
IP: remote1.Addr().AsSlice(),
|
IP: remote1.Addr().AsSlice(),
|
||||||
Mask: net.IPMask{255, 255, 255, 0},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ipNet2 := net.IPNet{
|
ipNet2 := net.IPNet{
|
||||||
IP: remote2.Addr().AsSlice(),
|
IP: remote2.Addr().AsSlice(),
|
||||||
Mask: net.IPMask{255, 255, 255, 0},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
remotes := NewRemoteList([]netip.Addr{netip.IPv4Unspecified()}, nil)
|
remotes := NewRemoteList([]netip.Addr{netip.IPv4Unspecified()}, nil)
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
"github.com/gaissmai/bart"
|
"github.com/gaissmai/bart"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
@@ -20,7 +21,7 @@ var dnsServer *dns.Server
|
|||||||
var dnsAddr string
|
var dnsAddr string
|
||||||
|
|
||||||
type dnsRecords struct {
|
type dnsRecords struct {
|
||||||
syncRWMutex
|
sync.RWMutex
|
||||||
l *logrus.Logger
|
l *logrus.Logger
|
||||||
dnsMap4 map[string]netip.Addr
|
dnsMap4 map[string]netip.Addr
|
||||||
dnsMap6 map[string]netip.Addr
|
dnsMap6 map[string]netip.Addr
|
||||||
@@ -30,7 +31,6 @@ type dnsRecords struct {
|
|||||||
|
|
||||||
func newDnsRecords(l *logrus.Logger, cs *CertState, hostMap *HostMap) *dnsRecords {
|
func newDnsRecords(l *logrus.Logger, cs *CertState, hostMap *HostMap) *dnsRecords {
|
||||||
return &dnsRecords{
|
return &dnsRecords{
|
||||||
syncRWMutex: newSyncRWMutex("dns-records"),
|
|
||||||
l: l,
|
l: l,
|
||||||
dnsMap4: make(map[string]netip.Addr),
|
dnsMap4: make(map[string]netip.Addr),
|
||||||
dnsMap6: make(map[string]netip.Addr),
|
dnsMap6: make(map[string]netip.Addr),
|
||||||
|
|||||||
@@ -13,11 +13,11 @@ pki:
|
|||||||
# disconnect_invalid is a toggle to force a client to be disconnected if the certificate is expired or invalid.
|
# disconnect_invalid is a toggle to force a client to be disconnected if the certificate is expired or invalid.
|
||||||
#disconnect_invalid: true
|
#disconnect_invalid: true
|
||||||
|
|
||||||
# default_version controls which certificate version is used in handshakes.
|
# initiating_version controls which certificate version is used when initiating handshakes.
|
||||||
# This setting only applies if both a v1 and a v2 certificate are configured, in which case it will default to `1`.
|
# This setting only applies if both a v1 and a v2 certificate are configured, in which case it will default to `1`.
|
||||||
# Once all hosts in the mesh are configured with both a v1 and v2 certificate then this should be changed to `2`.
|
# Once all hosts in the mesh are configured with both a v1 and v2 certificate then this should be changed to `2`.
|
||||||
# After all hosts in the mesh are using a v2 certificate then v1 certificates are no longer needed.
|
# After all hosts in the mesh are using a v2 certificate then v1 certificates are no longer needed.
|
||||||
# default_version: 1
|
# initiating_version: 1
|
||||||
|
|
||||||
# The static host map defines a set of hosts with fixed IP addresses on the internet (or any network).
|
# The static host map defines a set of hosts with fixed IP addresses on the internet (or any network).
|
||||||
# A host can have multiple fixed IP addresses defined here, and nebula will try each when establishing a tunnel.
|
# A host can have multiple fixed IP addresses defined here, and nebula will try each when establishing a tunnel.
|
||||||
|
|||||||
16
firewall.go
16
firewall.go
@@ -10,6 +10,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/gaissmai/bart"
|
"github.com/gaissmai/bart"
|
||||||
@@ -75,7 +76,7 @@ type firewallMetrics struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type FirewallConntrack struct {
|
type FirewallConntrack struct {
|
||||||
syncMutex
|
sync.Mutex
|
||||||
|
|
||||||
Conns map[firewall.Packet]*conn
|
Conns map[firewall.Packet]*conn
|
||||||
TimerWheel *TimerWheel[firewall.Packet]
|
TimerWheel *TimerWheel[firewall.Packet]
|
||||||
@@ -163,7 +164,6 @@ func NewFirewall(l *logrus.Logger, tcpTimeout, UDPTimeout, defaultTimeout time.D
|
|||||||
|
|
||||||
return &Firewall{
|
return &Firewall{
|
||||||
Conntrack: &FirewallConntrack{
|
Conntrack: &FirewallConntrack{
|
||||||
syncMutex: newSyncMutex("firewall-conntrack"),
|
|
||||||
Conns: make(map[firewall.Packet]*conn),
|
Conns: make(map[firewall.Packet]*conn),
|
||||||
TimerWheel: NewTimerWheel[firewall.Packet](tmin, tmax),
|
TimerWheel: NewTimerWheel[firewall.Packet](tmin, tmax),
|
||||||
},
|
},
|
||||||
@@ -606,7 +606,7 @@ func (f *Firewall) evict(p firewall.Packet) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
newT := t.Expires.Sub(time.Now())
|
newT := time.Until(t.Expires)
|
||||||
|
|
||||||
// Timeout is in the future, re-add the timer
|
// Timeout is in the future, re-add the timer
|
||||||
if newT > 0 {
|
if newT > 0 {
|
||||||
@@ -832,7 +832,7 @@ func (fr *FirewallRule) match(p firewall.Packet, c *cert.CachedCertificate) bool
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Shortcut path for if groups, hosts, or cidr contained an `any`
|
// Shortcut path for if groups, hosts, or cidr contained an `any`
|
||||||
if fr.Any.match(p, c) {
|
if fr.Any.match(p) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -849,21 +849,21 @@ func (fr *FirewallRule) match(p firewall.Packet, c *cert.CachedCertificate) bool
|
|||||||
found = true
|
found = true
|
||||||
}
|
}
|
||||||
|
|
||||||
if found && sg.LocalCIDR.match(p, c) {
|
if found && sg.LocalCIDR.match(p) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if fr.Hosts != nil {
|
if fr.Hosts != nil {
|
||||||
if flc, ok := fr.Hosts[c.Certificate.Name()]; ok {
|
if flc, ok := fr.Hosts[c.Certificate.Name()]; ok {
|
||||||
if flc.match(p, c) {
|
if flc.match(p) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range fr.CIDR.Supernets(netip.PrefixFrom(p.RemoteAddr, p.RemoteAddr.BitLen())) {
|
for _, v := range fr.CIDR.Supernets(netip.PrefixFrom(p.RemoteAddr, p.RemoteAddr.BitLen())) {
|
||||||
if v.match(p, c) {
|
if v.match(p) {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -892,7 +892,7 @@ func (flc *firewallLocalCIDR) addRule(f *Firewall, localIp netip.Prefix) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (flc *firewallLocalCIDR) match(p firewall.Packet, c *cert.CachedCertificate) bool {
|
func (flc *firewallLocalCIDR) match(p firewall.Packet) bool {
|
||||||
if flc == nil {
|
if flc == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,22 +35,27 @@ func TestNewFirewall(t *testing.T) {
|
|||||||
assert.Equal(t, 3602, conntrack.TimerWheel.wheelLen)
|
assert.Equal(t, 3602, conntrack.TimerWheel.wheelLen)
|
||||||
|
|
||||||
fw = NewFirewall(l, time.Second, time.Hour, time.Minute, c)
|
fw = NewFirewall(l, time.Second, time.Hour, time.Minute, c)
|
||||||
|
conntrack = fw.Conntrack
|
||||||
assert.Equal(t, time.Hour, conntrack.TimerWheel.wheelDuration)
|
assert.Equal(t, time.Hour, conntrack.TimerWheel.wheelDuration)
|
||||||
assert.Equal(t, 3602, conntrack.TimerWheel.wheelLen)
|
assert.Equal(t, 3602, conntrack.TimerWheel.wheelLen)
|
||||||
|
|
||||||
fw = NewFirewall(l, time.Hour, time.Second, time.Minute, c)
|
fw = NewFirewall(l, time.Hour, time.Second, time.Minute, c)
|
||||||
|
conntrack = fw.Conntrack
|
||||||
assert.Equal(t, time.Hour, conntrack.TimerWheel.wheelDuration)
|
assert.Equal(t, time.Hour, conntrack.TimerWheel.wheelDuration)
|
||||||
assert.Equal(t, 3602, conntrack.TimerWheel.wheelLen)
|
assert.Equal(t, 3602, conntrack.TimerWheel.wheelLen)
|
||||||
|
|
||||||
fw = NewFirewall(l, time.Hour, time.Minute, time.Second, c)
|
fw = NewFirewall(l, time.Hour, time.Minute, time.Second, c)
|
||||||
|
conntrack = fw.Conntrack
|
||||||
assert.Equal(t, time.Hour, conntrack.TimerWheel.wheelDuration)
|
assert.Equal(t, time.Hour, conntrack.TimerWheel.wheelDuration)
|
||||||
assert.Equal(t, 3602, conntrack.TimerWheel.wheelLen)
|
assert.Equal(t, 3602, conntrack.TimerWheel.wheelLen)
|
||||||
|
|
||||||
fw = NewFirewall(l, time.Minute, time.Hour, time.Second, c)
|
fw = NewFirewall(l, time.Minute, time.Hour, time.Second, c)
|
||||||
|
conntrack = fw.Conntrack
|
||||||
assert.Equal(t, time.Hour, conntrack.TimerWheel.wheelDuration)
|
assert.Equal(t, time.Hour, conntrack.TimerWheel.wheelDuration)
|
||||||
assert.Equal(t, 3602, conntrack.TimerWheel.wheelLen)
|
assert.Equal(t, 3602, conntrack.TimerWheel.wheelLen)
|
||||||
|
|
||||||
fw = NewFirewall(l, time.Minute, time.Second, time.Hour, c)
|
fw = NewFirewall(l, time.Minute, time.Second, time.Hour, c)
|
||||||
|
conntrack = fw.Conntrack
|
||||||
assert.Equal(t, time.Hour, conntrack.TimerWheel.wheelDuration)
|
assert.Equal(t, time.Hour, conntrack.TimerWheel.wheelDuration)
|
||||||
assert.Equal(t, 3602, conntrack.TimerWheel.wheelLen)
|
assert.Equal(t, 3602, conntrack.TimerWheel.wheelLen)
|
||||||
}
|
}
|
||||||
|
|||||||
12
go.mod
12
go.mod
@@ -8,14 +8,13 @@ require (
|
|||||||
dario.cat/mergo v1.0.1
|
dario.cat/mergo v1.0.1
|
||||||
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
|
github.com/anmitsu/go-shlex v0.0.0-20200514113438-38f4b401e2be
|
||||||
github.com/armon/go-radix v1.0.0
|
github.com/armon/go-radix v1.0.0
|
||||||
github.com/clarkmcc/go-dag v0.0.0-20220908000337-9c3ba5b365fc
|
|
||||||
github.com/cyberdelia/go-metrics-graphite v0.0.0-20161219230853-39f87cc3b432
|
github.com/cyberdelia/go-metrics-graphite v0.0.0-20161219230853-39f87cc3b432
|
||||||
github.com/flynn/noise v1.1.0
|
github.com/flynn/noise v1.1.0
|
||||||
github.com/gaissmai/bart v0.20.1
|
github.com/gaissmai/bart v0.20.1
|
||||||
github.com/gogo/protobuf v1.3.2
|
github.com/gogo/protobuf v1.3.2
|
||||||
github.com/google/gopacket v1.1.19
|
github.com/google/gopacket v1.1.19
|
||||||
github.com/kardianos/service v1.2.2
|
github.com/kardianos/service v1.2.2
|
||||||
github.com/miekg/dns v1.1.64
|
github.com/miekg/dns v1.1.65
|
||||||
github.com/miekg/pkcs11 v1.1.2-0.20231115102856-9078ad6b9d4b
|
github.com/miekg/pkcs11 v1.1.2-0.20231115102856-9078ad6b9d4b
|
||||||
github.com/nbrownus/go-metrics-prometheus v0.0.0-20210712211119-974a6260965f
|
github.com/nbrownus/go-metrics-prometheus v0.0.0-20210712211119-974a6260965f
|
||||||
github.com/prometheus/client_golang v1.21.1
|
github.com/prometheus/client_golang v1.21.1
|
||||||
@@ -24,14 +23,13 @@ require (
|
|||||||
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e
|
||||||
github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6
|
github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6
|
||||||
github.com/stretchr/testify v1.10.0
|
github.com/stretchr/testify v1.10.0
|
||||||
github.com/timandy/routine v1.1.5
|
|
||||||
github.com/vishvananda/netlink v1.3.0
|
github.com/vishvananda/netlink v1.3.0
|
||||||
golang.org/x/crypto v0.36.0
|
golang.org/x/crypto v0.37.0
|
||||||
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090
|
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090
|
||||||
golang.org/x/net v0.38.0
|
golang.org/x/net v0.38.0
|
||||||
golang.org/x/sync v0.12.0
|
golang.org/x/sync v0.13.0
|
||||||
golang.org/x/sys v0.31.0
|
golang.org/x/sys v0.32.0
|
||||||
golang.org/x/term v0.30.0
|
golang.org/x/term v0.31.0
|
||||||
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2
|
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2
|
||||||
golang.zx2c4.com/wireguard v0.0.0-20230325221338-052af4a8072b
|
golang.zx2c4.com/wireguard v0.0.0-20230325221338-052af4a8072b
|
||||||
golang.zx2c4.com/wireguard/windows v0.5.3
|
golang.zx2c4.com/wireguard/windows v0.5.3
|
||||||
|
|||||||
26
go.sum
26
go.sum
@@ -17,8 +17,6 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
|
|||||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs=
|
||||||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||||
github.com/clarkmcc/go-dag v0.0.0-20220908000337-9c3ba5b365fc h1:6e91sWiDE69Jl0WUsY/LvTCBPRBe6b2j8H7W96JGJ4s=
|
|
||||||
github.com/clarkmcc/go-dag v0.0.0-20220908000337-9c3ba5b365fc/go.mod h1:RGIcF96ORCYAsdz60Ou9mPBNa4+DjoQFS8nelPniFoY=
|
|
||||||
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 h1:M5QgkYacWj0Xs8MhpIK/5uwU02icXpEoSo9sM2aRCps=
|
||||||
github.com/cyberdelia/go-metrics-graphite v0.0.0-20161219230853-39f87cc3b432/go.mod h1:xwIwAxMvYnVrGJPe2FKx5prTrnAjGOD8zvDOnxnrrkM=
|
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.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
@@ -85,8 +83,8 @@ github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
|||||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||||
github.com/miekg/dns v1.1.64 h1:wuZgD9wwCE6XMT05UU/mlSko71eRSXEAm2EbjQXLKnQ=
|
github.com/miekg/dns v1.1.65 h1:0+tIPHzUW0GCge7IiK3guGP57VAw7hoPDfApjkMD1Fc=
|
||||||
github.com/miekg/dns v1.1.64/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck=
|
github.com/miekg/dns v1.1.65/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck=
|
||||||
github.com/miekg/pkcs11 v1.1.2-0.20231115102856-9078ad6b9d4b h1:J/AzCvg5z0Hn1rqZUJjpbzALUmkKX0Zwbc/i4fw7Sfk=
|
github.com/miekg/pkcs11 v1.1.2-0.20231115102856-9078ad6b9d4b h1:J/AzCvg5z0Hn1rqZUJjpbzALUmkKX0Zwbc/i4fw7Sfk=
|
||||||
github.com/miekg/pkcs11 v1.1.2-0.20231115102856-9078ad6b9d4b/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
github.com/miekg/pkcs11 v1.1.2-0.20231115102856-9078ad6b9d4b/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
@@ -147,10 +145,6 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
|||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
github.com/timandy/routine v1.1.1 h1:6/Z7qLFZj3GrzuRksBFzIG8YGUh8CLhjnnMePBQTrEI=
|
|
||||||
github.com/timandy/routine v1.1.1/go.mod h1:OZHPOKSvqL/ZvqXFkNZyit0xIVelERptYXdAHH00adQ=
|
|
||||||
github.com/timandy/routine v1.1.5 h1:LSpm7Iijwb9imIPlucl4krpr2EeCeAUvifiQ9Uf5X+M=
|
|
||||||
github.com/timandy/routine v1.1.5/go.mod h1:kXslgIosdY8LW0byTyPnenDgn4/azt2euufAq9rK51w=
|
|
||||||
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=
|
github.com/vishvananda/netlink v1.3.0 h1:X7l42GfcV4S6E4vHTsw48qbrV+9PVojNfIhZcwQdrZk=
|
||||||
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
|
github.com/vishvananda/netlink v1.3.0/go.mod h1:i6NetklAujEcC6fK0JPjT8qSwWyO0HLn4UKG+hGqeJs=
|
||||||
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
github.com/vishvananda/netns v0.0.4 h1:Oeaw1EM2JMxD51g9uhtC0D7erkIjgmj8+JZc26m1YX8=
|
||||||
@@ -162,8 +156,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
|
||||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||||
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 h1:Di6/M8l0O2lCLc6VVRWhgCiApHV8MnQurBnFSHsQtNY=
|
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 h1:Di6/M8l0O2lCLc6VVRWhgCiApHV8MnQurBnFSHsQtNY=
|
||||||
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
|
||||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||||
@@ -191,8 +185,8 @@ golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJ
|
|||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.12.0 h1:MHc5BpPuC30uJk597Ri8TV3CNZcTLu6B6z4lJy+g6Jw=
|
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||||
golang.org/x/sync v0.12.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/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-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
@@ -210,11 +204,11 @@ golang.org/x/sys v0.0.0-20210603081109-ebe580a85c40/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.30.0 h1:PQ39fJZ+mfadBm0y5WlL4vlM7Sx1Hgf13sMIY2+QS9Y=
|
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
|
||||||
golang.org/x/term v0.30.0/go.mod h1:NYYFdzHoI5wRh/h5tDMdMqCqPJZEuNqVR5xJLd/n67g=
|
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
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/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ func ixHandshakeStage0(f *Interface, hh *HandshakeHostInfo) bool {
|
|||||||
|
|
||||||
// If we're connecting to a v6 address we must use a v2 cert
|
// If we're connecting to a v6 address we must use a v2 cert
|
||||||
cs := f.pki.getCertState()
|
cs := f.pki.getCertState()
|
||||||
v := cs.defaultVersion
|
v := cs.initiatingVersion
|
||||||
for _, a := range hh.hostinfo.vpnAddrs {
|
for _, a := range hh.hostinfo.vpnAddrs {
|
||||||
if a.Is6() {
|
if a.Is6() {
|
||||||
v = cert.Version2
|
v = cert.Version2
|
||||||
@@ -101,7 +101,7 @@ func ixHandshakeStage1(f *Interface, addr netip.AddrPort, via *ViaSender, packet
|
|||||||
if crt == nil {
|
if crt == nil {
|
||||||
f.l.WithField("udpAddr", addr).
|
f.l.WithField("udpAddr", addr).
|
||||||
WithField("handshake", m{"stage": 0, "style": "ix_psk0"}).
|
WithField("handshake", m{"stage": 0, "style": "ix_psk0"}).
|
||||||
WithField("certVersion", cs.defaultVersion).
|
WithField("certVersion", cs.initiatingVersion).
|
||||||
Error("Unable to handshake with host because no certificate is available")
|
Error("Unable to handshake with host because no certificate is available")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -243,7 +243,6 @@ func ixHandshakeStage1(f *Interface, addr netip.AddrPort, via *ViaSender, packet
|
|||||||
}
|
}
|
||||||
|
|
||||||
hostinfo := &HostInfo{
|
hostinfo := &HostInfo{
|
||||||
syncRWMutex: newSyncRWMutex("hostinfo"),
|
|
||||||
ConnectionState: ci,
|
ConnectionState: ci,
|
||||||
localIndexId: myIndex,
|
localIndexId: myIndex,
|
||||||
remoteIndexId: hs.Details.InitiatorIndex,
|
remoteIndexId: hs.Details.InitiatorIndex,
|
||||||
@@ -251,7 +250,6 @@ func ixHandshakeStage1(f *Interface, addr netip.AddrPort, via *ViaSender, packet
|
|||||||
HandshakePacket: make(map[uint8][]byte, 0),
|
HandshakePacket: make(map[uint8][]byte, 0),
|
||||||
lastHandshakeTime: hs.Details.Time,
|
lastHandshakeTime: hs.Details.Time,
|
||||||
relayState: RelayState{
|
relayState: RelayState{
|
||||||
syncRWMutex: newSyncRWMutex("relay-state"),
|
|
||||||
relays: map[netip.Addr]struct{}{},
|
relays: map[netip.Addr]struct{}{},
|
||||||
relayForByAddr: map[netip.Addr]*Relay{},
|
relayForByAddr: map[netip.Addr]*Relay{},
|
||||||
relayForByIdx: map[uint32]*Relay{},
|
relayForByIdx: map[uint32]*Relay{},
|
||||||
@@ -345,7 +343,7 @@ func ixHandshakeStage1(f *Interface, addr netip.AddrPort, via *ViaSender, packet
|
|||||||
if existing.SetRemoteIfPreferred(f.hostMap, addr) {
|
if existing.SetRemoteIfPreferred(f.hostMap, addr) {
|
||||||
// Send a test packet to ensure the other side has also switched to
|
// Send a test packet to ensure the other side has also switched to
|
||||||
// the preferred remote
|
// the preferred remote
|
||||||
f.SendMessageToVpnAddr(header.Test, header.TestRequest, vpnAddrs[0], []byte(""), make([]byte, 12, 12), make([]byte, mtu))
|
f.SendMessageToVpnAddr(header.Test, header.TestRequest, vpnAddrs[0], []byte(""), make([]byte, 12), make([]byte, mtu))
|
||||||
}
|
}
|
||||||
|
|
||||||
msg = existing.HandshakePacket[2]
|
msg = existing.HandshakePacket[2]
|
||||||
@@ -388,7 +386,7 @@ func ixHandshakeStage1(f *Interface, addr netip.AddrPort, via *ViaSender, packet
|
|||||||
Info("Handshake too old")
|
Info("Handshake too old")
|
||||||
|
|
||||||
// Send a test packet to trigger an authenticated tunnel test, this should suss out any lingering tunnel issues
|
// Send a test packet to trigger an authenticated tunnel test, this should suss out any lingering tunnel issues
|
||||||
f.SendMessageToVpnAddr(header.Test, header.TestRequest, vpnAddrs[0], []byte(""), make([]byte, 12, 12), make([]byte, mtu))
|
f.SendMessageToVpnAddr(header.Test, header.TestRequest, vpnAddrs[0], []byte(""), make([]byte, 12), make([]byte, mtu))
|
||||||
return
|
return
|
||||||
case ErrLocalIndexCollision:
|
case ErrLocalIndexCollision:
|
||||||
// This means we failed to insert because of collision on localIndexId. Just let the next handshake packet retry
|
// This means we failed to insert because of collision on localIndexId. Just let the next handshake packet retry
|
||||||
@@ -463,8 +461,6 @@ func ixHandshakeStage1(f *Interface, addr netip.AddrPort, via *ViaSender, packet
|
|||||||
f.connectionManager.AddTrafficWatch(hostinfo.localIndexId)
|
f.connectionManager.AddTrafficWatch(hostinfo.localIndexId)
|
||||||
|
|
||||||
hostinfo.remotes.ResetBlockedRemotes()
|
hostinfo.remotes.ResetBlockedRemotes()
|
||||||
|
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ixHandshakeStage2(f *Interface, addr netip.AddrPort, via *ViaSender, hh *HandshakeHostInfo, packet []byte, h *header.H) bool {
|
func ixHandshakeStage2(f *Interface, addr netip.AddrPort, via *ViaSender, hh *HandshakeHostInfo, packet []byte, h *header.H) bool {
|
||||||
@@ -662,7 +658,7 @@ func ixHandshakeStage2(f *Interface, addr netip.AddrPort, via *ViaSender, hh *Ha
|
|||||||
}
|
}
|
||||||
|
|
||||||
if len(hh.packetStore) > 0 {
|
if len(hh.packetStore) > 0 {
|
||||||
nb := make([]byte, 12, 12)
|
nb := make([]byte, 12)
|
||||||
out := make([]byte, mtu)
|
out := make([]byte, mtu)
|
||||||
for _, cp := range hh.packetStore {
|
for _, cp := range hh.packetStore {
|
||||||
cp.callback(cp.messageType, cp.messageSubType, hostinfo, cp.packet, nb, out)
|
cp.callback(cp.messageType, cp.messageSubType, hostinfo, cp.packet, nb, out)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"slices"
|
"slices"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/rcrowley/go-metrics"
|
"github.com/rcrowley/go-metrics"
|
||||||
@@ -44,7 +45,7 @@ type HandshakeConfig struct {
|
|||||||
|
|
||||||
type HandshakeManager struct {
|
type HandshakeManager struct {
|
||||||
// Mutex for interacting with the vpnIps and indexes maps
|
// Mutex for interacting with the vpnIps and indexes maps
|
||||||
syncRWMutex
|
sync.RWMutex
|
||||||
|
|
||||||
vpnIps map[netip.Addr]*HandshakeHostInfo
|
vpnIps map[netip.Addr]*HandshakeHostInfo
|
||||||
indexes map[uint32]*HandshakeHostInfo
|
indexes map[uint32]*HandshakeHostInfo
|
||||||
@@ -65,7 +66,7 @@ type HandshakeManager struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type HandshakeHostInfo struct {
|
type HandshakeHostInfo struct {
|
||||||
syncMutex
|
sync.Mutex
|
||||||
|
|
||||||
startTime time.Time // Time that we first started trying with this handshake
|
startTime time.Time // Time that we first started trying with this handshake
|
||||||
ready bool // Is the handshake ready
|
ready bool // Is the handshake ready
|
||||||
@@ -103,7 +104,6 @@ func (hh *HandshakeHostInfo) cachePacket(l *logrus.Logger, t header.MessageType,
|
|||||||
|
|
||||||
func NewHandshakeManager(l *logrus.Logger, mainHostMap *HostMap, lightHouse *LightHouse, outside udp.Conn, config HandshakeConfig) *HandshakeManager {
|
func NewHandshakeManager(l *logrus.Logger, mainHostMap *HostMap, lightHouse *LightHouse, outside udp.Conn, config HandshakeConfig) *HandshakeManager {
|
||||||
return &HandshakeManager{
|
return &HandshakeManager{
|
||||||
syncRWMutex: newSyncRWMutex("handshake-manager"),
|
|
||||||
vpnIps: map[netip.Addr]*HandshakeHostInfo{},
|
vpnIps: map[netip.Addr]*HandshakeHostInfo{},
|
||||||
indexes: map[uint32]*HandshakeHostInfo{},
|
indexes: map[uint32]*HandshakeHostInfo{},
|
||||||
mainHostMap: mainHostMap,
|
mainHostMap: mainHostMap,
|
||||||
@@ -111,7 +111,7 @@ func NewHandshakeManager(l *logrus.Logger, mainHostMap *HostMap, lightHouse *Lig
|
|||||||
outside: outside,
|
outside: outside,
|
||||||
config: config,
|
config: config,
|
||||||
trigger: make(chan netip.Addr, config.triggerBuffer),
|
trigger: make(chan netip.Addr, config.triggerBuffer),
|
||||||
OutboundHandshakeTimer: NewLockingTimerWheel[netip.Addr]("handshake-manager-timer", config.tryInterval, hsTimeout(config.retries, config.tryInterval)),
|
OutboundHandshakeTimer: NewLockingTimerWheel[netip.Addr](config.tryInterval, hsTimeout(config.retries, config.tryInterval)),
|
||||||
messageMetrics: config.messageMetrics,
|
messageMetrics: config.messageMetrics,
|
||||||
metricInitiated: metrics.GetOrRegisterCounter("handshake_manager.initiated", nil),
|
metricInitiated: metrics.GetOrRegisterCounter("handshake_manager.initiated", nil),
|
||||||
metricTimedOut: metrics.GetOrRegisterCounter("handshake_manager.timed_out", nil),
|
metricTimedOut: metrics.GetOrRegisterCounter("handshake_manager.timed_out", nil),
|
||||||
@@ -448,11 +448,9 @@ func (hm *HandshakeManager) StartHandshake(vpnAddr netip.Addr, cacheCb func(*Han
|
|||||||
}
|
}
|
||||||
|
|
||||||
hostinfo := &HostInfo{
|
hostinfo := &HostInfo{
|
||||||
syncRWMutex: newSyncRWMutex("hostinfo"),
|
|
||||||
vpnAddrs: []netip.Addr{vpnAddr},
|
vpnAddrs: []netip.Addr{vpnAddr},
|
||||||
HandshakePacket: make(map[uint8][]byte, 0),
|
HandshakePacket: make(map[uint8][]byte, 0),
|
||||||
relayState: RelayState{
|
relayState: RelayState{
|
||||||
syncRWMutex: newSyncRWMutex("relay-state"),
|
|
||||||
relays: map[netip.Addr]struct{}{},
|
relays: map[netip.Addr]struct{}{},
|
||||||
relayForByAddr: map[netip.Addr]*Relay{},
|
relayForByAddr: map[netip.Addr]*Relay{},
|
||||||
relayForByIdx: map[uint32]*Relay{},
|
relayForByIdx: map[uint32]*Relay{},
|
||||||
@@ -460,7 +458,6 @@ func (hm *HandshakeManager) StartHandshake(vpnAddr netip.Addr, cacheCb func(*Han
|
|||||||
}
|
}
|
||||||
|
|
||||||
hh := &HandshakeHostInfo{
|
hh := &HandshakeHostInfo{
|
||||||
syncMutex: newSyncMutex("handshake-hostinfo"),
|
|
||||||
hostinfo: hostinfo,
|
hostinfo: hostinfo,
|
||||||
startTime: time.Now(),
|
startTime: time.Now(),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -24,7 +24,7 @@ func Test_NewHandshakeManagerVpnIp(t *testing.T) {
|
|||||||
lh := newTestLighthouse()
|
lh := newTestLighthouse()
|
||||||
|
|
||||||
cs := &CertState{
|
cs := &CertState{
|
||||||
defaultVersion: cert.Version1,
|
initiatingVersion: cert.Version1,
|
||||||
privateKey: []byte{},
|
privateKey: []byte{},
|
||||||
v1Cert: &dummyCert{version: cert.Version1},
|
v1Cert: &dummyCert{version: cert.Version1},
|
||||||
v1HandshakeBytes: []byte{},
|
v1HandshakeBytes: []byte{},
|
||||||
@@ -65,30 +65,16 @@ func Test_NewHandshakeManagerVpnIp(t *testing.T) {
|
|||||||
assert.NotContains(t, blah.vpnIps, ip)
|
assert.NotContains(t, blah.vpnIps, ip)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testCountTimerWheelEntries(tw *LockingTimerWheel[netip.Addr]) (c int) {
|
|
||||||
for _, i := range tw.t.wheel {
|
|
||||||
n := i.Head
|
|
||||||
for n != nil {
|
|
||||||
c++
|
|
||||||
n = n.Next
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return c
|
|
||||||
}
|
|
||||||
|
|
||||||
type mockEncWriter struct {
|
type mockEncWriter struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mw *mockEncWriter) SendMessageToVpnAddr(_ header.MessageType, _ header.MessageSubType, _ netip.Addr, _, _, _ []byte) {
|
func (mw *mockEncWriter) SendMessageToVpnAddr(_ header.MessageType, _ header.MessageSubType, _ netip.Addr, _, _, _ []byte) {
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mw *mockEncWriter) SendVia(_ *HostInfo, _ *Relay, _, _, _ []byte, _ bool) {
|
func (mw *mockEncWriter) SendVia(_ *HostInfo, _ *Relay, _, _, _ []byte, _ bool) {
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mw *mockEncWriter) SendMessageToHostInfo(_ header.MessageType, _ header.MessageSubType, _ *HostInfo, _, _, _ []byte) {
|
func (mw *mockEncWriter) SendMessageToHostInfo(_ header.MessageType, _ header.MessageSubType, _ *HostInfo, _, _, _ []byte) {
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (mw *mockEncWriter) Handshake(_ netip.Addr) {}
|
func (mw *mockEncWriter) Handshake(_ netip.Addr) {}
|
||||||
@@ -98,5 +84,5 @@ func (mw *mockEncWriter) GetHostInfo(_ netip.Addr) *HostInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (mw *mockEncWriter) GetCertState() *CertState {
|
func (mw *mockEncWriter) GetCertState() *CertState {
|
||||||
return &CertState{defaultVersion: cert.Version2}
|
return &CertState{initiatingVersion: cert.Version2}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ type m = map[string]any
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
Version uint8 = 1
|
Version uint8 = 1
|
||||||
Len = 16
|
Len int = 16
|
||||||
)
|
)
|
||||||
|
|
||||||
type MessageType uint8
|
type MessageType uint8
|
||||||
|
|||||||
15
hostmap.go
15
hostmap.go
@@ -4,6 +4,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"net"
|
"net"
|
||||||
"net/netip"
|
"net/netip"
|
||||||
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -52,7 +53,7 @@ type Relay struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type HostMap struct {
|
type HostMap struct {
|
||||||
syncRWMutex //Because we concurrently read and write to our maps
|
sync.RWMutex //Because we concurrently read and write to our maps
|
||||||
Indexes map[uint32]*HostInfo
|
Indexes map[uint32]*HostInfo
|
||||||
Relays map[uint32]*HostInfo // Maps a Relay IDX to a Relay HostInfo object
|
Relays map[uint32]*HostInfo // Maps a Relay IDX to a Relay HostInfo object
|
||||||
RemoteIndexes map[uint32]*HostInfo
|
RemoteIndexes map[uint32]*HostInfo
|
||||||
@@ -65,7 +66,7 @@ type HostMap struct {
|
|||||||
// struct, make a copy of an existing value, edit the fileds in the copy, and
|
// struct, make a copy of an existing value, edit the fileds in the copy, and
|
||||||
// then store a pointer to the new copy in both realyForBy* maps.
|
// then store a pointer to the new copy in both realyForBy* maps.
|
||||||
type RelayState struct {
|
type RelayState struct {
|
||||||
syncRWMutex
|
sync.RWMutex
|
||||||
|
|
||||||
relays map[netip.Addr]struct{} // Set of vpnAddr's of Hosts to use as relays to access this peer
|
relays map[netip.Addr]struct{} // Set of vpnAddr's of Hosts to use as relays to access this peer
|
||||||
// For data race avoidance, the contents of a *Relay are treated immutably. To update a *Relay, copy the existing data,
|
// For data race avoidance, the contents of a *Relay are treated immutably. To update a *Relay, copy the existing data,
|
||||||
@@ -208,7 +209,6 @@ func (rs *RelayState) InsertRelay(ip netip.Addr, idx uint32, r *Relay) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type HostInfo struct {
|
type HostInfo struct {
|
||||||
syncRWMutex
|
|
||||||
remote netip.AddrPort
|
remote netip.AddrPort
|
||||||
remotes *RemoteList
|
remotes *RemoteList
|
||||||
promoteCounter atomic.Uint32
|
promoteCounter atomic.Uint32
|
||||||
@@ -288,7 +288,6 @@ func NewHostMapFromConfig(l *logrus.Logger, c *config.C) *HostMap {
|
|||||||
|
|
||||||
func newHostMap(l *logrus.Logger) *HostMap {
|
func newHostMap(l *logrus.Logger) *HostMap {
|
||||||
return &HostMap{
|
return &HostMap{
|
||||||
syncRWMutex: newSyncRWMutex("hostmap"),
|
|
||||||
Indexes: map[uint32]*HostInfo{},
|
Indexes: map[uint32]*HostInfo{},
|
||||||
Relays: map[uint32]*HostInfo{},
|
Relays: map[uint32]*HostInfo{},
|
||||||
RemoteIndexes: map[uint32]*HostInfo{},
|
RemoteIndexes: map[uint32]*HostInfo{},
|
||||||
@@ -569,7 +568,7 @@ func (hm *HostMap) unlockedAddHostInfo(hostinfo *HostInfo, f *Interface) {
|
|||||||
dnsR.Add(remoteCert.Certificate.Name()+".", hostinfo.vpnAddrs)
|
dnsR.Add(remoteCert.Certificate.Name()+".", hostinfo.vpnAddrs)
|
||||||
}
|
}
|
||||||
for _, addr := range hostinfo.vpnAddrs {
|
for _, addr := range hostinfo.vpnAddrs {
|
||||||
hm.unlockedInnerAddHostInfo(addr, hostinfo, f)
|
hm.unlockedInnerAddHostInfo(addr, hostinfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
hm.Indexes[hostinfo.localIndexId] = hostinfo
|
hm.Indexes[hostinfo.localIndexId] = hostinfo
|
||||||
@@ -582,7 +581,7 @@ func (hm *HostMap) unlockedAddHostInfo(hostinfo *HostInfo, f *Interface) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (hm *HostMap) unlockedInnerAddHostInfo(vpnAddr netip.Addr, hostinfo *HostInfo, f *Interface) {
|
func (hm *HostMap) unlockedInnerAddHostInfo(vpnAddr netip.Addr, hostinfo *HostInfo) {
|
||||||
existing := hm.Hosts[vpnAddr]
|
existing := hm.Hosts[vpnAddr]
|
||||||
hm.Hosts[vpnAddr] = hostinfo
|
hm.Hosts[vpnAddr] = hostinfo
|
||||||
|
|
||||||
@@ -649,7 +648,7 @@ func (i *HostInfo) TryPromoteBest(preferredRanges []netip.Prefix, ifce *Interfac
|
|||||||
|
|
||||||
// Try to send a test packet to that host, this should
|
// Try to send a test packet to that host, this should
|
||||||
// cause it to detect a roaming event and switch remotes
|
// cause it to detect a roaming event and switch remotes
|
||||||
ifce.sendTo(header.Test, header.TestRequest, i.ConnectionState, i, addr, []byte(""), make([]byte, 12, 12), make([]byte, mtu))
|
ifce.sendTo(header.Test, header.TestRequest, i.ConnectionState, i, addr, []byte(""), make([]byte, 12), make([]byte, mtu))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -795,7 +794,7 @@ func localAddrs(l *logrus.Logger, allowList *LocalAllowList) []netip.Addr {
|
|||||||
}
|
}
|
||||||
addr = addr.Unmap()
|
addr = addr.Unmap()
|
||||||
|
|
||||||
if addr.IsLoopback() == false && addr.IsLinkLocalUnicast() == false {
|
if !addr.IsLoopback() && !addr.IsLinkLocalUnicast() {
|
||||||
isAllowed := allowList.Allow(addr)
|
isAllowed := allowList.Allow(addr)
|
||||||
if l.Level >= logrus.TraceLevel {
|
if l.Level >= logrus.TraceLevel {
|
||||||
l.WithField("localAddr", addr).WithField("allowed", isAllowed).Trace("localAllowList.Allow")
|
l.WithField("localAddr", addr).WithField("allowed", isAllowed).Trace("localAllowList.Allow")
|
||||||
|
|||||||
12
interface.go
12
interface.go
@@ -266,7 +266,7 @@ func (f *Interface) listenOut(i int) {
|
|||||||
plaintext := make([]byte, udp.MTU)
|
plaintext := make([]byte, udp.MTU)
|
||||||
h := &header.H{}
|
h := &header.H{}
|
||||||
fwPacket := &firewall.Packet{}
|
fwPacket := &firewall.Packet{}
|
||||||
nb := make([]byte, 12, 12)
|
nb := make([]byte, 12)
|
||||||
|
|
||||||
li.ListenOut(func(fromUdpAddr netip.AddrPort, payload []byte) {
|
li.ListenOut(func(fromUdpAddr netip.AddrPort, payload []byte) {
|
||||||
f.readOutsidePackets(fromUdpAddr, nil, plaintext[:0], payload, h, fwPacket, lhh, nb, i, ctCache.Get(f.l))
|
f.readOutsidePackets(fromUdpAddr, nil, plaintext[:0], payload, h, fwPacket, lhh, nb, i, ctCache.Get(f.l))
|
||||||
@@ -279,7 +279,7 @@ func (f *Interface) listenIn(reader io.ReadWriteCloser, i int) {
|
|||||||
packet := make([]byte, mtu)
|
packet := make([]byte, mtu)
|
||||||
out := make([]byte, mtu)
|
out := make([]byte, mtu)
|
||||||
fwPacket := &firewall.Packet{}
|
fwPacket := &firewall.Packet{}
|
||||||
nb := make([]byte, 12, 12)
|
nb := make([]byte, 12)
|
||||||
|
|
||||||
conntrackCache := firewall.NewConntrackCacheTicker(f.conntrackCacheTimeout)
|
conntrackCache := firewall.NewConntrackCacheTicker(f.conntrackCacheTimeout)
|
||||||
|
|
||||||
@@ -322,7 +322,7 @@ func (f *Interface) reloadDisconnectInvalid(c *config.C) {
|
|||||||
|
|
||||||
func (f *Interface) reloadFirewall(c *config.C) {
|
func (f *Interface) reloadFirewall(c *config.C) {
|
||||||
//TODO: need to trigger/detect if the certificate changed too
|
//TODO: need to trigger/detect if the certificate changed too
|
||||||
if c.HasChanged("firewall") == false {
|
if !c.HasChanged("firewall") {
|
||||||
f.l.Debug("No firewall config change detected")
|
f.l.Debug("No firewall config change detected")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -410,7 +410,7 @@ func (f *Interface) emitStats(ctx context.Context, i time.Duration) {
|
|||||||
udpStats := udp.NewUDPStatsEmitter(f.writers)
|
udpStats := udp.NewUDPStatsEmitter(f.writers)
|
||||||
|
|
||||||
certExpirationGauge := metrics.GetOrRegisterGauge("certificate.ttl_seconds", nil)
|
certExpirationGauge := metrics.GetOrRegisterGauge("certificate.ttl_seconds", nil)
|
||||||
certDefaultVersion := metrics.GetOrRegisterGauge("certificate.default_version", nil)
|
certInitiatingVersion := metrics.GetOrRegisterGauge("certificate.initiating_version", nil)
|
||||||
certMaxVersion := metrics.GetOrRegisterGauge("certificate.max_version", nil)
|
certMaxVersion := metrics.GetOrRegisterGauge("certificate.max_version", nil)
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@@ -424,8 +424,8 @@ func (f *Interface) emitStats(ctx context.Context, i time.Duration) {
|
|||||||
|
|
||||||
certState := f.pki.getCertState()
|
certState := f.pki.getCertState()
|
||||||
defaultCrt := certState.GetDefaultCertificate()
|
defaultCrt := certState.GetDefaultCertificate()
|
||||||
certExpirationGauge.Update(int64(defaultCrt.NotAfter().Sub(time.Now()) / time.Second))
|
certExpirationGauge.Update(int64(time.Until(defaultCrt.NotAfter()) / time.Second))
|
||||||
certDefaultVersion.Update(int64(defaultCrt.Version()))
|
certInitiatingVersion.Update(int64(defaultCrt.Version()))
|
||||||
|
|
||||||
// Report the max certificate version we are capable of using
|
// Report the max certificate version we are capable of using
|
||||||
if certState.v2Cert != nil {
|
if certState.v2Cert != nil {
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"net/netip"
|
"net/netip"
|
||||||
"slices"
|
"slices"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ var ErrHostNotKnown = errors.New("host not known")
|
|||||||
|
|
||||||
type LightHouse struct {
|
type LightHouse struct {
|
||||||
//TODO: We need a timer wheel to kick out vpnAddrs that haven't reported in a long time
|
//TODO: We need a timer wheel to kick out vpnAddrs that haven't reported in a long time
|
||||||
syncRWMutex //Because we concurrently read and write to our maps
|
sync.RWMutex //Because we concurrently read and write to our maps
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
amLighthouse bool
|
amLighthouse bool
|
||||||
|
|
||||||
@@ -95,7 +96,6 @@ func NewLightHouseFromConfig(ctx context.Context, l *logrus.Logger, c *config.C,
|
|||||||
}
|
}
|
||||||
|
|
||||||
h := LightHouse{
|
h := LightHouse{
|
||||||
syncRWMutex: newSyncRWMutex("lighthouse"),
|
|
||||||
ctx: ctx,
|
ctx: ctx,
|
||||||
amLighthouse: amLighthouse,
|
amLighthouse: amLighthouse,
|
||||||
myVpnNetworks: cs.myVpnNetworks,
|
myVpnNetworks: cs.myVpnNetworks,
|
||||||
@@ -371,7 +371,7 @@ func (lh *LightHouse) parseLighthouses(c *config.C, lhMap map[netip.Addr]struct{
|
|||||||
}
|
}
|
||||||
|
|
||||||
staticList := lh.GetStaticHostList()
|
staticList := lh.GetStaticHostList()
|
||||||
for lhAddr, _ := range lhMap {
|
for lhAddr := range lhMap {
|
||||||
if _, ok := staticList[lhAddr]; !ok {
|
if _, ok := staticList[lhAddr]; !ok {
|
||||||
return fmt.Errorf("lighthouse %s does not have a static_host_map entry", lhAddr)
|
return fmt.Errorf("lighthouse %s does not have a static_host_map entry", lhAddr)
|
||||||
}
|
}
|
||||||
@@ -475,7 +475,6 @@ func (lh *LightHouse) QueryServer(vpnAddr netip.Addr) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
chanDebugSend("lighthouse-query-chan")
|
|
||||||
lh.queryChan <- vpnAddr
|
lh.queryChan <- vpnAddr
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -655,11 +654,8 @@ func (lh *LightHouse) shouldAdd(vpnAddr netip.Addr, to netip.Addr) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, found := lh.myVpnNetworksTable.Lookup(to)
|
_, found := lh.myVpnNetworksTable.Lookup(to)
|
||||||
if found {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
return !found
|
||||||
}
|
}
|
||||||
|
|
||||||
// unlockedShouldAddV4 checks if to is allowed by our allow list
|
// unlockedShouldAddV4 checks if to is allowed by our allow list
|
||||||
@@ -676,11 +672,7 @@ func (lh *LightHouse) unlockedShouldAddV4(vpnAddr netip.Addr, to *V4AddrPort) bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, found := lh.myVpnNetworksTable.Lookup(udpAddr.Addr())
|
_, found := lh.myVpnNetworksTable.Lookup(udpAddr.Addr())
|
||||||
if found {
|
return !found
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// unlockedShouldAddV6 checks if to is allowed by our allow list
|
// unlockedShouldAddV6 checks if to is allowed by our allow list
|
||||||
@@ -697,11 +689,8 @@ func (lh *LightHouse) unlockedShouldAddV6(vpnAddr netip.Addr, to *V6AddrPort) bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
_, found := lh.myVpnNetworksTable.Lookup(udpAddr.Addr())
|
_, found := lh.myVpnNetworksTable.Lookup(udpAddr.Addr())
|
||||||
if found {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
return !found
|
||||||
}
|
}
|
||||||
|
|
||||||
func (lh *LightHouse) IsLighthouseAddr(vpnAddr netip.Addr) bool {
|
func (lh *LightHouse) IsLighthouseAddr(vpnAddr netip.Addr) bool {
|
||||||
@@ -729,11 +718,9 @@ func (lh *LightHouse) startQueryWorker() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
nb := make([]byte, 12, 12)
|
nb := make([]byte, 12)
|
||||||
out := make([]byte, mtu)
|
out := make([]byte, mtu)
|
||||||
|
|
||||||
chanDebugRecv("lighthouse-query-chan")
|
|
||||||
|
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-lh.ctx.Done():
|
case <-lh.ctx.Done():
|
||||||
@@ -766,7 +753,7 @@ func (lh *LightHouse) innerQueryServer(addr netip.Addr, nb, out []byte) {
|
|||||||
if hi != nil {
|
if hi != nil {
|
||||||
v = hi.ConnectionState.myCert.Version()
|
v = hi.ConnectionState.myCert.Version()
|
||||||
} else {
|
} else {
|
||||||
v = lh.ifce.GetCertState().defaultVersion
|
v = lh.ifce.GetCertState().initiatingVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
if v == cert.Version1 {
|
if v == cert.Version1 {
|
||||||
@@ -872,7 +859,7 @@ func (lh *LightHouse) SendUpdate() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
nb := make([]byte, 12, 12)
|
nb := make([]byte, 12)
|
||||||
out := make([]byte, mtu)
|
out := make([]byte, mtu)
|
||||||
|
|
||||||
var v1Update, v2Update []byte
|
var v1Update, v2Update []byte
|
||||||
@@ -886,7 +873,7 @@ func (lh *LightHouse) SendUpdate() {
|
|||||||
if hi != nil {
|
if hi != nil {
|
||||||
v = hi.ConnectionState.myCert.Version()
|
v = hi.ConnectionState.myCert.Version()
|
||||||
} else {
|
} else {
|
||||||
v = lh.ifce.GetCertState().defaultVersion
|
v = lh.ifce.GetCertState().initiatingVersion
|
||||||
}
|
}
|
||||||
if v == cert.Version1 {
|
if v == cert.Version1 {
|
||||||
if v1Update == nil {
|
if v1Update == nil {
|
||||||
@@ -974,7 +961,7 @@ type LightHouseHandler struct {
|
|||||||
func (lh *LightHouse) NewRequestHandler() *LightHouseHandler {
|
func (lh *LightHouse) NewRequestHandler() *LightHouseHandler {
|
||||||
lhh := &LightHouseHandler{
|
lhh := &LightHouseHandler{
|
||||||
lh: lh,
|
lh: lh,
|
||||||
nb: make([]byte, 12, 12),
|
nb: make([]byte, 12),
|
||||||
out: make([]byte, mtu),
|
out: make([]byte, mtu),
|
||||||
l: lh.l,
|
l: lh.l,
|
||||||
pb: make([]byte, mtu),
|
pb: make([]byte, mtu),
|
||||||
@@ -1117,7 +1104,7 @@ func (lhh *LightHouseHandler) sendHostPunchNotification(n *NebulaMeta, fromVpnAd
|
|||||||
targetHI := lhh.lh.ifce.GetHostInfo(punchNotifDest)
|
targetHI := lhh.lh.ifce.GetHostInfo(punchNotifDest)
|
||||||
var useVersion cert.Version
|
var useVersion cert.Version
|
||||||
if targetHI == nil {
|
if targetHI == nil {
|
||||||
useVersion = lhh.lh.ifce.GetCertState().defaultVersion
|
useVersion = lhh.lh.ifce.GetCertState().initiatingVersion
|
||||||
} else {
|
} else {
|
||||||
crt := targetHI.GetCert().Certificate
|
crt := targetHI.GetCert().Certificate
|
||||||
useVersion = crt.Version()
|
useVersion = crt.Version()
|
||||||
@@ -1165,7 +1152,7 @@ func (lhh *LightHouseHandler) coalesceAnswers(v cert.Version, c *cache, n *Nebul
|
|||||||
if c.v4.learned != nil {
|
if c.v4.learned != nil {
|
||||||
n.Details.V4AddrPorts = append(n.Details.V4AddrPorts, c.v4.learned)
|
n.Details.V4AddrPorts = append(n.Details.V4AddrPorts, c.v4.learned)
|
||||||
}
|
}
|
||||||
if c.v4.reported != nil && len(c.v4.reported) > 0 {
|
if len(c.v4.reported) > 0 {
|
||||||
n.Details.V4AddrPorts = append(n.Details.V4AddrPorts, c.v4.reported...)
|
n.Details.V4AddrPorts = append(n.Details.V4AddrPorts, c.v4.reported...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1174,7 +1161,7 @@ func (lhh *LightHouseHandler) coalesceAnswers(v cert.Version, c *cache, n *Nebul
|
|||||||
if c.v6.learned != nil {
|
if c.v6.learned != nil {
|
||||||
n.Details.V6AddrPorts = append(n.Details.V6AddrPorts, c.v6.learned)
|
n.Details.V6AddrPorts = append(n.Details.V6AddrPorts, c.v6.learned)
|
||||||
}
|
}
|
||||||
if c.v6.reported != nil && len(c.v6.reported) > 0 {
|
if len(c.v6.reported) > 0 {
|
||||||
n.Details.V6AddrPorts = append(n.Details.V6AddrPorts, c.v6.reported...)
|
n.Details.V6AddrPorts = append(n.Details.V6AddrPorts, c.v6.reported...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1372,7 +1359,7 @@ func (lhh *LightHouseHandler) handleHostPunchNotification(n *NebulaMeta, fromVpn
|
|||||||
//NOTE: we have to allocate a new output buffer here since we are spawning a new goroutine
|
//NOTE: we have to allocate a new output buffer here since we are spawning a new goroutine
|
||||||
// for each punchBack packet. We should move this into a timerwheel or a single goroutine
|
// for each punchBack packet. We should move this into a timerwheel or a single goroutine
|
||||||
// managed by a channel.
|
// managed by a channel.
|
||||||
w.SendMessageToVpnAddr(header.Test, header.TestRequest, queryVpnAddr, []byte(""), make([]byte, 12, 12), make([]byte, mtu))
|
w.SendMessageToVpnAddr(header.Test, header.TestRequest, queryVpnAddr, []byte(""), make([]byte, 12), make([]byte, mtu))
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -417,7 +417,7 @@ func (tw *testEncWriter) GetHostInfo(vpnIp netip.Addr) *HostInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (tw *testEncWriter) GetCertState() *CertState {
|
func (tw *testEncWriter) GetCertState() *CertState {
|
||||||
return &CertState{defaultVersion: tw.protocolVersion}
|
return &CertState{initiatingVersion: tw.protocolVersion}
|
||||||
}
|
}
|
||||||
|
|
||||||
// assertIp4InArray asserts every address in want is at the same position in have and that the lengths match
|
// assertIp4InArray asserts every address in want is at the same position in have and that the lengths match
|
||||||
@@ -484,12 +484,12 @@ func Test_findNetworkUnion(t *testing.T) {
|
|||||||
assert.Equal(t, out, afe81)
|
assert.Equal(t, out, afe81)
|
||||||
|
|
||||||
//falsey cases
|
//falsey cases
|
||||||
out, ok = findNetworkUnion([]netip.Prefix{oneSevenTwo, fe80}, []netip.Addr{a1})
|
_, ok = findNetworkUnion([]netip.Prefix{oneSevenTwo, fe80}, []netip.Addr{a1})
|
||||||
assert.False(t, ok)
|
assert.False(t, ok)
|
||||||
out, ok = findNetworkUnion([]netip.Prefix{fc00, fe80}, []netip.Addr{a1})
|
_, ok = findNetworkUnion([]netip.Prefix{fc00, fe80}, []netip.Addr{a1})
|
||||||
assert.False(t, ok)
|
assert.False(t, ok)
|
||||||
out, ok = findNetworkUnion([]netip.Prefix{oneSevenTwo, fc00}, []netip.Addr{a1, afe81})
|
_, ok = findNetworkUnion([]netip.Prefix{oneSevenTwo, fc00}, []netip.Addr{a1, afe81})
|
||||||
assert.False(t, ok)
|
assert.False(t, ok)
|
||||||
out, ok = findNetworkUnion([]netip.Prefix{fc00}, []netip.Addr{a1, afe81})
|
_, ok = findNetworkUnion([]netip.Prefix{fc00}, []netip.Addr{a1, afe81})
|
||||||
assert.False(t, ok)
|
assert.False(t, ok)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ type MessageMetrics struct {
|
|||||||
|
|
||||||
func (m *MessageMetrics) Rx(t header.MessageType, s header.MessageSubType, i int64) {
|
func (m *MessageMetrics) Rx(t header.MessageType, s header.MessageSubType, i int64) {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
if t >= 0 && int(t) < len(m.rx) && s >= 0 && int(s) < len(m.rx[t]) {
|
if int(t) < len(m.rx) && int(s) < len(m.rx[t]) {
|
||||||
m.rx[t][s].Inc(i)
|
m.rx[t][s].Inc(i)
|
||||||
} else if m.rxUnknown != nil {
|
} else if m.rxUnknown != nil {
|
||||||
m.rxUnknown.Inc(i)
|
m.rxUnknown.Inc(i)
|
||||||
@@ -26,7 +26,7 @@ func (m *MessageMetrics) Rx(t header.MessageType, s header.MessageSubType, i int
|
|||||||
}
|
}
|
||||||
func (m *MessageMetrics) Tx(t header.MessageType, s header.MessageSubType, i int64) {
|
func (m *MessageMetrics) Tx(t header.MessageType, s header.MessageSubType, i int64) {
|
||||||
if m != nil {
|
if m != nil {
|
||||||
if t >= 0 && int(t) < len(m.tx) && s >= 0 && int(s) < len(m.tx[t]) {
|
if int(t) < len(m.tx) && int(s) < len(m.tx[t]) {
|
||||||
m.tx[t][s].Inc(i)
|
m.tx[t][s].Inc(i)
|
||||||
} else if m.txUnknown != nil {
|
} else if m.txUnknown != nil {
|
||||||
m.txUnknown.Inc(i)
|
m.txUnknown.Inc(i)
|
||||||
|
|||||||
195
mutex_debug.go
195
mutex_debug.go
@@ -1,195 +0,0 @@
|
|||||||
//go:build mutex_debug
|
|
||||||
// +build mutex_debug
|
|
||||||
|
|
||||||
package nebula
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"runtime"
|
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/clarkmcc/go-dag"
|
|
||||||
"github.com/timandy/routine"
|
|
||||||
)
|
|
||||||
|
|
||||||
type mutexKey = string
|
|
||||||
|
|
||||||
// For each Key in this map, the Value is a list of lock types you can already have
|
|
||||||
// when you want to grab that Key. This ensures that locks are always fetched
|
|
||||||
// in the same order, to prevent deadlocks.
|
|
||||||
var allowedConcurrentLocks = map[mutexKey][]mutexKey{
|
|
||||||
"connection-manager-in": {"hostmap"},
|
|
||||||
"connection-manager-out": {"connection-manager-in", "handshake-hostinfo", "handshake-manager"},
|
|
||||||
"connection-manager-relay-used": {"handshake-hostinfo"},
|
|
||||||
"connection-manager-timer": {"connection-manager-out"},
|
|
||||||
// "connection-state-write": {"hostmap"},
|
|
||||||
"firewall-conntrack": {"handshake-hostinfo"},
|
|
||||||
"handshake-manager": {"handshake-hostinfo", "hostmap"},
|
|
||||||
"handshake-manager-timer": {"handshake-manager"},
|
|
||||||
"hostmap": {"lighthouse-query-chan", "handshake-hostinfo"},
|
|
||||||
"lighthouse": {"handshake-hostinfo"},
|
|
||||||
"relay-state": {"connection-manager-relay-used", "hostmap"},
|
|
||||||
"remote-list": {"lighthouse", "handshake-manager"},
|
|
||||||
"lighthouse-query-chan": {"handshake-hostinfo"},
|
|
||||||
}
|
|
||||||
|
|
||||||
type mutexValue struct {
|
|
||||||
file string
|
|
||||||
line int
|
|
||||||
}
|
|
||||||
|
|
||||||
func (m mutexValue) String() string {
|
|
||||||
return fmt.Sprintf("%s:%d", m.file, m.line)
|
|
||||||
}
|
|
||||||
|
|
||||||
var threadLocal = routine.NewThreadLocalWithInitial[map[mutexKey]mutexValue](func() map[mutexKey]mutexValue { return map[mutexKey]mutexValue{} })
|
|
||||||
|
|
||||||
var allowedDAG dag.AcyclicGraph
|
|
||||||
|
|
||||||
// We build a directed acyclic graph to assert that the locks can only be
|
|
||||||
// acquired in a determined order, If there are cycles in the DAG, then we
|
|
||||||
// know that the locking order is not guaranteed.
|
|
||||||
func init() {
|
|
||||||
for k, v := range allowedConcurrentLocks {
|
|
||||||
allowedDAG.Add(k)
|
|
||||||
for _, t := range v {
|
|
||||||
allowedDAG.Add(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for k, v := range allowedConcurrentLocks {
|
|
||||||
for _, t := range v {
|
|
||||||
allowedDAG.Connect(dag.BasicEdge(k, t))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if cycles := allowedDAG.Cycles(); len(cycles) > 0 {
|
|
||||||
panic(fmt.Errorf("Cycles found in allowedConcurrentLocks: %v", cycles))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rebuild allowedConcurrentLocks as a flattened list of all possibilities
|
|
||||||
for k := range allowedConcurrentLocks {
|
|
||||||
ancestors, err := allowedDAG.Ancestors(k)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
var allowed []mutexKey
|
|
||||||
for t := range ancestors {
|
|
||||||
allowed = append(allowed, t.(mutexKey))
|
|
||||||
}
|
|
||||||
allowedConcurrentLocks[k] = allowed
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
type syncRWMutex struct {
|
|
||||||
sync.RWMutex
|
|
||||||
mutexKey
|
|
||||||
}
|
|
||||||
|
|
||||||
type syncMutex struct {
|
|
||||||
sync.Mutex
|
|
||||||
mutexKey
|
|
||||||
}
|
|
||||||
|
|
||||||
func newSyncRWMutex(key mutexKey) syncRWMutex {
|
|
||||||
return syncRWMutex{
|
|
||||||
mutexKey: key,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newSyncMutex(key mutexKey) syncMutex {
|
|
||||||
return syncMutex{
|
|
||||||
mutexKey: key,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func alertMutex(err error) {
|
|
||||||
panic(err)
|
|
||||||
// NOTE: you could switch to this log Line and remove the panic if you want
|
|
||||||
// to log all failures instead of panicking on the first one
|
|
||||||
//log.Print(err, string(debug.Stack()))
|
|
||||||
}
|
|
||||||
|
|
||||||
func checkMutex(state map[mutexKey]mutexValue, add mutexKey) {
|
|
||||||
if add == "" {
|
|
||||||
alertMutex(fmt.Errorf("mutex not initialized with mutexKey"))
|
|
||||||
}
|
|
||||||
|
|
||||||
allowedConcurrent := allowedConcurrentLocks[add]
|
|
||||||
|
|
||||||
for k, v := range state {
|
|
||||||
if add == k {
|
|
||||||
alertMutex(fmt.Errorf("re-entrant lock: %s. previous allocation: %s", add, v))
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO use slices.Contains, but requires go1.21
|
|
||||||
var found bool
|
|
||||||
for _, a := range allowedConcurrent {
|
|
||||||
if a == k {
|
|
||||||
found = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !found {
|
|
||||||
alertMutex(fmt.Errorf("grabbing %s lock and already have these locks: %s", add, state))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func chanDebugRecv(key mutexKey) {
|
|
||||||
m := threadLocal.Get()
|
|
||||||
checkMutex(m, key)
|
|
||||||
v := mutexValue{}
|
|
||||||
_, v.file, v.line, _ = runtime.Caller(1)
|
|
||||||
m[key] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
func chanDebugSend(key mutexKey) {
|
|
||||||
m := threadLocal.Get()
|
|
||||||
checkMutex(m, key)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncRWMutex) Lock() {
|
|
||||||
m := threadLocal.Get()
|
|
||||||
checkMutex(m, s.mutexKey)
|
|
||||||
v := mutexValue{}
|
|
||||||
_, v.file, v.line, _ = runtime.Caller(1)
|
|
||||||
m[s.mutexKey] = v
|
|
||||||
s.RWMutex.Lock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncRWMutex) Unlock() {
|
|
||||||
m := threadLocal.Get()
|
|
||||||
delete(m, s.mutexKey)
|
|
||||||
s.RWMutex.Unlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncRWMutex) RLock() {
|
|
||||||
m := threadLocal.Get()
|
|
||||||
checkMutex(m, s.mutexKey)
|
|
||||||
v := mutexValue{}
|
|
||||||
_, v.file, v.line, _ = runtime.Caller(1)
|
|
||||||
m[s.mutexKey] = v
|
|
||||||
s.RWMutex.RLock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncRWMutex) RUnlock() {
|
|
||||||
m := threadLocal.Get()
|
|
||||||
delete(m, s.mutexKey)
|
|
||||||
s.RWMutex.RUnlock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncMutex) Lock() {
|
|
||||||
m := threadLocal.Get()
|
|
||||||
checkMutex(m, s.mutexKey)
|
|
||||||
v := mutexValue{}
|
|
||||||
_, v.file, v.line, _ = runtime.Caller(1)
|
|
||||||
m[s.mutexKey] = v
|
|
||||||
s.Mutex.Lock()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *syncMutex) Unlock() {
|
|
||||||
m := threadLocal.Get()
|
|
||||||
delete(m, s.mutexKey)
|
|
||||||
s.Mutex.Unlock()
|
|
||||||
}
|
|
||||||
@@ -1,23 +0,0 @@
|
|||||||
//go:build !mutex_debug
|
|
||||||
// +build !mutex_debug
|
|
||||||
|
|
||||||
package nebula
|
|
||||||
|
|
||||||
import (
|
|
||||||
"sync"
|
|
||||||
)
|
|
||||||
|
|
||||||
type mutexKey = string
|
|
||||||
type syncRWMutex = sync.RWMutex
|
|
||||||
type syncMutex = sync.Mutex
|
|
||||||
|
|
||||||
func newSyncRWMutex(mutexKey) syncRWMutex {
|
|
||||||
return sync.RWMutex{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func newSyncMutex(mutexKey) syncMutex {
|
|
||||||
return sync.Mutex{}
|
|
||||||
}
|
|
||||||
|
|
||||||
func chanDebugRecv(key mutexKey) {}
|
|
||||||
func chanDebugSend(key mutexKey) {}
|
|
||||||
@@ -228,7 +228,7 @@ func (f *Interface) closeTunnel(hostInfo *HostInfo) {
|
|||||||
|
|
||||||
// sendCloseTunnel is a helper function to send a proper close tunnel packet to a remote
|
// sendCloseTunnel is a helper function to send a proper close tunnel packet to a remote
|
||||||
func (f *Interface) sendCloseTunnel(h *HostInfo) {
|
func (f *Interface) sendCloseTunnel(h *HostInfo) {
|
||||||
f.send(header.CloseTunnel, 0, h.ConnectionState, h, []byte{}, make([]byte, 12, 12), make([]byte, mtu))
|
f.send(header.CloseTunnel, 0, h.ConnectionState, h, []byte{}, make([]byte, 12), make([]byte, mtu))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *Interface) handleHostRoaming(hostinfo *HostInfo, udpAddr netip.AddrPort) {
|
func (f *Interface) handleHostRoaming(hostinfo *HostInfo, udpAddr netip.AddrPort) {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package overlay
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"math"
|
"math"
|
||||||
"net"
|
|
||||||
"net/netip"
|
"net/netip"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -305,29 +304,3 @@ func parseUnsafeRoutes(c *config.C, networks []netip.Prefix) ([]Route, error) {
|
|||||||
|
|
||||||
return routes, nil
|
return routes, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func ipWithin(o *net.IPNet, i *net.IPNet) bool {
|
|
||||||
// Make sure o contains the lowest form of i
|
|
||||||
if !o.Contains(i.IP.Mask(i.Mask)) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Find the max ip in i
|
|
||||||
ip4 := i.IP.To4()
|
|
||||||
if ip4 == nil {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
last := make(net.IP, len(ip4))
|
|
||||||
copy(last, ip4)
|
|
||||||
for x := range ip4 {
|
|
||||||
last[x] |= ^i.Mask[x]
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure o contains the max
|
|
||||||
if !o.Contains(last) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -225,6 +225,7 @@ func Test_parseUnsafeRoutes(t *testing.T) {
|
|||||||
// no mtu
|
// no mtu
|
||||||
c.Settings["tun"] = map[string]any{"unsafe_routes": []any{map[string]any{"via": "127.0.0.1", "route": "1.0.0.0/8"}}}
|
c.Settings["tun"] = map[string]any{"unsafe_routes": []any{map[string]any{"via": "127.0.0.1", "route": "1.0.0.0/8"}}}
|
||||||
routes, err = parseUnsafeRoutes(c, []netip.Prefix{n})
|
routes, err = parseUnsafeRoutes(c, []netip.Prefix{n})
|
||||||
|
require.NoError(t, err)
|
||||||
assert.Len(t, routes, 1)
|
assert.Len(t, routes, 1)
|
||||||
assert.Equal(t, 0, routes[0].MTU)
|
assert.Equal(t, 0, routes[0].MTU)
|
||||||
|
|
||||||
@@ -318,7 +319,7 @@ func Test_makeRouteTree(t *testing.T) {
|
|||||||
|
|
||||||
ip, err = netip.ParseAddr("1.1.0.1")
|
ip, err = netip.ParseAddr("1.1.0.1")
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
r, ok = routeTree.Lookup(ip)
|
_, ok = routeTree.Lookup(ip)
|
||||||
assert.False(t, ok)
|
assert.False(t, ok)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
package pkclient
|
package pkclient
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
|
||||||
"crypto/x509"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strconv"
|
"strconv"
|
||||||
@@ -50,27 +48,6 @@ func FromUrl(pkurl string) (*PKClient, error) {
|
|||||||
return New(module, uint(slotid), pin, id, label)
|
return New(module, uint(slotid), pin, id, label)
|
||||||
}
|
}
|
||||||
|
|
||||||
func ecKeyToArray(key *ecdsa.PublicKey) []byte {
|
|
||||||
x := make([]byte, 32)
|
|
||||||
y := make([]byte, 32)
|
|
||||||
key.X.FillBytes(x)
|
|
||||||
key.Y.FillBytes(y)
|
|
||||||
return append([]byte{0x04}, append(x, y...)...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func formatPubkeyFromPublicKeyInfoAttr(d []byte) ([]byte, error) {
|
|
||||||
e, err := x509.ParsePKIXPublicKey(d)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
switch t := e.(type) {
|
|
||||||
case *ecdsa.PublicKey:
|
|
||||||
return ecKeyToArray(e.(*ecdsa.PublicKey)), nil
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unknown public key type: %T", t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *PKClient) Test() error {
|
func (c *PKClient) Test() error {
|
||||||
pub, err := c.GetPubKey()
|
pub, err := c.GetPubKey()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -3,6 +3,8 @@
|
|||||||
package pkclient
|
package pkclient
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"crypto/ecdsa"
|
||||||
|
"crypto/x509"
|
||||||
"encoding/asn1"
|
"encoding/asn1"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
@@ -227,3 +229,24 @@ func (c *PKClient) GetPubKey() ([]byte, error) {
|
|||||||
return nil, fmt.Errorf("unknown public key length: %d", len(d))
|
return nil, fmt.Errorf("unknown public key length: %d", len(d))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ecKeyToArray(key *ecdsa.PublicKey) []byte {
|
||||||
|
x := make([]byte, 32)
|
||||||
|
y := make([]byte, 32)
|
||||||
|
key.X.FillBytes(x)
|
||||||
|
key.Y.FillBytes(y)
|
||||||
|
return append([]byte{0x04}, append(x, y...)...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func formatPubkeyFromPublicKeyInfoAttr(d []byte) ([]byte, error) {
|
||||||
|
e, err := x509.ParsePKIXPublicKey(d)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
switch t := e.(type) {
|
||||||
|
case *ecdsa.PublicKey:
|
||||||
|
return ecKeyToArray(e.(*ecdsa.PublicKey)), nil
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("unknown public key type: %T", t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -7,10 +7,10 @@ import "errors"
|
|||||||
type PKClient struct {
|
type PKClient struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var notImplemented = errors.New("not implemented")
|
var errNotImplemented = errors.New("not implemented")
|
||||||
|
|
||||||
func New(hsmPath string, slotId uint, pin string, id string, label string) (*PKClient, error) {
|
func New(hsmPath string, slotId uint, pin string, id string, label string) (*PKClient, error) {
|
||||||
return nil, notImplemented
|
return nil, errNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PKClient) Close() error {
|
func (c *PKClient) Close() error {
|
||||||
@@ -18,13 +18,13 @@ func (c *PKClient) Close() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *PKClient) SignASN1(data []byte) ([]byte, error) {
|
func (c *PKClient) SignASN1(data []byte) ([]byte, error) {
|
||||||
return nil, notImplemented
|
return nil, errNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PKClient) DeriveNoise(_ []byte) ([]byte, error) {
|
func (c *PKClient) DeriveNoise(_ []byte) ([]byte, error) {
|
||||||
return nil, notImplemented
|
return nil, errNotImplemented
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *PKClient) GetPubKey() ([]byte, error) {
|
func (c *PKClient) GetPubKey() ([]byte, error) {
|
||||||
return nil, notImplemented
|
return nil, errNotImplemented
|
||||||
}
|
}
|
||||||
|
|||||||
34
pki.go
34
pki.go
@@ -33,7 +33,7 @@ type CertState struct {
|
|||||||
v2Cert cert.Certificate
|
v2Cert cert.Certificate
|
||||||
v2HandshakeBytes []byte
|
v2HandshakeBytes []byte
|
||||||
|
|
||||||
defaultVersion cert.Version
|
initiatingVersion cert.Version
|
||||||
privateKey []byte
|
privateKey []byte
|
||||||
pkcs11Backed bool
|
pkcs11Backed bool
|
||||||
cipher string
|
cipher string
|
||||||
@@ -194,7 +194,7 @@ func (p *PKI) reloadCAPool(c *config.C) *util.ContextualError {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (cs *CertState) GetDefaultCertificate() cert.Certificate {
|
func (cs *CertState) GetDefaultCertificate() cert.Certificate {
|
||||||
c := cs.getCertificate(cs.defaultVersion)
|
c := cs.getCertificate(cs.initiatingVersion)
|
||||||
if c == nil {
|
if c == nil {
|
||||||
panic("No default certificate found")
|
panic("No default certificate found")
|
||||||
}
|
}
|
||||||
@@ -317,28 +317,28 @@ func newCertStateFromConfig(c *config.C) (*CertState, error) {
|
|||||||
return nil, errors.New("no certificates found in pki.cert")
|
return nil, errors.New("no certificates found in pki.cert")
|
||||||
}
|
}
|
||||||
|
|
||||||
useDefaultVersion := uint32(1)
|
useInitiatingVersion := uint32(1)
|
||||||
if v1 == nil {
|
if v1 == nil {
|
||||||
// The only condition that requires v2 as the default is if only a v2 certificate is present
|
// The only condition that requires v2 as the default is if only a v2 certificate is present
|
||||||
// We do this to avoid having to configure it specifically in the config file
|
// We do this to avoid having to configure it specifically in the config file
|
||||||
useDefaultVersion = 2
|
useInitiatingVersion = 2
|
||||||
}
|
}
|
||||||
|
|
||||||
rawDefaultVersion := c.GetUint32("pki.default_version", useDefaultVersion)
|
rawInitiatingVersion := c.GetUint32("pki.initiating_version", useInitiatingVersion)
|
||||||
var defaultVersion cert.Version
|
var initiatingVersion cert.Version
|
||||||
switch rawDefaultVersion {
|
switch rawInitiatingVersion {
|
||||||
case 1:
|
case 1:
|
||||||
if v1 == nil {
|
if v1 == nil {
|
||||||
return nil, fmt.Errorf("can not use pki.default_version 1 without a v1 certificate in pki.cert")
|
return nil, fmt.Errorf("can not use pki.initiating_version 1 without a v1 certificate in pki.cert")
|
||||||
}
|
}
|
||||||
defaultVersion = cert.Version1
|
initiatingVersion = cert.Version1
|
||||||
case 2:
|
case 2:
|
||||||
defaultVersion = cert.Version2
|
initiatingVersion = cert.Version2
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("unknown pki.default_version: %v", rawDefaultVersion)
|
return nil, fmt.Errorf("unknown pki.initiating_version: %v", rawInitiatingVersion)
|
||||||
}
|
}
|
||||||
|
|
||||||
return newCertState(defaultVersion, v1, v2, isPkcs11, curve, rawKey)
|
return newCertState(initiatingVersion, v1, v2, isPkcs11, curve, rawKey)
|
||||||
}
|
}
|
||||||
|
|
||||||
func newCertState(dv cert.Version, v1, v2 cert.Certificate, pkcs11backed bool, privateKeyCurve cert.Curve, privateKey []byte) (*CertState, error) {
|
func newCertState(dv cert.Version, v1, v2 cert.Certificate, pkcs11backed bool, privateKeyCurve cert.Curve, privateKey []byte) (*CertState, error) {
|
||||||
@@ -361,7 +361,7 @@ func newCertState(dv cert.Version, v1, v2 cert.Certificate, pkcs11backed bool, p
|
|||||||
|
|
||||||
//TODO: CERT-V2 make sure v2 has v1s address
|
//TODO: CERT-V2 make sure v2 has v1s address
|
||||||
|
|
||||||
cs.defaultVersion = dv
|
cs.initiatingVersion = dv
|
||||||
}
|
}
|
||||||
|
|
||||||
if v1 != nil {
|
if v1 != nil {
|
||||||
@@ -380,8 +380,8 @@ func newCertState(dv cert.Version, v1, v2 cert.Certificate, pkcs11backed bool, p
|
|||||||
cs.v1Cert = v1
|
cs.v1Cert = v1
|
||||||
cs.v1HandshakeBytes = v1hs
|
cs.v1HandshakeBytes = v1hs
|
||||||
|
|
||||||
if cs.defaultVersion == 0 {
|
if cs.initiatingVersion == 0 {
|
||||||
cs.defaultVersion = cert.Version1
|
cs.initiatingVersion = cert.Version1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -401,8 +401,8 @@ func newCertState(dv cert.Version, v1, v2 cert.Certificate, pkcs11backed bool, p
|
|||||||
cs.v2Cert = v2
|
cs.v2Cert = v2
|
||||||
cs.v2HandshakeBytes = v2hs
|
cs.v2HandshakeBytes = v2hs
|
||||||
|
|
||||||
if cs.defaultVersion == 0 {
|
if cs.initiatingVersion == 0 {
|
||||||
cs.defaultVersion = cert.Version2
|
cs.initiatingVersion = cert.Version2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import (
|
|||||||
"slices"
|
"slices"
|
||||||
"sort"
|
"sort"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"sync"
|
||||||
"sync/atomic"
|
"sync/atomic"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@@ -184,7 +185,7 @@ func (hr *hostnamesResults) GetAddrs() []netip.AddrPort {
|
|||||||
// It serves as a local cache of query replies, host update notifications, and locally learned addresses
|
// It serves as a local cache of query replies, host update notifications, and locally learned addresses
|
||||||
type RemoteList struct {
|
type RemoteList struct {
|
||||||
// Every interaction with internals requires a lock!
|
// Every interaction with internals requires a lock!
|
||||||
syncRWMutex
|
sync.RWMutex
|
||||||
|
|
||||||
// The full list of vpn addresses assigned to this host
|
// The full list of vpn addresses assigned to this host
|
||||||
vpnAddrs []netip.Addr
|
vpnAddrs []netip.Addr
|
||||||
@@ -214,7 +215,6 @@ type RemoteList struct {
|
|||||||
// NewRemoteList creates a new empty RemoteList
|
// NewRemoteList creates a new empty RemoteList
|
||||||
func NewRemoteList(vpnAddrs []netip.Addr, shouldAdd func(netip.Addr) bool) *RemoteList {
|
func NewRemoteList(vpnAddrs []netip.Addr, shouldAdd func(netip.Addr) bool) *RemoteList {
|
||||||
r := &RemoteList{
|
r := &RemoteList{
|
||||||
syncRWMutex: newSyncRWMutex("remote-list"),
|
|
||||||
vpnAddrs: make([]netip.Addr, len(vpnAddrs)),
|
vpnAddrs: make([]netip.Addr, len(vpnAddrs)),
|
||||||
addrs: make([]netip.AddrPort, 0),
|
addrs: make([]netip.AddrPort, 0),
|
||||||
relays: make([]netip.Addr, 0),
|
relays: make([]netip.Addr, 0),
|
||||||
@@ -263,9 +263,7 @@ func (r *RemoteList) CopyAddrs(preferredRanges []netip.Prefix) []netip.AddrPort
|
|||||||
r.RLock()
|
r.RLock()
|
||||||
defer r.RUnlock()
|
defer r.RUnlock()
|
||||||
c := make([]netip.AddrPort, len(r.addrs))
|
c := make([]netip.AddrPort, len(r.addrs))
|
||||||
for i, v := range r.addrs {
|
copy(c, r.addrs)
|
||||||
c[i] = v
|
|
||||||
}
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,9 +324,7 @@ func (r *RemoteList) CopyCache() *CacheMap {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if mc.relay != nil {
|
if mc.relay != nil {
|
||||||
for _, a := range mc.relay.relay {
|
c.Relay = append(c.Relay, mc.relay.relay...)
|
||||||
c.Relay = append(c.Relay, a)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -362,9 +358,7 @@ func (r *RemoteList) CopyBlockedRemotes() []netip.AddrPort {
|
|||||||
defer r.RUnlock()
|
defer r.RUnlock()
|
||||||
|
|
||||||
c := make([]netip.AddrPort, len(r.badRemotes))
|
c := make([]netip.AddrPort, len(r.badRemotes))
|
||||||
for i, v := range r.badRemotes {
|
copy(c, r.badRemotes)
|
||||||
c[i] = v
|
|
||||||
}
|
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -569,9 +563,7 @@ func (r *RemoteList) unlockedCollect() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if c.relay != nil {
|
if c.relay != nil {
|
||||||
for _, v := range c.relay.relay {
|
relays = append(relays, c.relay.relay...)
|
||||||
relays = append(relays, v)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -635,15 +627,15 @@ func (r *RemoteList) unlockedSort(preferredRanges []netip.Prefix) {
|
|||||||
a4 := a.Addr().Is4()
|
a4 := a.Addr().Is4()
|
||||||
b4 := b.Addr().Is4()
|
b4 := b.Addr().Is4()
|
||||||
switch {
|
switch {
|
||||||
case a4 == false && b4 == true:
|
case !a4 && b4:
|
||||||
// If i is v6 and j is v4, i is less than j
|
// If i is v6 and j is v4, i is less than j
|
||||||
return true
|
return true
|
||||||
|
|
||||||
case a4 == true && b4 == false:
|
case a4 && !b4:
|
||||||
// If j is v6 and i is v4, i is not less than j
|
// If j is v6 and i is v4, i is not less than j
|
||||||
return false
|
return false
|
||||||
|
|
||||||
case a4 == true && b4 == true:
|
case a4 && b4:
|
||||||
// i and j are both ipv4
|
// i and j are both ipv4
|
||||||
aPrivate := a.Addr().IsPrivate()
|
aPrivate := a.Addr().IsPrivate()
|
||||||
bPrivate := b.Addr().IsPrivate()
|
bPrivate := b.Addr().IsPrivate()
|
||||||
@@ -691,7 +683,6 @@ func (r *RemoteList) unlockedSort(preferredRanges []netip.Prefix) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
r.addrs = r.addrs[:a+1]
|
r.addrs = r.addrs[:a+1]
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// minInt returns the minimum integer of a or b
|
// minInt returns the minimum integer of a or b
|
||||||
|
|||||||
20
ssh.go
20
ssh.go
@@ -527,11 +527,11 @@ func sshStartCpuProfile(fs any, a []string, w sshd.StringWriter) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
func sshVersion(ifce *Interface, fs any, a []string, w sshd.StringWriter) error {
|
func sshVersion(ifce *Interface, _ any, _ []string, w sshd.StringWriter) error {
|
||||||
return w.WriteLine(fmt.Sprintf("%s", ifce.version))
|
return w.WriteLine(ifce.version)
|
||||||
}
|
}
|
||||||
|
|
||||||
func sshQueryLighthouse(ifce *Interface, fs any, a []string, w sshd.StringWriter) error {
|
func sshQueryLighthouse(ifce *Interface, _ any, a []string, w sshd.StringWriter) error {
|
||||||
if len(a) == 0 {
|
if len(a) == 0 {
|
||||||
return w.WriteLine("No vpn address was provided")
|
return w.WriteLine("No vpn address was provided")
|
||||||
}
|
}
|
||||||
@@ -584,7 +584,7 @@ func sshCloseTunnel(ifce *Interface, fs any, a []string, w sshd.StringWriter) er
|
|||||||
hostInfo.ConnectionState,
|
hostInfo.ConnectionState,
|
||||||
hostInfo,
|
hostInfo,
|
||||||
[]byte{},
|
[]byte{},
|
||||||
make([]byte, 12, 12),
|
make([]byte, 12),
|
||||||
make([]byte, mtu),
|
make([]byte, mtu),
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -614,12 +614,12 @@ func sshCreateTunnel(ifce *Interface, fs any, a []string, w sshd.StringWriter) e
|
|||||||
|
|
||||||
hostInfo := ifce.hostMap.QueryVpnAddr(vpnAddr)
|
hostInfo := ifce.hostMap.QueryVpnAddr(vpnAddr)
|
||||||
if hostInfo != nil {
|
if hostInfo != nil {
|
||||||
return w.WriteLine(fmt.Sprintf("Tunnel already exists"))
|
return w.WriteLine("Tunnel already exists")
|
||||||
}
|
}
|
||||||
|
|
||||||
hostInfo = ifce.handshakeManager.QueryVpnAddr(vpnAddr)
|
hostInfo = ifce.handshakeManager.QueryVpnAddr(vpnAddr)
|
||||||
if hostInfo != nil {
|
if hostInfo != nil {
|
||||||
return w.WriteLine(fmt.Sprintf("Tunnel already handshaking"))
|
return w.WriteLine("Tunnel already handshaking")
|
||||||
}
|
}
|
||||||
|
|
||||||
var addr netip.AddrPort
|
var addr netip.AddrPort
|
||||||
@@ -735,7 +735,7 @@ func sshGetMutexProfile(fs any, a []string, w sshd.StringWriter) error {
|
|||||||
return w.WriteLine(fmt.Sprintf("Mutex profile created at %s", a))
|
return w.WriteLine(fmt.Sprintf("Mutex profile created at %s", a))
|
||||||
}
|
}
|
||||||
|
|
||||||
func sshLogLevel(l *logrus.Logger, fs any, a []string, w sshd.StringWriter) error {
|
func sshLogLevel(l *logrus.Logger, _ any, a []string, w sshd.StringWriter) error {
|
||||||
if len(a) == 0 {
|
if len(a) == 0 {
|
||||||
return w.WriteLine(fmt.Sprintf("Log level is: %s", l.Level))
|
return w.WriteLine(fmt.Sprintf("Log level is: %s", l.Level))
|
||||||
}
|
}
|
||||||
@@ -749,7 +749,7 @@ func sshLogLevel(l *logrus.Logger, fs any, a []string, w sshd.StringWriter) erro
|
|||||||
return w.WriteLine(fmt.Sprintf("Log level is: %s", l.Level))
|
return w.WriteLine(fmt.Sprintf("Log level is: %s", l.Level))
|
||||||
}
|
}
|
||||||
|
|
||||||
func sshLogFormat(l *logrus.Logger, fs any, a []string, w sshd.StringWriter) error {
|
func sshLogFormat(l *logrus.Logger, _ any, a []string, w sshd.StringWriter) error {
|
||||||
if len(a) == 0 {
|
if len(a) == 0 {
|
||||||
return w.WriteLine(fmt.Sprintf("Log format is: %s", reflect.TypeOf(l.Formatter)))
|
return w.WriteLine(fmt.Sprintf("Log format is: %s", reflect.TypeOf(l.Formatter)))
|
||||||
}
|
}
|
||||||
@@ -822,10 +822,10 @@ func sshPrintCert(ifce *Interface, fs any, a []string, w sshd.StringWriter) erro
|
|||||||
return w.WriteLine(cert.String())
|
return w.WriteLine(cert.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func sshPrintRelays(ifce *Interface, fs any, a []string, w sshd.StringWriter) error {
|
func sshPrintRelays(ifce *Interface, fs any, _ []string, w sshd.StringWriter) error {
|
||||||
args, ok := fs.(*sshPrintTunnelFlags)
|
args, ok := fs.(*sshPrintTunnelFlags)
|
||||||
if !ok {
|
if !ok {
|
||||||
w.WriteLine(fmt.Sprintf("sshPrintRelays failed to convert args type"))
|
w.WriteLine("sshPrintRelays failed to convert args type")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,6 @@ type SSHServer struct {
|
|||||||
trustedCAs []ssh.PublicKey
|
trustedCAs []ssh.PublicKey
|
||||||
|
|
||||||
// List of available commands
|
// List of available commands
|
||||||
helpCommand *Command
|
|
||||||
commands *radix.Tree
|
commands *radix.Tree
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
|
|
||||||
@@ -43,7 +42,7 @@ func NewSSHServer(l *logrus.Entry) (*SSHServer, error) {
|
|||||||
conns: make(map[int]*session),
|
conns: make(map[int]*session),
|
||||||
}
|
}
|
||||||
|
|
||||||
cc := ssh.CertChecker{
|
cc := &ssh.CertChecker{
|
||||||
IsUserAuthority: func(auth ssh.PublicKey) bool {
|
IsUserAuthority: func(auth ssh.PublicKey) bool {
|
||||||
for _, ca := range s.trustedCAs {
|
for _, ca := range s.trustedCAs {
|
||||||
if bytes.Equal(ca.Marshal(), auth.Marshal()) {
|
if bytes.Equal(ca.Marshal(), auth.Marshal()) {
|
||||||
@@ -77,10 +76,11 @@ func NewSSHServer(l *logrus.Entry) (*SSHServer, error) {
|
|||||||
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
s.certChecker = cc
|
||||||
|
|
||||||
s.config = &ssh.ServerConfig{
|
s.config = &ssh.ServerConfig{
|
||||||
PublicKeyCallback: cc.Authenticate,
|
PublicKeyCallback: cc.Authenticate,
|
||||||
ServerVersion: fmt.Sprintf("SSH-2.0-Nebula???"),
|
ServerVersion: "SSH-2.0-Nebula???",
|
||||||
}
|
}
|
||||||
|
|
||||||
s.RegisterCommand(&Command{
|
s.RegisterCommand(&Command{
|
||||||
|
|||||||
@@ -170,7 +170,6 @@ func (s *session) dispatchCommand(line string, w StringWriter) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
_ = execCommand(c, args[1:], w)
|
_ = execCommand(c, args[1:], w)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *session) Close() {
|
func (s *session) Close() {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package nebula
|
package nebula
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -33,7 +34,7 @@ type TimerWheel[T any] struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type LockingTimerWheel[T any] struct {
|
type LockingTimerWheel[T any] struct {
|
||||||
m syncMutex
|
m sync.Mutex
|
||||||
t *TimerWheel[T]
|
t *TimerWheel[T]
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -80,9 +81,8 @@ func NewTimerWheel[T any](min, max time.Duration) *TimerWheel[T] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NewLockingTimerWheel is version of TimerWheel that is safe for concurrent use with a small performance penalty
|
// NewLockingTimerWheel is version of TimerWheel that is safe for concurrent use with a small performance penalty
|
||||||
func NewLockingTimerWheel[T any](name string, min, max time.Duration) *LockingTimerWheel[T] {
|
func NewLockingTimerWheel[T any](min, max time.Duration) *LockingTimerWheel[T] {
|
||||||
return &LockingTimerWheel[T]{
|
return &LockingTimerWheel[T]{
|
||||||
m: newSyncMutex(name),
|
|
||||||
t: NewTimerWheel[T](min, max),
|
t: NewTimerWheel[T](min, max),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -30,15 +30,11 @@ func (NoopConn) Rebind() error {
|
|||||||
func (NoopConn) LocalAddr() (netip.AddrPort, error) {
|
func (NoopConn) LocalAddr() (netip.AddrPort, error) {
|
||||||
return netip.AddrPort{}, nil
|
return netip.AddrPort{}, nil
|
||||||
}
|
}
|
||||||
func (NoopConn) ListenOut(_ EncReader) {
|
func (NoopConn) ListenOut(_ EncReader) {}
|
||||||
return
|
|
||||||
}
|
|
||||||
func (NoopConn) WriteTo(_ []byte, _ netip.AddrPort) error {
|
func (NoopConn) WriteTo(_ []byte, _ netip.AddrPort) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (NoopConn) ReloadConfig(_ *config.C) {
|
func (NoopConn) ReloadConfig(_ *config.C) {}
|
||||||
return
|
|
||||||
}
|
|
||||||
func (NoopConn) Close() error {
|
func (NoopConn) Close() error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ func NewGenericListener(l *logrus.Logger, ip netip.Addr, port int, multi bool, b
|
|||||||
if uc, ok := pc.(*net.UDPConn); ok {
|
if uc, ok := pc.(*net.UDPConn); ok {
|
||||||
return &GenericConn{UDPConn: uc, l: l}, nil
|
return &GenericConn{UDPConn: uc, l: l}, nil
|
||||||
}
|
}
|
||||||
return nil, fmt.Errorf("Unexpected PacketConn: %T %#v", pc, pc)
|
return nil, fmt.Errorf("unexpected PacketConn: %T %#v", pc, pc)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *GenericConn) WriteTo(b []byte, addr netip.AddrPort) error {
|
func (u *GenericConn) WriteTo(b []byte, addr netip.AddrPort) error {
|
||||||
@@ -66,10 +66,6 @@ func NewUDPStatsEmitter(udpConns []Conn) func() {
|
|||||||
return func() {}
|
return func() {}
|
||||||
}
|
}
|
||||||
|
|
||||||
type rawMessage struct {
|
|
||||||
Len uint32
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *GenericConn) ListenOut(r EncReader) {
|
func (u *GenericConn) ListenOut(r EncReader) {
|
||||||
buffer := make([]byte, MTU)
|
buffer := make([]byte, MTU)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user