From 2605948e015fe215640c2707e3a8a056a032ac1d Mon Sep 17 00:00:00 2001 From: Pascal Fischer <32096965+pascal-fischer@users.noreply.github.com> Date: Fri, 24 Jan 2025 12:04:50 +0100 Subject: [PATCH 1/9] [management] use account request buffer on sync (#3229) --- management/server/account_test.go | 36 ++++++++++--------- .../peers_handler_benchmark_test.go | 16 ++++----- management/server/peer.go | 2 +- 3 files changed, 29 insertions(+), 25 deletions(-) diff --git a/management/server/account_test.go b/management/server/account_test.go index 57bc0c757..1fc1ceb92 100644 --- a/management/server/account_test.go +++ b/management/server/account_test.go @@ -3005,6 +3005,8 @@ func peerShouldReceiveUpdate(t *testing.T, updateMessage <-chan *UpdateMessage) } func BenchmarkSyncAndMarkPeer(b *testing.B) { + b.Setenv("NB_GET_ACCOUNT_BUFFER_INTERVAL", "0") + benchCases := []struct { name string peers int @@ -3015,10 +3017,10 @@ func BenchmarkSyncAndMarkPeer(b *testing.B) { minMsPerOpCICD float64 maxMsPerOpCICD float64 }{ - {"Small", 50, 5, 1, 3, 3, 19}, - {"Medium", 500, 100, 7, 13, 10, 90}, - {"Large", 5000, 200, 65, 80, 60, 240}, - {"Small single", 50, 10, 1, 3, 3, 80}, + {"Small", 50, 5, 1, 5, 3, 19}, + {"Medium", 500, 100, 7, 22, 10, 90}, + {"Large", 5000, 200, 65, 110, 60, 240}, + {"Small single", 50, 10, 1, 4, 3, 80}, {"Medium single", 500, 10, 7, 13, 10, 37}, {"Large 5", 5000, 15, 65, 80, 60, 220}, } @@ -3072,6 +3074,7 @@ func BenchmarkSyncAndMarkPeer(b *testing.B) { } func BenchmarkLoginPeer_ExistingPeer(b *testing.B) { + b.Setenv("NB_GET_ACCOUNT_BUFFER_INTERVAL", "0") benchCases := []struct { name string peers int @@ -3082,12 +3085,12 @@ func BenchmarkLoginPeer_ExistingPeer(b *testing.B) { minMsPerOpCICD float64 maxMsPerOpCICD float64 }{ - {"Small", 50, 5, 102, 110, 3, 20}, - {"Medium", 500, 100, 105, 140, 20, 110}, - {"Large", 5000, 200, 160, 200, 120, 260}, - {"Small single", 50, 10, 102, 110, 5, 40}, - {"Medium single", 500, 10, 105, 140, 10, 60}, - {"Large 5", 5000, 15, 160, 200, 60, 180}, + {"Small", 50, 5, 2, 10, 3, 35}, + {"Medium", 500, 100, 5, 40, 20, 110}, + {"Large", 5000, 200, 60, 100, 120, 260}, + {"Small single", 50, 10, 2, 10, 5, 40}, + {"Medium single", 500, 10, 5, 40, 10, 60}, + {"Large 5", 5000, 15, 60, 100, 60, 180}, } log.SetOutput(io.Discard) @@ -3146,6 +3149,7 @@ func BenchmarkLoginPeer_ExistingPeer(b *testing.B) { } func BenchmarkLoginPeer_NewPeer(b *testing.B) { + b.Setenv("NB_GET_ACCOUNT_BUFFER_INTERVAL", "0") benchCases := []struct { name string peers int @@ -3156,12 +3160,12 @@ func BenchmarkLoginPeer_NewPeer(b *testing.B) { minMsPerOpCICD float64 maxMsPerOpCICD float64 }{ - {"Small", 50, 5, 107, 120, 10, 80}, - {"Medium", 500, 100, 105, 140, 30, 140}, - {"Large", 5000, 200, 180, 220, 140, 300}, - {"Small single", 50, 10, 107, 120, 10, 80}, - {"Medium single", 500, 10, 105, 140, 20, 60}, - {"Large 5", 5000, 15, 180, 220, 80, 200}, + {"Small", 50, 5, 7, 20, 10, 80}, + {"Medium", 500, 100, 5, 40, 30, 140}, + {"Large", 5000, 200, 80, 120, 140, 300}, + {"Small single", 50, 10, 7, 20, 10, 80}, + {"Medium single", 500, 10, 5, 40, 20, 60}, + {"Large 5", 5000, 15, 80, 120, 80, 200}, } log.SetOutput(io.Discard) diff --git a/management/server/http/testing/benchmarks/peers_handler_benchmark_test.go b/management/server/http/testing/benchmarks/peers_handler_benchmark_test.go index 23b4edefb..7f8eee6e7 100644 --- a/management/server/http/testing/benchmarks/peers_handler_benchmark_test.go +++ b/management/server/http/testing/benchmarks/peers_handler_benchmark_test.go @@ -145,14 +145,14 @@ func BenchmarkGetAllPeers(b *testing.B) { func BenchmarkDeletePeer(b *testing.B) { var expectedMetrics = map[string]testing_tools.PerformanceMetrics{ - "Peers - XS": {MinMsPerOpLocal: 0, MaxMsPerOpLocal: 4, MinMsPerOpCICD: 2, MaxMsPerOpCICD: 16}, - "Peers - S": {MinMsPerOpLocal: 0, MaxMsPerOpLocal: 4, MinMsPerOpCICD: 2, MaxMsPerOpCICD: 16}, - "Peers - M": {MinMsPerOpLocal: 0, MaxMsPerOpLocal: 4, MinMsPerOpCICD: 2, MaxMsPerOpCICD: 16}, - "Peers - L": {MinMsPerOpLocal: 0, MaxMsPerOpLocal: 4, MinMsPerOpCICD: 2, MaxMsPerOpCICD: 16}, - "Groups - L": {MinMsPerOpLocal: 0, MaxMsPerOpLocal: 4, MinMsPerOpCICD: 2, MaxMsPerOpCICD: 16}, - "Users - L": {MinMsPerOpLocal: 0, MaxMsPerOpLocal: 4, MinMsPerOpCICD: 2, MaxMsPerOpCICD: 16}, - "Setup Keys - L": {MinMsPerOpLocal: 0, MaxMsPerOpLocal: 4, MinMsPerOpCICD: 2, MaxMsPerOpCICD: 16}, - "Peers - XL": {MinMsPerOpLocal: 0, MaxMsPerOpLocal: 4, MinMsPerOpCICD: 2, MaxMsPerOpCICD: 16}, + "Peers - XS": {MinMsPerOpLocal: 0, MaxMsPerOpLocal: 4, MinMsPerOpCICD: 2, MaxMsPerOpCICD: 18}, + "Peers - S": {MinMsPerOpLocal: 0, MaxMsPerOpLocal: 4, MinMsPerOpCICD: 2, MaxMsPerOpCICD: 18}, + "Peers - M": {MinMsPerOpLocal: 0, MaxMsPerOpLocal: 4, MinMsPerOpCICD: 2, MaxMsPerOpCICD: 18}, + "Peers - L": {MinMsPerOpLocal: 0, MaxMsPerOpLocal: 4, MinMsPerOpCICD: 2, MaxMsPerOpCICD: 18}, + "Groups - L": {MinMsPerOpLocal: 0, MaxMsPerOpLocal: 4, MinMsPerOpCICD: 2, MaxMsPerOpCICD: 18}, + "Users - L": {MinMsPerOpLocal: 0, MaxMsPerOpLocal: 4, MinMsPerOpCICD: 2, MaxMsPerOpCICD: 18}, + "Setup Keys - L": {MinMsPerOpLocal: 0, MaxMsPerOpLocal: 4, MinMsPerOpCICD: 2, MaxMsPerOpCICD: 18}, + "Peers - XL": {MinMsPerOpLocal: 0, MaxMsPerOpLocal: 4, MinMsPerOpCICD: 2, MaxMsPerOpCICD: 18}, } log.SetOutput(io.Discard) diff --git a/management/server/peer.go b/management/server/peer.go index e5442acea..0eafb35e0 100644 --- a/management/server/peer.go +++ b/management/server/peer.go @@ -989,7 +989,7 @@ func (am *DefaultAccountManager) getValidatedPeerWithMap(ctx context.Context, is return peer, emptyMap, nil, nil } - account, err := am.Store.GetAccount(ctx, accountID) + account, err := am.requestBuffer.GetAccountWithBackpressure(ctx, accountID) if err != nil { return nil, nil, nil, err } From b6abd4b4da2af7d32c5b76c0211836477107383d Mon Sep 17 00:00:00 2001 From: Pascal Fischer <32096965+pascal-fischer@users.noreply.github.com> Date: Fri, 24 Jan 2025 14:17:30 +0100 Subject: [PATCH 2/9] [management/signal/relay] add metrics descriptions (#3233) --- management/server/peer.go | 8 ++- .../telemetry/accountmanager_metrics.go | 13 +++-- management/server/telemetry/grpc_metrics.go | 32 +++++++++--- .../server/telemetry/http_api_metrics.go | 35 ++++++++++--- management/server/telemetry/idp_metrics.go | 50 +++++++++++++++---- management/server/telemetry/store_metrics.go | 23 +++++++-- .../server/telemetry/updatechannel_metrics.go | 42 +++++++++++++--- management/server/types/account.go | 6 +-- relay/metrics/realy.go | 30 ++++++++--- signal/metrics/app.go | 40 +++++++++++---- 10 files changed, 213 insertions(+), 66 deletions(-) diff --git a/management/server/peer.go b/management/server/peer.go index 0eafb35e0..efd9c64e3 100644 --- a/management/server/peer.go +++ b/management/server/peer.go @@ -1130,11 +1130,6 @@ func (am *DefaultAccountManager) UpdateAccountPeers(ctx context.Context, account } start := time.Now() - defer func() { - if am.metrics != nil { - am.metrics.AccountManagerMetrics().CountUpdateAccountPeersDuration(time.Since(start)) - } - }() approvedPeersMap, err := am.integratedPeerValidator.GetValidatedPeers(account.Id, maps.Values(account.Groups), maps.Values(account.Peers), account.Settings.Extra) if err != nil { @@ -1175,6 +1170,9 @@ func (am *DefaultAccountManager) UpdateAccountPeers(ctx context.Context, account } wg.Wait() + if am.metrics != nil { + am.metrics.AccountManagerMetrics().CountUpdateAccountPeersDuration(time.Since(start)) + } } // UpdateAccountPeer updates a single peer that belongs to an account. diff --git a/management/server/telemetry/accountmanager_metrics.go b/management/server/telemetry/accountmanager_metrics.go index 4a5a31e2d..3b1e078eb 100644 --- a/management/server/telemetry/accountmanager_metrics.go +++ b/management/server/telemetry/accountmanager_metrics.go @@ -22,7 +22,8 @@ func NewAccountManagerMetrics(ctx context.Context, meter metric.Meter) (*Account metric.WithUnit("milliseconds"), metric.WithExplicitBucketBoundaries( 0.5, 1, 2.5, 5, 10, 25, 50, 100, 250, 500, 1000, 2500, 5000, 10000, 30000, - )) + ), + metric.WithDescription("Duration of triggering the account peers update and preparing the required data for the network map being sent to the clients")) if err != nil { return nil, err } @@ -31,7 +32,8 @@ func NewAccountManagerMetrics(ctx context.Context, meter metric.Meter) (*Account metric.WithUnit("milliseconds"), metric.WithExplicitBucketBoundaries( 0.1, 0.5, 1, 2.5, 5, 10, 25, 50, 100, 250, 500, 1000, - )) + ), + metric.WithDescription("Duration of calculating the peer network map that is sent to the clients")) if err != nil { return nil, err } @@ -40,12 +42,15 @@ func NewAccountManagerMetrics(ctx context.Context, meter metric.Meter) (*Account metric.WithUnit("objects"), metric.WithExplicitBucketBoundaries( 50, 100, 200, 500, 1000, 2500, 5000, 10000, - )) + ), + metric.WithDescription("Number of objects in the network map like peers, routes, firewall rules, etc. that are sent to the clients")) if err != nil { return nil, err } - peerMetaUpdateCount, err := meter.Int64Counter("management.account.peer.meta.update.counter", metric.WithUnit("1")) + peerMetaUpdateCount, err := meter.Int64Counter("management.account.peer.meta.update.counter", + metric.WithUnit("1"), + metric.WithDescription("Number of updates with new meta data from the peers")) if err != nil { return nil, err } diff --git a/management/server/telemetry/grpc_metrics.go b/management/server/telemetry/grpc_metrics.go index acbe1281c..ac6ff2ea8 100644 --- a/management/server/telemetry/grpc_metrics.go +++ b/management/server/telemetry/grpc_metrics.go @@ -22,32 +22,50 @@ type GRPCMetrics struct { // NewGRPCMetrics creates new GRPCMetrics struct and registers common metrics of the gRPC server func NewGRPCMetrics(ctx context.Context, meter metric.Meter) (*GRPCMetrics, error) { - syncRequestsCounter, err := meter.Int64Counter("management.grpc.sync.request.counter", metric.WithUnit("1")) + syncRequestsCounter, err := meter.Int64Counter("management.grpc.sync.request.counter", + metric.WithUnit("1"), + metric.WithDescription("Number of sync gRPC requests from the peers to establish a connection and receive network map updates (update channel)"), + ) if err != nil { return nil, err } - loginRequestsCounter, err := meter.Int64Counter("management.grpc.login.request.counter", metric.WithUnit("1")) + loginRequestsCounter, err := meter.Int64Counter("management.grpc.login.request.counter", + metric.WithUnit("1"), + metric.WithDescription("Number of login gRPC requests from the peers to authenticate and receive initial configuration and relay credentials"), + ) if err != nil { return nil, err } - getKeyRequestsCounter, err := meter.Int64Counter("management.grpc.key.request.counter", metric.WithUnit("1")) + getKeyRequestsCounter, err := meter.Int64Counter("management.grpc.key.request.counter", + metric.WithUnit("1"), + metric.WithDescription("Number of key gRPC requests from the peers to get the server's public WireGuard key"), + ) if err != nil { return nil, err } - activeStreamsGauge, err := meter.Int64ObservableGauge("management.grpc.connected.streams", metric.WithUnit("1")) + activeStreamsGauge, err := meter.Int64ObservableGauge("management.grpc.connected.streams", + metric.WithUnit("1"), + metric.WithDescription("Number of active peer streams connected to the gRPC server"), + ) if err != nil { return nil, err } - syncRequestDuration, err := meter.Int64Histogram("management.grpc.sync.request.duration.ms", metric.WithUnit("milliseconds")) + syncRequestDuration, err := meter.Int64Histogram("management.grpc.sync.request.duration.ms", + metric.WithUnit("milliseconds"), + metric.WithDescription("Duration of the sync gRPC requests from the peers to establish a connection and receive network map updates (update channel)"), + ) if err != nil { return nil, err } - loginRequestDuration, err := meter.Int64Histogram("management.grpc.login.request.duration.ms", metric.WithUnit("milliseconds")) + loginRequestDuration, err := meter.Int64Histogram("management.grpc.login.request.duration.ms", + metric.WithUnit("milliseconds"), + metric.WithDescription("Duration of the login gRPC requests from the peers to authenticate and receive initial configuration and relay credentials"), + ) if err != nil { return nil, err } @@ -57,7 +75,7 @@ func NewGRPCMetrics(ctx context.Context, meter metric.Meter) (*GRPCMetrics, erro // TODO(yury): This needs custom bucketing as we are interested in the values from 0 to server.channelBufferSize (100) channelQueue, err := meter.Int64Histogram( "management.grpc.updatechannel.queue", - metric.WithDescription("Number of update messages in the channel queue"), + metric.WithDescription("Number of update messages piling up in the update channel queue"), metric.WithUnit("length"), ) if err != nil { diff --git a/management/server/telemetry/http_api_metrics.go b/management/server/telemetry/http_api_metrics.go index 357f019c7..5ef9e6d02 100644 --- a/management/server/telemetry/http_api_metrics.go +++ b/management/server/telemetry/http_api_metrics.go @@ -74,37 +74,58 @@ type HTTPMiddleware struct { // NewMetricsMiddleware creates a new HTTPMiddleware func NewMetricsMiddleware(ctx context.Context, meter metric.Meter) (*HTTPMiddleware, error) { - httpRequestCounter, err := meter.Int64Counter(httpRequestCounterPrefix, metric.WithUnit("1")) + httpRequestCounter, err := meter.Int64Counter(httpRequestCounterPrefix, + metric.WithUnit("1"), + metric.WithDescription("Number of incoming HTTP requests by endpoint and method"), + ) if err != nil { return nil, err } - httpResponseCounter, err := meter.Int64Counter(httpResponseCounterPrefix, metric.WithUnit("1")) + httpResponseCounter, err := meter.Int64Counter(httpResponseCounterPrefix, + metric.WithUnit("1"), + metric.WithDescription("Number of outgoing HTTP responses by endpoint, method and returned status code"), + ) if err != nil { return nil, err } - totalHTTPRequestsCounter, err := meter.Int64Counter(fmt.Sprintf("%s.total", httpRequestCounterPrefix), metric.WithUnit("1")) + totalHTTPRequestsCounter, err := meter.Int64Counter(fmt.Sprintf("%s.total", httpRequestCounterPrefix), + metric.WithUnit("1"), + metric.WithDescription("Number of incoming HTTP requests"), + ) if err != nil { return nil, err } - totalHTTPResponseCounter, err := meter.Int64Counter(fmt.Sprintf("%s.total", httpResponseCounterPrefix), metric.WithUnit("1")) + totalHTTPResponseCounter, err := meter.Int64Counter(fmt.Sprintf("%s.total", httpResponseCounterPrefix), + metric.WithUnit("1"), + metric.WithDescription("Number of outgoing HTTP responses"), + ) if err != nil { return nil, err } - totalHTTPResponseCodeCounter, err := meter.Int64Counter(fmt.Sprintf("%s.code.total", httpResponseCounterPrefix), metric.WithUnit("1")) + totalHTTPResponseCodeCounter, err := meter.Int64Counter(fmt.Sprintf("%s.code.total", httpResponseCounterPrefix), + metric.WithUnit("1"), + metric.WithDescription("Number of outgoing HTTP responses by status code"), + ) if err != nil { return nil, err } - httpRequestDuration, err := meter.Int64Histogram(httpRequestDurationPrefix, metric.WithUnit("milliseconds")) + httpRequestDuration, err := meter.Int64Histogram(httpRequestDurationPrefix, + metric.WithUnit("milliseconds"), + metric.WithDescription("Duration of incoming HTTP requests by endpoint and method"), + ) if err != nil { return nil, err } - totalHTTPRequestDuration, err := meter.Int64Histogram(fmt.Sprintf("%s.total", httpRequestDurationPrefix), metric.WithUnit("milliseconds")) + totalHTTPRequestDuration, err := meter.Int64Histogram(fmt.Sprintf("%s.total", httpRequestDurationPrefix), + metric.WithUnit("milliseconds"), + metric.WithDescription("Duration of incoming HTTP requests"), + ) if err != nil { return nil, err } diff --git a/management/server/telemetry/idp_metrics.go b/management/server/telemetry/idp_metrics.go index 0bcd5d432..5337c91c2 100644 --- a/management/server/telemetry/idp_metrics.go +++ b/management/server/telemetry/idp_metrics.go @@ -23,43 +23,73 @@ type IDPMetrics struct { // NewIDPMetrics creates new IDPMetrics struct and registers common func NewIDPMetrics(ctx context.Context, meter metric.Meter) (*IDPMetrics, error) { - metaUpdateCounter, err := meter.Int64Counter("management.idp.update.user.meta.counter", metric.WithUnit("1")) + metaUpdateCounter, err := meter.Int64Counter("management.idp.update.user.meta.counter", + metric.WithUnit("1"), + metric.WithDescription("Number of updates of user metadata sent to the configured identity provider"), + ) if err != nil { return nil, err } - getUserByEmailCounter, err := meter.Int64Counter("management.idp.get.user.by.email.counter", metric.WithUnit("1")) + getUserByEmailCounter, err := meter.Int64Counter("management.idp.get.user.by.email.counter", + metric.WithUnit("1"), + metric.WithDescription("Number of requests to get a user by email from the configured identity provider"), + ) if err != nil { return nil, err } - getAllAccountsCounter, err := meter.Int64Counter("management.idp.get.accounts.counter", metric.WithUnit("1")) + getAllAccountsCounter, err := meter.Int64Counter("management.idp.get.accounts.counter", + metric.WithUnit("1"), + metric.WithDescription("Number of requests to get all accounts from the configured identity provider"), + ) if err != nil { return nil, err } - createUserCounter, err := meter.Int64Counter("management.idp.create.user.counter", metric.WithUnit("1")) + createUserCounter, err := meter.Int64Counter("management.idp.create.user.counter", + metric.WithUnit("1"), + metric.WithDescription("Number of requests to create a new user in the configured identity provider"), + ) if err != nil { return nil, err } - deleteUserCounter, err := meter.Int64Counter("management.idp.delete.user.counter", metric.WithUnit("1")) + deleteUserCounter, err := meter.Int64Counter("management.idp.delete.user.counter", + metric.WithUnit("1"), + metric.WithDescription("Number of requests to delete a user from the configured identity provider"), + ) if err != nil { return nil, err } - getAccountCounter, err := meter.Int64Counter("management.idp.get.account.counter", metric.WithUnit("1")) + getAccountCounter, err := meter.Int64Counter("management.idp.get.account.counter", + metric.WithUnit("1"), + metric.WithDescription("Number of requests to get all users in an account from the configured identity provider"), + ) if err != nil { return nil, err } - getUserByIDCounter, err := meter.Int64Counter("management.idp.get.user.by.id.counter", metric.WithUnit("1")) + getUserByIDCounter, err := meter.Int64Counter("management.idp.get.user.by.id.counter", + metric.WithUnit("1"), + metric.WithDescription("Number of requests to get a user by ID from the configured identity provider"), + ) if err != nil { return nil, err } - authenticateRequestCounter, err := meter.Int64Counter("management.idp.authenticate.request.counter", metric.WithUnit("1")) + authenticateRequestCounter, err := meter.Int64Counter("management.idp.authenticate.request.counter", + metric.WithUnit("1"), + metric.WithDescription("Number of requests to authenticate the server with the configured identity provider"), + ) if err != nil { return nil, err } - requestErrorCounter, err := meter.Int64Counter("management.idp.request.error.counter", metric.WithUnit("1")) + requestErrorCounter, err := meter.Int64Counter("management.idp.request.error.counter", + metric.WithUnit("1"), + metric.WithDescription("Number of errors that happened when doing http request to the configured identity provider"), + ) if err != nil { return nil, err } - requestStatusErrorCounter, err := meter.Int64Counter("management.idp.request.status.error.counter", metric.WithUnit("1")) + requestStatusErrorCounter, err := meter.Int64Counter("management.idp.request.status.error.counter", + metric.WithUnit("1"), + metric.WithDescription("Number of responses that came from the configured identity provider with non success status code"), + ) if err != nil { return nil, err } diff --git a/management/server/telemetry/store_metrics.go b/management/server/telemetry/store_metrics.go index bb3745b5a..f035ce847 100644 --- a/management/server/telemetry/store_metrics.go +++ b/management/server/telemetry/store_metrics.go @@ -20,28 +20,41 @@ type StoreMetrics struct { // NewStoreMetrics creates an instance of StoreMetrics func NewStoreMetrics(ctx context.Context, meter metric.Meter) (*StoreMetrics, error) { globalLockAcquisitionDurationMicro, err := meter.Int64Histogram("management.store.global.lock.acquisition.duration.micro", - metric.WithUnit("microseconds")) + metric.WithUnit("microseconds"), + metric.WithDescription("Duration of how long it takes to acquire the global lock in the store to block all other requests to the store"), + ) if err != nil { return nil, err } - globalLockAcquisitionDurationMs, err := meter.Int64Histogram("management.store.global.lock.acquisition.duration.ms") + globalLockAcquisitionDurationMs, err := meter.Int64Histogram("management.store.global.lock.acquisition.duration.ms", + metric.WithUnit("milliseconds"), + metric.WithDescription("Duration of how long a process holds the acquired global lock in the store"), + ) if err != nil { return nil, err } persistenceDurationMicro, err := meter.Int64Histogram("management.store.persistence.duration.micro", - metric.WithUnit("microseconds")) + metric.WithUnit("microseconds"), + metric.WithDescription("Duration of how long it takes to save or delete an account in the store"), + ) if err != nil { return nil, err } - persistenceDurationMs, err := meter.Int64Histogram("management.store.persistence.duration.ms") + persistenceDurationMs, err := meter.Int64Histogram("management.store.persistence.duration.ms", + metric.WithUnit("milliseconds"), + metric.WithDescription("Duration of how long it takes to save or delete an account in the store"), + ) if err != nil { return nil, err } - transactionDurationMs, err := meter.Int64Histogram("management.store.transaction.duration.ms") + transactionDurationMs, err := meter.Int64Histogram("management.store.transaction.duration.ms", + metric.WithUnit("milliseconds"), + metric.WithDescription("Duration of how long it takes to execute a transaction in the store"), + ) if err != nil { return nil, err } diff --git a/management/server/telemetry/updatechannel_metrics.go b/management/server/telemetry/updatechannel_metrics.go index 2582006e5..584b9ec20 100644 --- a/management/server/telemetry/updatechannel_metrics.go +++ b/management/server/telemetry/updatechannel_metrics.go @@ -23,42 +23,68 @@ type UpdateChannelMetrics struct { // NewUpdateChannelMetrics creates an instance of UpdateChannel func NewUpdateChannelMetrics(ctx context.Context, meter metric.Meter) (*UpdateChannelMetrics, error) { - createChannelDurationMicro, err := meter.Int64Histogram("management.updatechannel.create.duration.micro") + createChannelDurationMicro, err := meter.Int64Histogram("management.updatechannel.create.duration.micro", + metric.WithUnit("microseconds"), + metric.WithDescription("Duration of how long it takes to create a new peer update channel"), + ) if err != nil { return nil, err } - closeChannelDurationMicro, err := meter.Int64Histogram("management.updatechannel.close.one.duration.micro") + closeChannelDurationMicro, err := meter.Int64Histogram("management.updatechannel.close.one.duration.micro", + metric.WithUnit("microseconds"), + metric.WithDescription("Duration of how long it takes to close a peer update channel"), + ) if err != nil { return nil, err } - closeChannelsDurationMicro, err := meter.Int64Histogram("management.updatechannel.close.multiple.duration.micro") + closeChannelsDurationMicro, err := meter.Int64Histogram("management.updatechannel.close.multiple.duration.micro", + metric.WithUnit("microseconds"), + metric.WithDescription("Duration of how long it takes to close a set of peer update channels"), + ) + if err != nil { return nil, err } - closeChannels, err := meter.Int64Histogram("management.updatechannel.close.multiple.channels") + closeChannels, err := meter.Int64Histogram("management.updatechannel.close.multiple.channels", + metric.WithUnit("1"), + metric.WithDescription("Number of peer update channels that have been closed"), + ) + if err != nil { return nil, err } - sendUpdateDurationMicro, err := meter.Int64Histogram("management.updatechannel.send.duration.micro") + sendUpdateDurationMicro, err := meter.Int64Histogram("management.updatechannel.send.duration.micro", + metric.WithUnit("microseconds"), + metric.WithDescription("Duration of how long it takes to send an network map update to a peer"), + ) if err != nil { return nil, err } - getAllConnectedPeersDurationMicro, err := meter.Int64Histogram("management.updatechannel.get.all.duration.micro") + getAllConnectedPeersDurationMicro, err := meter.Int64Histogram("management.updatechannel.get.all.duration.micro", + metric.WithUnit("microseconds"), + metric.WithDescription("Duration of how long it takes to get all connected peers"), + ) if err != nil { return nil, err } - getAllConnectedPeers, err := meter.Int64Histogram("management.updatechannel.get.all.peers") + getAllConnectedPeers, err := meter.Int64Histogram("management.updatechannel.get.all.peers", + metric.WithUnit("1"), + metric.WithDescription("Number of connected peers"), + ) if err != nil { return nil, err } - hasChannelDurationMicro, err := meter.Int64Histogram("management.updatechannel.haschannel.duration.micro") + hasChannelDurationMicro, err := meter.Int64Histogram("management.updatechannel.haschannel.duration.micro", + metric.WithUnit("microseconds"), + metric.WithDescription("Duration of how long it takes to check if a peer has a channel"), + ) if err != nil { return nil, err } diff --git a/management/server/types/account.go b/management/server/types/account.go index f74d38cb6..0df15816f 100644 --- a/management/server/types/account.go +++ b/management/server/types/account.go @@ -289,14 +289,14 @@ func (a *Account) GetPeerNetworkMap( } if metrics != nil { - objectCount := int64(len(peersToConnect) + len(expiredPeers) + len(routesUpdate) + len(firewallRules)) + objectCount := int64(len(peersToConnectIncludingRouters) + len(expiredPeers) + len(routesUpdate) + len(networkResourcesRoutes) + len(firewallRules) + +len(networkResourcesFirewallRules) + len(routesFirewallRules)) metrics.CountNetworkMapObjects(objectCount) metrics.CountGetPeerNetworkMapDuration(time.Since(start)) if objectCount > 5000 { log.WithContext(ctx).Tracef("account: %s has a total resource count of %d objects, "+ - "peers to connect: %d, expired peers: %d, routes: %d, firewall rules: %d", - a.Id, objectCount, len(peersToConnect), len(expiredPeers), len(routesUpdate), len(firewallRules)) + "peers to connect: %d, expired peers: %d, routes: %d, firewall rules: %d, network resources routes: %d, network resources firewall rules: %d, routes firewall rules: %d", + a.Id, objectCount, len(peersToConnectIncludingRouters), len(expiredPeers), len(routesUpdate), len(firewallRules), len(networkResourcesRoutes), len(networkResourcesFirewallRules), len(routesFirewallRules)) } } diff --git a/relay/metrics/realy.go b/relay/metrics/realy.go index 4dc98a0e0..2e90940e6 100644 --- a/relay/metrics/realy.go +++ b/relay/metrics/realy.go @@ -29,37 +29,53 @@ type Metrics struct { } func NewMetrics(ctx context.Context, meter metric.Meter) (*Metrics, error) { - bytesSent, err := meter.Int64Counter("relay_transfer_sent_bytes_total") + bytesSent, err := meter.Int64Counter("relay_transfer_sent_bytes_total", + metric.WithDescription("Total number of bytes sent to peers"), + ) if err != nil { return nil, err } - bytesRecv, err := meter.Int64Counter("relay_transfer_received_bytes_total") + bytesRecv, err := meter.Int64Counter("relay_transfer_received_bytes_total", + metric.WithDescription("Total number of bytes received from peers"), + ) if err != nil { return nil, err } - peers, err := meter.Int64UpDownCounter("relay_peers") + peers, err := meter.Int64UpDownCounter("relay_peers", + metric.WithDescription("Number of connected peers"), + ) if err != nil { return nil, err } - peersActive, err := meter.Int64ObservableGauge("relay_peers_active") + peersActive, err := meter.Int64ObservableGauge("relay_peers_active", + metric.WithDescription("Number of active connected peers"), + ) if err != nil { return nil, err } - peersIdle, err := meter.Int64ObservableGauge("relay_peers_idle") + peersIdle, err := meter.Int64ObservableGauge("relay_peers_idle", + metric.WithDescription("Number of idle connected peers"), + ) if err != nil { return nil, err } - authTime, err := meter.Float64Histogram("relay_peer_authentication_time_milliseconds", metric.WithExplicitBucketBoundaries(getStandardBucketBoundaries()...)) + authTime, err := meter.Float64Histogram("relay_peer_authentication_time_milliseconds", + metric.WithExplicitBucketBoundaries(getStandardBucketBoundaries()...), + metric.WithDescription("Time taken to authenticate a peer"), + ) if err != nil { return nil, err } - peerStoreTime, err := meter.Float64Histogram("relay_peer_store_time_milliseconds", metric.WithExplicitBucketBoundaries(getStandardBucketBoundaries()...)) + peerStoreTime, err := meter.Float64Histogram("relay_peer_store_time_milliseconds", + metric.WithExplicitBucketBoundaries(getStandardBucketBoundaries()...), + metric.WithDescription("Time taken to store a new peer connection"), + ) if err != nil { return nil, err } diff --git a/signal/metrics/app.go b/signal/metrics/app.go index f8be88be7..b3457cf96 100644 --- a/signal/metrics/app.go +++ b/signal/metrics/app.go @@ -23,56 +23,76 @@ type AppMetrics struct { } func NewAppMetrics(meter metric.Meter) (*AppMetrics, error) { - activePeers, err := meter.Int64UpDownCounter("active_peers") + activePeers, err := meter.Int64UpDownCounter("active_peers", + metric.WithDescription("Number of active connected peers"), + ) if err != nil { return nil, err } peerConnectionDuration, err := meter.Int64Histogram("peer_connection_duration_seconds", - metric.WithExplicitBucketBoundaries(getPeerConnectionDurationBucketBoundaries()...)) + metric.WithExplicitBucketBoundaries(getPeerConnectionDurationBucketBoundaries()...), + metric.WithDescription("Duration of how long a peer was connected"), + ) if err != nil { return nil, err } - registrations, err := meter.Int64Counter("registrations_total") + registrations, err := meter.Int64Counter("registrations_total", + metric.WithDescription("Total number of peer registrations"), + ) if err != nil { return nil, err } - deregistrations, err := meter.Int64Counter("deregistrations_total") + deregistrations, err := meter.Int64Counter("deregistrations_total", + metric.WithDescription("Total number of peer deregistrations"), + ) if err != nil { return nil, err } - registrationFailures, err := meter.Int64Counter("registration_failures_total") + registrationFailures, err := meter.Int64Counter("registration_failures_total", + metric.WithDescription("Total number of peer registration failures"), + ) if err != nil { return nil, err } registrationDelay, err := meter.Float64Histogram("registration_delay_milliseconds", - metric.WithExplicitBucketBoundaries(getStandardBucketBoundaries()...)) + metric.WithExplicitBucketBoundaries(getStandardBucketBoundaries()...), + metric.WithDescription("Duration of how long it takes to register a peer"), + ) if err != nil { return nil, err } getRegistrationDelay, err := meter.Float64Histogram("get_registration_delay_milliseconds", - metric.WithExplicitBucketBoundaries(getStandardBucketBoundaries()...)) + metric.WithExplicitBucketBoundaries(getStandardBucketBoundaries()...), + metric.WithDescription("Duration of how long it takes to load a connection from the registry"), + ) if err != nil { return nil, err } - messagesForwarded, err := meter.Int64Counter("messages_forwarded_total") + messagesForwarded, err := meter.Int64Counter("messages_forwarded_total", + metric.WithDescription("Total number of messages forwarded to peers"), + ) if err != nil { return nil, err } - messageForwardFailures, err := meter.Int64Counter("message_forward_failures_total") + messageForwardFailures, err := meter.Int64Counter("message_forward_failures_total", + metric.WithDescription("Total number of message forwarding failures"), + ) if err != nil { return nil, err } messageForwardLatency, err := meter.Float64Histogram("message_forward_latency_milliseconds", - metric.WithExplicitBucketBoundaries(getStandardBucketBoundaries()...)) + metric.WithExplicitBucketBoundaries(getStandardBucketBoundaries()...), + metric.WithDescription("Duration of how long it takes to forward a message to a peer"), + ) if err != nil { return nil, err } From 5c05131a948acb885af45d00123423f2934313f6 Mon Sep 17 00:00:00 2001 From: Viktor Liu <17948409+lixmal@users.noreply.github.com> Date: Mon, 27 Jan 2025 13:51:57 +0100 Subject: [PATCH 3/9] [client] Support port ranges in peer ACLs (#3232) --- client/firewall/iptables/acl_linux.go | 33 +-- .../firewall/iptables/manager_linux_test.go | 9 +- client/firewall/iptables/router_linux.go | 4 +- client/firewall/iptables/router_linux_test.go | 12 +- client/firewall/manager/port.go | 8 +- client/firewall/nftables/acl_linux.go | 40 +--- .../firewall/nftables/manager_linux_test.go | 8 +- client/firewall/nftables/router_linux.go | 6 +- client/firewall/nftables/router_linux_test.go | 12 +- client/firewall/uspfilter/rule.go | 6 +- client/firewall/uspfilter/uspfilter.go | 46 ++-- .../uspfilter/uspfilter_bench_test.go | 12 +- client/firewall/uspfilter/uspfilter_test.go | 12 +- client/internal/acl/manager.go | 13 +- client/internal/dnsfwd/manager.go | 2 +- client/internal/engine.go | 2 +- management/proto/management.pb.go | 214 +++++++++--------- management/proto/management.proto | 1 + 18 files changed, 206 insertions(+), 234 deletions(-) diff --git a/client/firewall/iptables/acl_linux.go b/client/firewall/iptables/acl_linux.go index 2e745a31e..6c4895e05 100644 --- a/client/firewall/iptables/acl_linux.go +++ b/client/firewall/iptables/acl_linux.go @@ -4,7 +4,6 @@ import ( "fmt" "net" "slices" - "strconv" "github.com/coreos/go-iptables/iptables" "github.com/google/uuid" @@ -87,19 +86,10 @@ func (m *aclManager) AddPeerFiltering( action firewall.Action, ipsetName string, ) ([]firewall.Rule, error) { - var dPortVal, sPortVal string - if dPort != nil && dPort.Values != nil { - // TODO: we support only one port per rule in current implementation of ACLs - dPortVal = strconv.Itoa(dPort.Values[0]) - } - if sPort != nil && sPort.Values != nil { - sPortVal = strconv.Itoa(sPort.Values[0]) - } - chain := chainNameInputRules - ipsetName = transformIPsetName(ipsetName, sPortVal, dPortVal) - specs := filterRuleSpecs(ip, string(protocol), sPortVal, dPortVal, action, ipsetName) + ipsetName = transformIPsetName(ipsetName, sPort, dPort) + specs := filterRuleSpecs(ip, string(protocol), sPort, dPort, action, ipsetName) mangleSpecs := slices.Clone(specs) mangleSpecs = append(mangleSpecs, @@ -109,7 +99,6 @@ func (m *aclManager) AddPeerFiltering( ) specs = append(specs, "-j", actionToStr(action)) - if ipsetName != "" { if ipList, ipsetExists := m.ipsetStore.ipset(ipsetName); ipsetExists { if err := ipset.Add(ipsetName, ip.String()); err != nil { @@ -370,7 +359,7 @@ func (m *aclManager) updateState() { } // filterRuleSpecs returns the specs of a filtering rule -func filterRuleSpecs(ip net.IP, protocol, sPort, dPort string, action firewall.Action, ipsetName string) (specs []string) { +func filterRuleSpecs(ip net.IP, protocol string, sPort, dPort *firewall.Port, action firewall.Action, ipsetName string) (specs []string) { matchByIP := true // don't use IP matching if IP is ip 0.0.0.0 if ip.String() == "0.0.0.0" { @@ -387,12 +376,8 @@ func filterRuleSpecs(ip net.IP, protocol, sPort, dPort string, action firewall.A if protocol != "all" { specs = append(specs, "-p", protocol) } - if sPort != "" { - specs = append(specs, "--sport", sPort) - } - if dPort != "" { - specs = append(specs, "--dport", dPort) - } + specs = append(specs, applyPort("--sport", sPort)...) + specs = append(specs, applyPort("--dport", dPort)...) return specs } @@ -403,15 +388,15 @@ func actionToStr(action firewall.Action) string { return "DROP" } -func transformIPsetName(ipsetName string, sPort, dPort string) string { +func transformIPsetName(ipsetName string, sPort, dPort *firewall.Port) string { switch { case ipsetName == "": return "" - case sPort != "" && dPort != "": + case sPort != nil && dPort != nil: return ipsetName + "-sport-dport" - case sPort != "": + case sPort != nil: return ipsetName + "-sport" - case dPort != "": + case dPort != nil: return ipsetName + "-dport" default: return ipsetName diff --git a/client/firewall/iptables/manager_linux_test.go b/client/firewall/iptables/manager_linux_test.go index fe0bc86de..ba578c033 100644 --- a/client/firewall/iptables/manager_linux_test.go +++ b/client/firewall/iptables/manager_linux_test.go @@ -72,7 +72,8 @@ func TestIptablesManager(t *testing.T) { t.Run("add second rule", func(t *testing.T) { ip := net.ParseIP("10.20.0.3") port := &fw.Port{ - Values: []int{8043: 8046}, + IsRange: true, + Values: []uint16{8043, 8046}, } rule2, err = manager.AddPeerFiltering(ip, "tcp", port, nil, fw.ActionAccept, "", "accept HTTPS traffic from ports range") require.NoError(t, err, "failed to add rule") @@ -95,7 +96,7 @@ func TestIptablesManager(t *testing.T) { t.Run("reset check", func(t *testing.T) { // add second rule ip := net.ParseIP("10.20.0.3") - port := &fw.Port{Values: []int{5353}} + port := &fw.Port{Values: []uint16{5353}} _, err = manager.AddPeerFiltering(ip, "udp", nil, port, fw.ActionAccept, "", "accept Fake DNS traffic") require.NoError(t, err, "failed to add rule") @@ -145,7 +146,7 @@ func TestIptablesManagerIPSet(t *testing.T) { t.Run("add second rule", func(t *testing.T) { ip := net.ParseIP("10.20.0.3") port := &fw.Port{ - Values: []int{443}, + Values: []uint16{443}, } rule2, err = manager.AddPeerFiltering(ip, "tcp", port, nil, fw.ActionAccept, "default", "accept HTTPS traffic from ports range") for _, r := range rule2 { @@ -214,7 +215,7 @@ func TestIptablesCreatePerformance(t *testing.T) { ip := net.ParseIP("10.20.0.100") start := time.Now() for i := 0; i < testMax; i++ { - port := &fw.Port{Values: []int{1000 + i}} + port := &fw.Port{Values: []uint16{uint16(1000 + i)}} _, err = manager.AddPeerFiltering(ip, "tcp", nil, port, fw.ActionAccept, "", "accept HTTP traffic") require.NoError(t, err, "failed to add rule") diff --git a/client/firewall/iptables/router_linux.go b/client/firewall/iptables/router_linux.go index d067a3e7b..a47d3ffe6 100644 --- a/client/firewall/iptables/router_linux.go +++ b/client/firewall/iptables/router_linux.go @@ -590,10 +590,10 @@ func applyPort(flag string, port *firewall.Port) []string { if len(port.Values) > 1 { portList := make([]string, len(port.Values)) for i, p := range port.Values { - portList[i] = strconv.Itoa(p) + portList[i] = strconv.Itoa(int(p)) } return []string{"-m", "multiport", flag, strings.Join(portList, ",")} } - return []string{flag, strconv.Itoa(port.Values[0])} + return []string{flag, strconv.Itoa(int(port.Values[0]))} } diff --git a/client/firewall/iptables/router_linux_test.go b/client/firewall/iptables/router_linux_test.go index 861bf8601..0eb207567 100644 --- a/client/firewall/iptables/router_linux_test.go +++ b/client/firewall/iptables/router_linux_test.go @@ -239,7 +239,7 @@ func TestRouter_AddRouteFiltering(t *testing.T) { destination: netip.MustParsePrefix("10.0.0.0/24"), proto: firewall.ProtocolTCP, sPort: nil, - dPort: &firewall.Port{Values: []int{80}}, + dPort: &firewall.Port{Values: []uint16{80}}, direction: firewall.RuleDirectionIN, action: firewall.ActionAccept, expectSet: false, @@ -252,7 +252,7 @@ func TestRouter_AddRouteFiltering(t *testing.T) { }, destination: netip.MustParsePrefix("10.0.0.0/8"), proto: firewall.ProtocolUDP, - sPort: &firewall.Port{Values: []int{1024, 2048}, IsRange: true}, + sPort: &firewall.Port{Values: []uint16{1024, 2048}, IsRange: true}, dPort: nil, direction: firewall.RuleDirectionOUT, action: firewall.ActionDrop, @@ -285,7 +285,7 @@ func TestRouter_AddRouteFiltering(t *testing.T) { sources: []netip.Prefix{netip.MustParsePrefix("172.16.0.0/12")}, destination: netip.MustParsePrefix("192.168.0.0/16"), proto: firewall.ProtocolTCP, - sPort: &firewall.Port{Values: []int{80, 443, 8080}}, + sPort: &firewall.Port{Values: []uint16{80, 443, 8080}}, dPort: nil, direction: firewall.RuleDirectionOUT, action: firewall.ActionAccept, @@ -297,7 +297,7 @@ func TestRouter_AddRouteFiltering(t *testing.T) { destination: netip.MustParsePrefix("10.0.0.0/24"), proto: firewall.ProtocolUDP, sPort: nil, - dPort: &firewall.Port{Values: []int{5000, 5100}, IsRange: true}, + dPort: &firewall.Port{Values: []uint16{5000, 5100}, IsRange: true}, direction: firewall.RuleDirectionIN, action: firewall.ActionDrop, expectSet: false, @@ -307,8 +307,8 @@ func TestRouter_AddRouteFiltering(t *testing.T) { sources: []netip.Prefix{netip.MustParsePrefix("10.0.0.0/24")}, destination: netip.MustParsePrefix("172.16.0.0/16"), proto: firewall.ProtocolTCP, - sPort: &firewall.Port{Values: []int{1024, 65535}, IsRange: true}, - dPort: &firewall.Port{Values: []int{22}}, + sPort: &firewall.Port{Values: []uint16{1024, 65535}, IsRange: true}, + dPort: &firewall.Port{Values: []uint16{22}}, direction: firewall.RuleDirectionOUT, action: firewall.ActionAccept, expectSet: false, diff --git a/client/firewall/manager/port.go b/client/firewall/manager/port.go index 9061c1e63..df02e3117 100644 --- a/client/firewall/manager/port.go +++ b/client/firewall/manager/port.go @@ -30,7 +30,7 @@ type Port struct { IsRange bool // Values contains one value for single port, multiple values for the list of ports, or two values for the range of ports - Values []int + Values []uint16 } // String interface implementation @@ -40,7 +40,11 @@ func (p *Port) String() string { if ports != "" { ports += "," } - ports += strconv.Itoa(port) + ports += strconv.Itoa(int(port)) } + if p.IsRange { + ports = "range:" + ports + } + return ports } diff --git a/client/firewall/nftables/acl_linux.go b/client/firewall/nftables/acl_linux.go index 0d1d659af..fc5cc6873 100644 --- a/client/firewall/nftables/acl_linux.go +++ b/client/firewall/nftables/acl_linux.go @@ -2,7 +2,6 @@ package nftables import ( "bytes" - "encoding/binary" "fmt" "net" "slices" @@ -327,37 +326,8 @@ func (m *AclManager) addIOFiltering( } } - if sPort != nil && len(sPort.Values) != 0 { - expressions = append(expressions, - &expr.Payload{ - DestRegister: 1, - Base: expr.PayloadBaseTransportHeader, - Offset: 0, - Len: 2, - }, - &expr.Cmp{ - Op: expr.CmpOpEq, - Register: 1, - Data: encodePort(*sPort), - }, - ) - } - - if dPort != nil && len(dPort.Values) != 0 { - expressions = append(expressions, - &expr.Payload{ - DestRegister: 1, - Base: expr.PayloadBaseTransportHeader, - Offset: 2, - Len: 2, - }, - &expr.Cmp{ - Op: expr.CmpOpEq, - Register: 1, - Data: encodePort(*dPort), - }, - ) - } + expressions = append(expressions, applyPort(sPort, true)...) + expressions = append(expressions, applyPort(dPort, false)...) mainExpressions := slices.Clone(expressions) @@ -729,12 +699,6 @@ func generatePeerRuleId(ip net.IP, sPort *firewall.Port, dPort *firewall.Port, a return "set:" + ipset.Name + rulesetID } -func encodePort(port firewall.Port) []byte { - bs := make([]byte, 2) - binary.BigEndian.PutUint16(bs, uint16(port.Values[0])) - return bs -} - func ifname(n string) []byte { b := make([]byte, 16) copy(b, n+"\x00") diff --git a/client/firewall/nftables/manager_linux_test.go b/client/firewall/nftables/manager_linux_test.go index 9c9637282..8d693725a 100644 --- a/client/firewall/nftables/manager_linux_test.go +++ b/client/firewall/nftables/manager_linux_test.go @@ -74,7 +74,7 @@ func TestNftablesManager(t *testing.T) { testClient := &nftables.Conn{} - rule, err := manager.AddPeerFiltering(ip, fw.ProtocolTCP, nil, &fw.Port{Values: []int{53}}, fw.ActionDrop, "", "") + rule, err := manager.AddPeerFiltering(ip, fw.ProtocolTCP, nil, &fw.Port{Values: []uint16{53}}, fw.ActionDrop, "", "") require.NoError(t, err, "failed to add rule") err = manager.Flush() @@ -200,7 +200,7 @@ func TestNFtablesCreatePerformance(t *testing.T) { ip := net.ParseIP("10.20.0.100") start := time.Now() for i := 0; i < testMax; i++ { - port := &fw.Port{Values: []int{1000 + i}} + port := &fw.Port{Values: []uint16{uint16(1000 + i)}} _, err = manager.AddPeerFiltering(ip, "tcp", nil, port, fw.ActionAccept, "", "accept HTTP traffic") require.NoError(t, err, "failed to add rule") @@ -283,7 +283,7 @@ func TestNftablesManagerCompatibilityWithIptables(t *testing.T) { }) ip := net.ParseIP("100.96.0.1") - _, err = manager.AddPeerFiltering(ip, fw.ProtocolTCP, nil, &fw.Port{Values: []int{80}}, fw.ActionAccept, "", "test rule") + _, err = manager.AddPeerFiltering(ip, fw.ProtocolTCP, nil, &fw.Port{Values: []uint16{80}}, fw.ActionAccept, "", "test rule") require.NoError(t, err, "failed to add peer filtering rule") _, err = manager.AddRouteFiltering( @@ -291,7 +291,7 @@ func TestNftablesManagerCompatibilityWithIptables(t *testing.T) { netip.MustParsePrefix("10.1.0.0/24"), fw.ProtocolTCP, nil, - &fw.Port{Values: []int{443}}, + &fw.Port{Values: []uint16{443}}, fw.ActionAccept, ) require.NoError(t, err, "failed to add route filtering rule") diff --git a/client/firewall/nftables/router_linux.go b/client/firewall/nftables/router_linux.go index 34bc9a9bc..19734673b 100644 --- a/client/firewall/nftables/router_linux.go +++ b/client/firewall/nftables/router_linux.go @@ -956,12 +956,12 @@ func applyPort(port *firewall.Port, isSource bool) []expr.Any { &expr.Cmp{ Op: expr.CmpOpGte, Register: 1, - Data: binaryutil.BigEndian.PutUint16(uint16(port.Values[0])), + Data: binaryutil.BigEndian.PutUint16(port.Values[0]), }, &expr.Cmp{ Op: expr.CmpOpLte, Register: 1, - Data: binaryutil.BigEndian.PutUint16(uint16(port.Values[1])), + Data: binaryutil.BigEndian.PutUint16(port.Values[1]), }, ) } else { @@ -980,7 +980,7 @@ func applyPort(port *firewall.Port, isSource bool) []expr.Any { exprs = append(exprs, &expr.Cmp{ Op: expr.CmpOpEq, Register: 1, - Data: binaryutil.BigEndian.PutUint16(uint16(p)), + Data: binaryutil.BigEndian.PutUint16(p), }) } } diff --git a/client/firewall/nftables/router_linux_test.go b/client/firewall/nftables/router_linux_test.go index afc4d5c39..2a5d7168d 100644 --- a/client/firewall/nftables/router_linux_test.go +++ b/client/firewall/nftables/router_linux_test.go @@ -222,7 +222,7 @@ func TestRouter_AddRouteFiltering(t *testing.T) { destination: netip.MustParsePrefix("10.0.0.0/24"), proto: firewall.ProtocolTCP, sPort: nil, - dPort: &firewall.Port{Values: []int{80}}, + dPort: &firewall.Port{Values: []uint16{80}}, direction: firewall.RuleDirectionIN, action: firewall.ActionAccept, expectSet: false, @@ -235,7 +235,7 @@ func TestRouter_AddRouteFiltering(t *testing.T) { }, destination: netip.MustParsePrefix("10.0.0.0/8"), proto: firewall.ProtocolUDP, - sPort: &firewall.Port{Values: []int{1024, 2048}, IsRange: true}, + sPort: &firewall.Port{Values: []uint16{1024, 2048}, IsRange: true}, dPort: nil, direction: firewall.RuleDirectionOUT, action: firewall.ActionDrop, @@ -268,7 +268,7 @@ func TestRouter_AddRouteFiltering(t *testing.T) { sources: []netip.Prefix{netip.MustParsePrefix("172.16.0.0/12")}, destination: netip.MustParsePrefix("192.168.0.0/16"), proto: firewall.ProtocolTCP, - sPort: &firewall.Port{Values: []int{80, 443, 8080}}, + sPort: &firewall.Port{Values: []uint16{80, 443, 8080}}, dPort: nil, direction: firewall.RuleDirectionOUT, action: firewall.ActionAccept, @@ -280,7 +280,7 @@ func TestRouter_AddRouteFiltering(t *testing.T) { destination: netip.MustParsePrefix("10.0.0.0/24"), proto: firewall.ProtocolUDP, sPort: nil, - dPort: &firewall.Port{Values: []int{5000, 5100}, IsRange: true}, + dPort: &firewall.Port{Values: []uint16{5000, 5100}, IsRange: true}, direction: firewall.RuleDirectionIN, action: firewall.ActionDrop, expectSet: false, @@ -290,8 +290,8 @@ func TestRouter_AddRouteFiltering(t *testing.T) { sources: []netip.Prefix{netip.MustParsePrefix("10.0.0.0/24")}, destination: netip.MustParsePrefix("172.16.0.0/16"), proto: firewall.ProtocolTCP, - sPort: &firewall.Port{Values: []int{1024, 65535}, IsRange: true}, - dPort: &firewall.Port{Values: []int{22}}, + sPort: &firewall.Port{Values: []uint16{1024, 65535}, IsRange: true}, + dPort: &firewall.Port{Values: []uint16{22}}, direction: firewall.RuleDirectionOUT, action: firewall.ActionAccept, expectSet: false, diff --git a/client/firewall/uspfilter/rule.go b/client/firewall/uspfilter/rule.go index 1f98ef43e..c59d4b264 100644 --- a/client/firewall/uspfilter/rule.go +++ b/client/firewall/uspfilter/rule.go @@ -4,6 +4,8 @@ import ( "net" "github.com/google/gopacket" + + firewall "github.com/netbirdio/netbird/client/firewall/manager" ) // Rule to handle management of rules @@ -13,8 +15,8 @@ type Rule struct { ipLayer gopacket.LayerType matchByIP bool protoLayer gopacket.LayerType - sPort uint16 - dPort uint16 + sPort *firewall.Port + dPort *firewall.Port drop bool comment string diff --git a/client/firewall/uspfilter/uspfilter.go b/client/firewall/uspfilter/uspfilter.go index f35d971b8..757249b2d 100644 --- a/client/firewall/uspfilter/uspfilter.go +++ b/client/firewall/uspfilter/uspfilter.go @@ -179,13 +179,8 @@ func (m *Manager) AddPeerFiltering( r.matchByIP = false } - if sPort != nil && len(sPort.Values) == 1 { - r.sPort = uint16(sPort.Values[0]) - } - - if dPort != nil && len(dPort.Values) == 1 { - r.dPort = uint16(dPort.Values[0]) - } + r.sPort = sPort + r.dPort = dPort switch proto { case firewall.ProtocolTCP: @@ -364,7 +359,7 @@ func (m *Manager) checkUDPHooks(d *decoder, dstIP net.IP, packetData []byte) boo for _, ipKey := range []string{dstIP.String(), "0.0.0.0", "::"} { if rules, exists := m.outgoingRules[ipKey]; exists { for _, rule := range rules { - if rule.udpHook != nil && (rule.dPort == 0 || rule.dPort == uint16(d.udp.DstPort)) { + if rule.udpHook != nil && portsMatch(rule.dPort, uint16(d.udp.DstPort)) { return rule.udpHook(packetData) } } @@ -484,6 +479,23 @@ func (m *Manager) applyRules(srcIP net.IP, packetData []byte, rules map[string]R return true } +func portsMatch(rulePort *firewall.Port, packetPort uint16) bool { + if rulePort == nil { + return true + } + + if rulePort.IsRange { + return packetPort >= rulePort.Values[0] && packetPort <= rulePort.Values[1] + } + + for _, p := range rulePort.Values { + if p == packetPort { + return true + } + } + return false +} + func validateRule(ip net.IP, packetData []byte, rules map[string]Rule, d *decoder) (bool, bool) { payloadLayer := d.decoded[1] for _, rule := range rules { @@ -501,13 +513,7 @@ func validateRule(ip net.IP, packetData []byte, rules map[string]Rule, d *decode switch payloadLayer { case layers.LayerTypeTCP: - if rule.sPort == 0 && rule.dPort == 0 { - return rule.drop, true - } - if rule.sPort != 0 && rule.sPort == uint16(d.tcp.SrcPort) { - return rule.drop, true - } - if rule.dPort != 0 && rule.dPort == uint16(d.tcp.DstPort) { + if portsMatch(rule.sPort, uint16(d.tcp.SrcPort)) && portsMatch(rule.dPort, uint16(d.tcp.DstPort)) { return rule.drop, true } case layers.LayerTypeUDP: @@ -517,13 +523,7 @@ func validateRule(ip net.IP, packetData []byte, rules map[string]Rule, d *decode return rule.udpHook(packetData), true } - if rule.sPort == 0 && rule.dPort == 0 { - return rule.drop, true - } - if rule.sPort != 0 && rule.sPort == uint16(d.udp.SrcPort) { - return rule.drop, true - } - if rule.dPort != 0 && rule.dPort == uint16(d.udp.DstPort) { + if portsMatch(rule.sPort, uint16(d.udp.SrcPort)) && portsMatch(rule.dPort, uint16(d.udp.DstPort)) { return rule.drop, true } case layers.LayerTypeICMPv4, layers.LayerTypeICMPv6: @@ -548,7 +548,7 @@ func (m *Manager) AddUDPPacketHook( id: uuid.New().String(), ip: ip, protoLayer: layers.LayerTypeUDP, - dPort: dPort, + dPort: &firewall.Port{Values: []uint16{dPort}}, ipLayer: layers.LayerTypeIPv6, comment: fmt.Sprintf("UDP Hook direction: %v, ip:%v, dport:%d", in, ip, dPort), udpHook: hook, diff --git a/client/firewall/uspfilter/uspfilter_bench_test.go b/client/firewall/uspfilter/uspfilter_bench_test.go index 4a210bf47..46bc4439d 100644 --- a/client/firewall/uspfilter/uspfilter_bench_test.go +++ b/client/firewall/uspfilter/uspfilter_bench_test.go @@ -112,8 +112,8 @@ func BenchmarkCoreFiltering(b *testing.B) { for i := 0; i < 1000; i++ { // Simulate realistic ruleset size ip := generateRandomIPs(1)[0] _, err := m.AddPeerFiltering(ip, fw.ProtocolTCP, - &fw.Port{Values: []int{1024 + i}}, - &fw.Port{Values: []int{80}}, + &fw.Port{Values: []uint16{uint16(1024 + i)}}, + &fw.Port{Values: []uint16{80}}, fw.ActionAccept, "", "explicit return") require.NoError(b, err) } @@ -588,7 +588,7 @@ func BenchmarkLongLivedConnections(b *testing.B) { if sc.rules { // Single rule to allow all return traffic from port 80 _, err := manager.AddPeerFiltering(net.ParseIP("0.0.0.0"), fw.ProtocolTCP, - &fw.Port{Values: []int{80}}, + &fw.Port{Values: []uint16{80}}, nil, fw.ActionAccept, "", "return traffic") require.NoError(b, err) @@ -679,7 +679,7 @@ func BenchmarkShortLivedConnections(b *testing.B) { if sc.rules { // Single rule to allow all return traffic from port 80 _, err := manager.AddPeerFiltering(net.ParseIP("0.0.0.0"), fw.ProtocolTCP, - &fw.Port{Values: []int{80}}, + &fw.Port{Values: []uint16{80}}, nil, fw.ActionAccept, "", "return traffic") require.NoError(b, err) @@ -797,7 +797,7 @@ func BenchmarkParallelLongLivedConnections(b *testing.B) { // Setup initial state based on scenario if sc.rules { _, err := manager.AddPeerFiltering(net.ParseIP("0.0.0.0"), fw.ProtocolTCP, - &fw.Port{Values: []int{80}}, + &fw.Port{Values: []uint16{80}}, nil, fw.ActionAccept, "", "return traffic") require.NoError(b, err) @@ -884,7 +884,7 @@ func BenchmarkParallelShortLivedConnections(b *testing.B) { if sc.rules { _, err := manager.AddPeerFiltering(net.ParseIP("0.0.0.0"), fw.ProtocolTCP, - &fw.Port{Values: []int{80}}, + &fw.Port{Values: []uint16{80}}, nil, fw.ActionAccept, "", "return traffic") require.NoError(b, err) diff --git a/client/firewall/uspfilter/uspfilter_test.go b/client/firewall/uspfilter/uspfilter_test.go index 7e87443aa..9d795de69 100644 --- a/client/firewall/uspfilter/uspfilter_test.go +++ b/client/firewall/uspfilter/uspfilter_test.go @@ -69,7 +69,7 @@ func TestManagerAddPeerFiltering(t *testing.T) { ip := net.ParseIP("192.168.1.1") proto := fw.ProtocolTCP - port := &fw.Port{Values: []int{80}} + port := &fw.Port{Values: []uint16{80}} action := fw.ActionDrop comment := "Test rule" @@ -103,7 +103,7 @@ func TestManagerDeleteRule(t *testing.T) { ip := net.ParseIP("192.168.1.1") proto := fw.ProtocolTCP - port := &fw.Port{Values: []int{80}} + port := &fw.Port{Values: []uint16{80}} action := fw.ActionDrop comment := "Test rule 2" @@ -194,8 +194,8 @@ func TestAddUDPPacketHook(t *testing.T) { t.Errorf("expected ip %s, got %s", tt.ip, addedRule.ip) return } - if tt.dPort != addedRule.dPort { - t.Errorf("expected dPort %d, got %d", tt.dPort, addedRule.dPort) + if tt.dPort != addedRule.dPort.Values[0] { + t.Errorf("expected dPort %d, got %d", tt.dPort, addedRule.dPort.Values[0]) return } if layers.LayerTypeUDP != addedRule.protoLayer { @@ -223,7 +223,7 @@ func TestManagerReset(t *testing.T) { ip := net.ParseIP("192.168.1.1") proto := fw.ProtocolTCP - port := &fw.Port{Values: []int{80}} + port := &fw.Port{Values: []uint16{80}} action := fw.ActionDrop comment := "Test rule" @@ -463,7 +463,7 @@ func TestUSPFilterCreatePerformance(t *testing.T) { ip := net.ParseIP("10.20.0.100") start := time.Now() for i := 0; i < testMax; i++ { - port := &fw.Port{Values: []int{1000 + i}} + port := &fw.Port{Values: []uint16{uint16(1000 + i)}} _, err = manager.AddPeerFiltering(ip, "tcp", nil, port, fw.ActionAccept, "", "accept HTTP traffic") require.NoError(t, err, "failed to add rule") diff --git a/client/internal/acl/manager.go b/client/internal/acl/manager.go index 0ade5d7ce..9ec0bb031 100644 --- a/client/internal/acl/manager.go +++ b/client/internal/acl/manager.go @@ -268,13 +268,16 @@ func (d *DefaultManager) protoRuleToFirewallRule( } var port *firewall.Port - if r.Port != "" { + if r.PortInfo != nil { + port = convertPortInfo(r.PortInfo) + } else if r.Port != "" { + // old version of management, single port value, err := strconv.Atoi(r.Port) if err != nil { - return "", nil, fmt.Errorf("invalid port, skipping firewall rule") + return "", nil, fmt.Errorf("invalid port: %w", err) } port = &firewall.Port{ - Values: []int{value}, + Values: []uint16{uint16(value)}, } } @@ -539,14 +542,14 @@ func convertPortInfo(portInfo *mgmProto.PortInfo) *firewall.Port { if portInfo.GetPort() != 0 { return &firewall.Port{ - Values: []int{int(portInfo.GetPort())}, + Values: []uint16{uint16(int(portInfo.GetPort()))}, } } if portInfo.GetRange() != nil { return &firewall.Port{ IsRange: true, - Values: []int{int(portInfo.GetRange().Start), int(portInfo.GetRange().End)}, + Values: []uint16{uint16(portInfo.GetRange().Start), uint16(portInfo.GetRange().End)}, } } diff --git a/client/internal/dnsfwd/manager.go b/client/internal/dnsfwd/manager.go index 968f2d398..5d3036dde 100644 --- a/client/internal/dnsfwd/manager.go +++ b/client/internal/dnsfwd/manager.go @@ -81,7 +81,7 @@ func (m *Manager) Stop(ctx context.Context) error { func (h *Manager) allowDNSFirewall() error { dport := &firewall.Port{ IsRange: false, - Values: []int{ListenPort}, + Values: []uint16{ListenPort}, } if h.firewall == nil { diff --git a/client/internal/engine.go b/client/internal/engine.go index b3689c911..43749fbe5 100644 --- a/client/internal/engine.go +++ b/client/internal/engine.go @@ -495,7 +495,7 @@ func (e *Engine) initFirewall() error { } rosenpassPort := e.rpManager.GetAddress().Port - port := manager.Port{Values: []int{rosenpassPort}} + port := manager.Port{Values: []uint16{uint16(rosenpassPort)}} // this rule is static and will be torn down on engine down by the firewall manager if _, err := e.firewall.AddPeerFiltering( diff --git a/management/proto/management.pb.go b/management/proto/management.pb.go index 7846c286d..ae6559675 100644 --- a/management/proto/management.pb.go +++ b/management/proto/management.pb.go @@ -2624,6 +2624,7 @@ type FirewallRule struct { Action RuleAction `protobuf:"varint,3,opt,name=Action,proto3,enum=management.RuleAction" json:"Action,omitempty"` Protocol RuleProtocol `protobuf:"varint,4,opt,name=Protocol,proto3,enum=management.RuleProtocol" json:"Protocol,omitempty"` Port string `protobuf:"bytes,5,opt,name=Port,proto3" json:"Port,omitempty"` + PortInfo *PortInfo `protobuf:"bytes,6,opt,name=PortInfo,proto3" json:"PortInfo,omitempty"` } func (x *FirewallRule) Reset() { @@ -2693,6 +2694,13 @@ func (x *FirewallRule) GetPort() string { return "" } +func (x *FirewallRule) GetPortInfo() *PortInfo { + if x != nil { + return x.PortInfo + } + return nil +} + type NetworkAddress struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3397,7 +3405,7 @@ var file_management_proto_rawDesc = []byte{ 0x52, 0x02, 0x49, 0x50, 0x12, 0x16, 0x0a, 0x06, 0x4e, 0x53, 0x54, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x4e, 0x53, 0x54, 0x79, 0x70, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, - 0x22, 0xd9, 0x01, 0x0a, 0x0c, 0x46, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, + 0x22, 0x8b, 0x02, 0x0a, 0x0c, 0x46, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x50, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x50, 0x65, 0x65, 0x72, 0x49, 0x50, 0x12, 0x37, 0x0a, 0x09, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x19, 0x2e, 0x6d, @@ -3410,87 +3418,90 @@ var file_management_proto_rawDesc = []byte{ 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x75, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x12, 0x0a, 0x04, 0x50, 0x6f, 0x72, 0x74, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x22, 0x38, 0x0a, 0x0e, - 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x14, - 0x0a, 0x05, 0x6e, 0x65, 0x74, 0x49, 0x50, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6e, - 0x65, 0x74, 0x49, 0x50, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x63, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x03, 0x6d, 0x61, 0x63, 0x22, 0x1e, 0x0a, 0x06, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x73, - 0x12, 0x14, 0x0a, 0x05, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x05, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x08, 0x50, 0x6f, 0x72, 0x74, 0x49, - 0x6e, 0x66, 0x6f, 0x12, 0x14, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x0d, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x32, 0x0a, 0x05, 0x72, 0x61, 0x6e, - 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, - 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x2e, 0x52, - 0x61, 0x6e, 0x67, 0x65, 0x48, 0x00, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x1a, 0x2f, 0x0a, - 0x05, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, 0x0a, 0x03, - 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x65, 0x6e, 0x64, 0x42, 0x0f, - 0x0a, 0x0d, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x22, - 0xd1, 0x02, 0x0a, 0x11, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, 0x72, 0x65, 0x77, 0x61, 0x6c, - 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, - 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x73, 0x6f, 0x75, - 0x72, 0x63, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x06, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x6d, 0x61, 0x6e, 0x61, - 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x75, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, - 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, 0x08, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x18, 0x2e, - 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x75, 0x6c, 0x65, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, - 0x6c, 0x12, 0x30, 0x0a, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, - 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x49, - 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x73, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, 0x63, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x44, 0x79, 0x6e, 0x61, 0x6d, 0x69, - 0x63, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x07, 0x20, 0x03, - 0x28, 0x09, 0x52, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x26, 0x0a, 0x0e, 0x63, - 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x63, 0x6f, 0x6c, 0x2a, 0x4c, 0x0a, 0x0c, 0x52, 0x75, 0x6c, 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x63, 0x6f, 0x6c, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x10, 0x00, - 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, 0x43, 0x50, - 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x03, 0x12, 0x08, 0x0a, 0x04, 0x49, - 0x43, 0x4d, 0x50, 0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x55, 0x53, 0x54, 0x4f, 0x4d, 0x10, - 0x05, 0x2a, 0x20, 0x0a, 0x0d, 0x52, 0x75, 0x6c, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x06, 0x0a, 0x02, 0x49, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x4f, 0x55, - 0x54, 0x10, 0x01, 0x2a, 0x22, 0x0a, 0x0a, 0x52, 0x75, 0x6c, 0x65, 0x41, 0x63, 0x74, 0x69, 0x6f, - 0x6e, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x10, 0x00, 0x12, 0x08, 0x0a, - 0x04, 0x44, 0x52, 0x4f, 0x50, 0x10, 0x01, 0x32, 0x90, 0x04, 0x0a, 0x11, 0x4d, 0x61, 0x6e, 0x61, - 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x45, 0x0a, - 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x50, 0x6f, 0x72, 0x74, 0x12, 0x30, 0x0a, 0x08, + 0x50, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, + 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x50, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x38, + 0x0a, 0x0e, 0x4e, 0x65, 0x74, 0x77, 0x6f, 0x72, 0x6b, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, + 0x12, 0x14, 0x0a, 0x05, 0x6e, 0x65, 0x74, 0x49, 0x50, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x6e, 0x65, 0x74, 0x49, 0x50, 0x12, 0x10, 0x0a, 0x03, 0x6d, 0x61, 0x63, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x03, 0x6d, 0x61, 0x63, 0x22, 0x1e, 0x0a, 0x06, 0x43, 0x68, 0x65, 0x63, + 0x6b, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, + 0x09, 0x52, 0x05, 0x46, 0x69, 0x6c, 0x65, 0x73, 0x22, 0x96, 0x01, 0x0a, 0x08, 0x50, 0x6f, 0x72, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x14, 0x0a, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x0d, 0x48, 0x00, 0x52, 0x04, 0x70, 0x6f, 0x72, 0x74, 0x12, 0x32, 0x0a, 0x05, 0x72, + 0x61, 0x6e, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x6d, 0x61, 0x6e, + 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, + 0x2e, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x48, 0x00, 0x52, 0x05, 0x72, 0x61, 0x6e, 0x67, 0x65, 0x1a, + 0x2f, 0x0a, 0x05, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x10, + 0x0a, 0x03, 0x65, 0x6e, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x03, 0x65, 0x6e, 0x64, + 0x42, 0x0f, 0x0a, 0x0d, 0x70, 0x6f, 0x72, 0x74, 0x53, 0x65, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x22, 0xd1, 0x02, 0x0a, 0x11, 0x52, 0x6f, 0x75, 0x74, 0x65, 0x46, 0x69, 0x72, 0x65, 0x77, + 0x61, 0x6c, 0x6c, 0x52, 0x75, 0x6c, 0x65, 0x12, 0x22, 0x0a, 0x0c, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0c, 0x73, + 0x6f, 0x75, 0x72, 0x63, 0x65, 0x52, 0x61, 0x6e, 0x67, 0x65, 0x73, 0x12, 0x2e, 0x0a, 0x06, 0x61, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x16, 0x2e, 0x6d, 0x61, + 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x75, 0x6c, 0x65, 0x41, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x06, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x20, 0x0a, 0x0b, 0x64, + 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x64, 0x65, 0x73, 0x74, 0x69, 0x6e, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x34, 0x0a, + 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x18, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x52, 0x75, 0x6c, + 0x65, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x63, 0x6f, 0x6c, 0x12, 0x30, 0x0a, 0x08, 0x70, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x14, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x2e, 0x50, 0x6f, 0x72, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x08, 0x70, 0x6f, 0x72, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x69, 0x73, 0x44, 0x79, 0x6e, 0x61, 0x6d, + 0x69, 0x63, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x69, 0x73, 0x44, 0x79, 0x6e, 0x61, + 0x6d, 0x69, 0x63, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x18, 0x07, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x07, 0x64, 0x6f, 0x6d, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x26, 0x0a, + 0x0e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x0e, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x2a, 0x4c, 0x0a, 0x0c, 0x52, 0x75, 0x6c, 0x65, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x63, 0x6f, 0x6c, 0x12, 0x0b, 0x0a, 0x07, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, + 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, 0x41, 0x4c, 0x4c, 0x10, 0x01, 0x12, 0x07, 0x0a, 0x03, 0x54, + 0x43, 0x50, 0x10, 0x02, 0x12, 0x07, 0x0a, 0x03, 0x55, 0x44, 0x50, 0x10, 0x03, 0x12, 0x08, 0x0a, + 0x04, 0x49, 0x43, 0x4d, 0x50, 0x10, 0x04, 0x12, 0x0a, 0x0a, 0x06, 0x43, 0x55, 0x53, 0x54, 0x4f, + 0x4d, 0x10, 0x05, 0x2a, 0x20, 0x0a, 0x0d, 0x52, 0x75, 0x6c, 0x65, 0x44, 0x69, 0x72, 0x65, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x06, 0x0a, 0x02, 0x49, 0x4e, 0x10, 0x00, 0x12, 0x07, 0x0a, 0x03, + 0x4f, 0x55, 0x54, 0x10, 0x01, 0x2a, 0x22, 0x0a, 0x0a, 0x52, 0x75, 0x6c, 0x65, 0x41, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x0a, 0x0a, 0x06, 0x41, 0x43, 0x43, 0x45, 0x50, 0x54, 0x10, 0x00, 0x12, + 0x08, 0x0a, 0x04, 0x44, 0x52, 0x4f, 0x50, 0x10, 0x01, 0x32, 0x90, 0x04, 0x0a, 0x11, 0x4d, 0x61, + 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, + 0x45, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, + 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, + 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, - 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x04, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x1c, 0x2e, 0x6d, + 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x46, 0x0a, 0x04, 0x53, 0x79, 0x6e, 0x63, 0x12, 0x1c, + 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, + 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, - 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, - 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, - 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x42, 0x0a, 0x0c, - 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x11, 0x2e, 0x6d, - 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, - 0x1d, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, 0x65, 0x72, - 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x22, 0x00, - 0x12, 0x33, 0x0a, 0x09, 0x69, 0x73, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x12, 0x11, 0x2e, - 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x1a, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x44, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, - 0x6c, 0x6f, 0x77, 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, + 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x30, 0x01, 0x12, 0x42, + 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x12, 0x11, + 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x1a, 0x1d, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x4b, 0x65, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x22, 0x00, 0x12, 0x33, 0x0a, 0x09, 0x69, 0x73, 0x48, 0x65, 0x61, 0x6c, 0x74, 0x68, 0x79, 0x12, + 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x12, 0x5a, 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x44, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x46, 0x6c, 0x6f, 0x77, 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, + 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, - 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, - 0x00, 0x12, 0x58, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x50, 0x4b, 0x43, 0x45, 0x41, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x6c, 0x6f, 0x77, 0x12, 0x1c, 0x2e, + 0x65, 0x22, 0x00, 0x12, 0x58, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x50, 0x4b, 0x43, 0x45, 0x41, 0x75, + 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x46, 0x6c, 0x6f, 0x77, 0x12, + 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, + 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, - 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x1c, 0x2e, 0x6d, 0x61, - 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, - 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x3d, 0x0a, 0x08, 0x53, - 0x79, 0x6e, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, - 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, 0x6d, 0x65, - 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x42, 0x08, 0x5a, 0x06, 0x2f, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x70, 0x74, 0x65, 0x64, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x00, 0x12, 0x3d, 0x0a, + 0x08, 0x53, 0x79, 0x6e, 0x63, 0x4d, 0x65, 0x74, 0x61, 0x12, 0x1c, 0x2e, 0x6d, 0x61, 0x6e, 0x61, + 0x67, 0x65, 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6e, 0x63, 0x72, 0x79, 0x70, 0x74, 0x65, 0x64, + 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x1a, 0x11, 0x2e, 0x6d, 0x61, 0x6e, 0x61, 0x67, 0x65, + 0x6d, 0x65, 0x6e, 0x74, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x22, 0x00, 0x42, 0x08, 0x5a, 0x06, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -3596,29 +3607,30 @@ var file_management_proto_depIdxs = []int32{ 1, // 39: management.FirewallRule.Direction:type_name -> management.RuleDirection 2, // 40: management.FirewallRule.Action:type_name -> management.RuleAction 0, // 41: management.FirewallRule.Protocol:type_name -> management.RuleProtocol - 42, // 42: management.PortInfo.range:type_name -> management.PortInfo.Range - 2, // 43: management.RouteFirewallRule.action:type_name -> management.RuleAction - 0, // 44: management.RouteFirewallRule.protocol:type_name -> management.RuleProtocol - 40, // 45: management.RouteFirewallRule.portInfo:type_name -> management.PortInfo - 5, // 46: management.ManagementService.Login:input_type -> management.EncryptedMessage - 5, // 47: management.ManagementService.Sync:input_type -> management.EncryptedMessage - 17, // 48: management.ManagementService.GetServerKey:input_type -> management.Empty - 17, // 49: management.ManagementService.isHealthy:input_type -> management.Empty - 5, // 50: management.ManagementService.GetDeviceAuthorizationFlow:input_type -> management.EncryptedMessage - 5, // 51: management.ManagementService.GetPKCEAuthorizationFlow:input_type -> management.EncryptedMessage - 5, // 52: management.ManagementService.SyncMeta:input_type -> management.EncryptedMessage - 5, // 53: management.ManagementService.Login:output_type -> management.EncryptedMessage - 5, // 54: management.ManagementService.Sync:output_type -> management.EncryptedMessage - 16, // 55: management.ManagementService.GetServerKey:output_type -> management.ServerKeyResponse - 17, // 56: management.ManagementService.isHealthy:output_type -> management.Empty - 5, // 57: management.ManagementService.GetDeviceAuthorizationFlow:output_type -> management.EncryptedMessage - 5, // 58: management.ManagementService.GetPKCEAuthorizationFlow:output_type -> management.EncryptedMessage - 17, // 59: management.ManagementService.SyncMeta:output_type -> management.Empty - 53, // [53:60] is the sub-list for method output_type - 46, // [46:53] is the sub-list for method input_type - 46, // [46:46] is the sub-list for extension type_name - 46, // [46:46] is the sub-list for extension extendee - 0, // [0:46] is the sub-list for field type_name + 40, // 42: management.FirewallRule.PortInfo:type_name -> management.PortInfo + 42, // 43: management.PortInfo.range:type_name -> management.PortInfo.Range + 2, // 44: management.RouteFirewallRule.action:type_name -> management.RuleAction + 0, // 45: management.RouteFirewallRule.protocol:type_name -> management.RuleProtocol + 40, // 46: management.RouteFirewallRule.portInfo:type_name -> management.PortInfo + 5, // 47: management.ManagementService.Login:input_type -> management.EncryptedMessage + 5, // 48: management.ManagementService.Sync:input_type -> management.EncryptedMessage + 17, // 49: management.ManagementService.GetServerKey:input_type -> management.Empty + 17, // 50: management.ManagementService.isHealthy:input_type -> management.Empty + 5, // 51: management.ManagementService.GetDeviceAuthorizationFlow:input_type -> management.EncryptedMessage + 5, // 52: management.ManagementService.GetPKCEAuthorizationFlow:input_type -> management.EncryptedMessage + 5, // 53: management.ManagementService.SyncMeta:input_type -> management.EncryptedMessage + 5, // 54: management.ManagementService.Login:output_type -> management.EncryptedMessage + 5, // 55: management.ManagementService.Sync:output_type -> management.EncryptedMessage + 16, // 56: management.ManagementService.GetServerKey:output_type -> management.ServerKeyResponse + 17, // 57: management.ManagementService.isHealthy:output_type -> management.Empty + 5, // 58: management.ManagementService.GetDeviceAuthorizationFlow:output_type -> management.EncryptedMessage + 5, // 59: management.ManagementService.GetPKCEAuthorizationFlow:output_type -> management.EncryptedMessage + 17, // 60: management.ManagementService.SyncMeta:output_type -> management.Empty + 54, // [54:61] is the sub-list for method output_type + 47, // [47:54] is the sub-list for method input_type + 47, // [47:47] is the sub-list for extension type_name + 47, // [47:47] is the sub-list for extension extendee + 0, // [0:47] is the sub-list for field type_name } func init() { file_management_proto_init() } diff --git a/management/proto/management.proto b/management/proto/management.proto index 2318fc675..9db66ec4d 100644 --- a/management/proto/management.proto +++ b/management/proto/management.proto @@ -430,6 +430,7 @@ message FirewallRule { RuleAction Action = 3; RuleProtocol Protocol = 4; string Port = 5; + PortInfo PortInfo = 6; } message NetworkAddress { From a32ec97911962c14d386724463b183ef1e487a4d Mon Sep 17 00:00:00 2001 From: Viktor Liu <17948409+lixmal@users.noreply.github.com> Date: Mon, 27 Jan 2025 18:13:10 +0100 Subject: [PATCH 4/9] [client] Use dynamic dns route resolution on iOS (#3243) --- client/internal/routemanager/client.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/internal/routemanager/client.go b/client/internal/routemanager/client.go index 73f552aab..faf0fadaa 100644 --- a/client/internal/routemanager/client.go +++ b/client/internal/routemanager/client.go @@ -4,6 +4,7 @@ import ( "context" "fmt" "reflect" + runtime "runtime" "time" "github.com/hashicorp/go-multierror" @@ -439,7 +440,7 @@ func handlerType(rt *route.Route, useNewDNSRoute bool) int { return handlerTypeStatic } - if useNewDNSRoute { + if useNewDNSRoute && runtime.GOOS != "ios" { return handlerTypeDomain } return handlerTypeDynamic From 7335c825531abf14f5851437d03aef26e88ff53f Mon Sep 17 00:00:00 2001 From: Pascal Fischer <32096965+pascal-fischer@users.noreply.github.com> Date: Tue, 28 Jan 2025 07:05:21 +0100 Subject: [PATCH 5/9] [management] copy destination and source resource on policyRUle copy (#3235) --- management/server/types/policyrule.go | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/management/server/types/policyrule.go b/management/server/types/policyrule.go index bd9a99292..721621a4b 100644 --- a/management/server/types/policyrule.go +++ b/management/server/types/policyrule.go @@ -66,18 +66,20 @@ type PolicyRule struct { // Copy returns a copy of a policy rule func (pm *PolicyRule) Copy() *PolicyRule { rule := &PolicyRule{ - ID: pm.ID, - PolicyID: pm.PolicyID, - Name: pm.Name, - Description: pm.Description, - Enabled: pm.Enabled, - Action: pm.Action, - Destinations: make([]string, len(pm.Destinations)), - Sources: make([]string, len(pm.Sources)), - Bidirectional: pm.Bidirectional, - Protocol: pm.Protocol, - Ports: make([]string, len(pm.Ports)), - PortRanges: make([]RulePortRange, len(pm.PortRanges)), + ID: pm.ID, + PolicyID: pm.PolicyID, + Name: pm.Name, + Description: pm.Description, + Enabled: pm.Enabled, + Action: pm.Action, + Destinations: make([]string, len(pm.Destinations)), + DestinationResource: pm.DestinationResource, + Sources: make([]string, len(pm.Sources)), + SourceResource: pm.SourceResource, + Bidirectional: pm.Bidirectional, + Protocol: pm.Protocol, + Ports: make([]string, len(pm.Ports)), + PortRanges: make([]RulePortRange, len(pm.PortRanges)), } copy(rule.Destinations, pm.Destinations) copy(rule.Sources, pm.Sources) From a7ddb8f1f8fe2893d90132ee7de038d0adc93b46 Mon Sep 17 00:00:00 2001 From: Viktor Liu <17948409+lixmal@users.noreply.github.com> Date: Tue, 28 Jan 2025 12:25:45 +0100 Subject: [PATCH 6/9] [client] Replace engine probes with direct calls (#3195) --- client/cmd/up.go | 2 +- client/internal/connect.go | 17 ++--- client/internal/engine.go | 133 ++++++++++++------------------------- client/internal/probe.go | 58 ---------------- client/server/server.go | 46 +++++-------- 5 files changed, 69 insertions(+), 187 deletions(-) delete mode 100644 client/internal/probe.go diff --git a/client/cmd/up.go b/client/cmd/up.go index 9f8f738bc..f7c2bbfe4 100644 --- a/client/cmd/up.go +++ b/client/cmd/up.go @@ -190,7 +190,7 @@ func runInForegroundMode(ctx context.Context, cmd *cobra.Command) error { r.GetFullStatus() connectClient := internal.NewConnectClient(ctx, config, r) - return connectClient.Run() + return connectClient.Run(nil) } func runInDaemonMode(ctx context.Context, cmd *cobra.Command) error { diff --git a/client/internal/connect.go b/client/internal/connect.go index a1e8f0f8c..3e3f04f17 100644 --- a/client/internal/connect.go +++ b/client/internal/connect.go @@ -59,13 +59,8 @@ func NewConnectClient( } // Run with main logic. -func (c *ConnectClient) Run() error { - return c.run(MobileDependency{}, nil, nil) -} - -// RunWithProbes runs the client's main logic with probes attached -func (c *ConnectClient) RunWithProbes(probes *ProbeHolder, runningChan chan error) error { - return c.run(MobileDependency{}, probes, runningChan) +func (c *ConnectClient) Run(runningChan chan error) error { + return c.run(MobileDependency{}, runningChan) } // RunOnAndroid with main logic on mobile system @@ -84,7 +79,7 @@ func (c *ConnectClient) RunOnAndroid( HostDNSAddresses: dnsAddresses, DnsReadyListener: dnsReadyListener, } - return c.run(mobileDependency, nil, nil) + return c.run(mobileDependency, nil) } func (c *ConnectClient) RunOniOS( @@ -102,10 +97,10 @@ func (c *ConnectClient) RunOniOS( DnsManager: dnsManager, StateFilePath: stateFilePath, } - return c.run(mobileDependency, nil, nil) + return c.run(mobileDependency, nil) } -func (c *ConnectClient) run(mobileDependency MobileDependency, probes *ProbeHolder, runningChan chan error) error { +func (c *ConnectClient) run(mobileDependency MobileDependency, runningChan chan error) error { defer func() { if r := recover(); r != nil { log.Panicf("Panic occurred: %v, stack trace: %s", r, string(debug.Stack())) @@ -261,7 +256,7 @@ func (c *ConnectClient) run(mobileDependency MobileDependency, probes *ProbeHold checks := loginResp.GetChecks() c.engineMutex.Lock() - c.engine = NewEngineWithProbes(engineCtx, cancel, signalClient, mgmClient, relayManager, engineConfig, mobileDependency, c.statusRecorder, probes, checks) + c.engine = NewEngine(engineCtx, cancel, signalClient, mgmClient, relayManager, engineConfig, mobileDependency, c.statusRecorder, checks) c.engine.SetNetworkMapPersistence(c.persistNetworkMap) c.engineMutex.Unlock() diff --git a/client/internal/engine.go b/client/internal/engine.go index 43749fbe5..4f69adfa6 100644 --- a/client/internal/engine.go +++ b/client/internal/engine.go @@ -175,8 +175,6 @@ type Engine struct { dnsServer dns.Server - probes *ProbeHolder - // checks are the client-applied posture checks that need to be evaluated on the client checks []*mgmProto.Checks @@ -196,7 +194,7 @@ type Peer struct { WgAllowedIps string } -// NewEngine creates a new Connection Engine +// NewEngine creates a new Connection Engine with probes attached func NewEngine( clientCtx context.Context, clientCancel context.CancelFunc, @@ -207,33 +205,6 @@ func NewEngine( mobileDep MobileDependency, statusRecorder *peer.Status, checks []*mgmProto.Checks, -) *Engine { - return NewEngineWithProbes( - clientCtx, - clientCancel, - signalClient, - mgmClient, - relayManager, - config, - mobileDep, - statusRecorder, - nil, - checks, - ) -} - -// NewEngineWithProbes creates a new Connection Engine with probes attached -func NewEngineWithProbes( - clientCtx context.Context, - clientCancel context.CancelFunc, - signalClient signal.Client, - mgmClient mgm.Client, - relayManager *relayClient.Manager, - config *EngineConfig, - mobileDep MobileDependency, - statusRecorder *peer.Status, - probes *ProbeHolder, - checks []*mgmProto.Checks, ) *Engine { engine := &Engine{ clientCtx: clientCtx, @@ -251,7 +222,6 @@ func NewEngineWithProbes( networkSerial: 0, sshServerFunc: nbssh.DefaultSSHServer, statusRecorder: statusRecorder, - probes: probes, checks: checks, connSemaphore: semaphoregroup.NewSemaphoreGroup(connInitLimit), } @@ -450,7 +420,6 @@ func (e *Engine) Start() error { e.receiveSignalEvents() e.receiveManagementEvents() - e.receiveProbeEvents() // starting network monitor at the very last to avoid disruptions e.startNetworkMonitor() @@ -1513,72 +1482,58 @@ func (e *Engine) getRosenpassAddr() string { return "" } -func (e *Engine) receiveProbeEvents() { - if e.probes == nil { - return +// RunHealthProbes executes health checks for Signal, Management, Relay and WireGuard services +// and updates the status recorder with the latest states. +func (e *Engine) RunHealthProbes() bool { + signalHealthy := e.signal.IsHealthy() + log.Debugf("signal health check: healthy=%t", signalHealthy) + + managementHealthy := e.mgmClient.IsHealthy() + log.Debugf("management health check: healthy=%t", managementHealthy) + + results := append(e.probeSTUNs(), e.probeTURNs()...) + e.statusRecorder.UpdateRelayStates(results) + + relayHealthy := true + for _, res := range results { + if res.Err != nil { + relayHealthy = false + break + } } - if e.probes.SignalProbe != nil { - go e.probes.SignalProbe.Receive(e.ctx, func() bool { - healthy := e.signal.IsHealthy() - log.Debugf("received signal probe request, healthy: %t", healthy) - return healthy - }) + log.Debugf("relay health check: healthy=%t", relayHealthy) + + for _, key := range e.peerStore.PeersPubKey() { + wgStats, err := e.wgInterface.GetStats(key) + if err != nil { + log.Debugf("failed to get wg stats for peer %s: %s", key, err) + continue + } + // wgStats could be zero value, in which case we just reset the stats + if err := e.statusRecorder.UpdateWireGuardPeerState(key, wgStats); err != nil { + log.Debugf("failed to update wg stats for peer %s: %s", key, err) + } } - if e.probes.MgmProbe != nil { - go e.probes.MgmProbe.Receive(e.ctx, func() bool { - healthy := e.mgmClient.IsHealthy() - log.Debugf("received management probe request, healthy: %t", healthy) - return healthy - }) - } - - if e.probes.RelayProbe != nil { - go e.probes.RelayProbe.Receive(e.ctx, func() bool { - healthy := true - - results := append(e.probeSTUNs(), e.probeTURNs()...) - e.statusRecorder.UpdateRelayStates(results) - - // A single failed server will result in a "failed" probe - for _, res := range results { - if res.Err != nil { - healthy = false - break - } - } - - log.Debugf("received relay probe request, healthy: %t", healthy) - return healthy - }) - } - - if e.probes.WgProbe != nil { - go e.probes.WgProbe.Receive(e.ctx, func() bool { - log.Debug("received wg probe request") - - for _, key := range e.peerStore.PeersPubKey() { - wgStats, err := e.wgInterface.GetStats(key) - if err != nil { - log.Debugf("failed to get wg stats for peer %s: %s", key, err) - } - // wgStats could be zero value, in which case we just reset the stats - if err := e.statusRecorder.UpdateWireGuardPeerState(key, wgStats); err != nil { - log.Debugf("failed to update wg stats for peer %s: %s", key, err) - } - } - - return true - }) - } + allHealthy := signalHealthy && managementHealthy && relayHealthy + log.Debugf("all health checks completed: healthy=%t", allHealthy) + return allHealthy } func (e *Engine) probeSTUNs() []relay.ProbeResult { - return relay.ProbeAll(e.ctx, relay.ProbeSTUN, e.STUNs) + e.syncMsgMux.Lock() + stuns := slices.Clone(e.STUNs) + e.syncMsgMux.Unlock() + + return relay.ProbeAll(e.ctx, relay.ProbeSTUN, stuns) } func (e *Engine) probeTURNs() []relay.ProbeResult { - return relay.ProbeAll(e.ctx, relay.ProbeTURN, e.TURNs) + e.syncMsgMux.Lock() + turns := slices.Clone(e.TURNs) + e.syncMsgMux.Unlock() + + return relay.ProbeAll(e.ctx, relay.ProbeTURN, turns) } func (e *Engine) restartEngine() { diff --git a/client/internal/probe.go b/client/internal/probe.go deleted file mode 100644 index 23290cf74..000000000 --- a/client/internal/probe.go +++ /dev/null @@ -1,58 +0,0 @@ -package internal - -import "context" - -type ProbeHolder struct { - MgmProbe *Probe - SignalProbe *Probe - RelayProbe *Probe - WgProbe *Probe -} - -// Probe allows to run on-demand callbacks from different code locations. -// Pass the probe to a receiving and a sending end. The receiving end starts listening -// to requests with Receive and executes a callback when the sending end requests it -// by calling Probe. -type Probe struct { - request chan struct{} - result chan bool - ready bool -} - -// NewProbe returns a new initialized probe. -func NewProbe() *Probe { - return &Probe{ - request: make(chan struct{}), - result: make(chan bool), - } -} - -// Probe requests the callback to be run and returns a bool indicating success. -// It always returns true as long as the receiver is not ready. -func (p *Probe) Probe() bool { - if !p.ready { - return true - } - - p.request <- struct{}{} - return <-p.result -} - -// Receive starts listening for probe requests. On such a request it runs the supplied -// callback func which must return a bool indicating success. -// Blocks until the passed context is cancelled. -func (p *Probe) Receive(ctx context.Context, callback func() bool) { - p.ready = true - defer func() { - p.ready = false - }() - - for { - select { - case <-ctx.Done(): - return - case <-p.request: - p.result <- callback() - } - } -} diff --git a/client/server/server.go b/client/server/server.go index 638ede386..42420d1c1 100644 --- a/client/server/server.go +++ b/client/server/server.go @@ -63,12 +63,7 @@ type Server struct { statusRecorder *peer.Status sessionWatcher *internal.SessionWatcher - mgmProbe *internal.Probe - signalProbe *internal.Probe - relayProbe *internal.Probe - wgProbe *internal.Probe - lastProbe time.Time - + lastProbe time.Time persistNetworkMap bool } @@ -86,12 +81,7 @@ func New(ctx context.Context, configPath, logFile string) *Server { latestConfigInput: internal.ConfigInput{ ConfigPath: configPath, }, - logFile: logFile, - mgmProbe: internal.NewProbe(), - signalProbe: internal.NewProbe(), - relayProbe: internal.NewProbe(), - wgProbe: internal.NewProbe(), - + logFile: logFile, persistNetworkMap: true, } } @@ -202,14 +192,7 @@ func (s *Server) connectWithRetryRuns(ctx context.Context, config *internal.Conf s.connectClient = internal.NewConnectClient(ctx, config, statusRecorder) s.connectClient.SetNetworkMapPersistence(s.persistNetworkMap) - probes := internal.ProbeHolder{ - MgmProbe: s.mgmProbe, - SignalProbe: s.signalProbe, - RelayProbe: s.relayProbe, - WgProbe: s.wgProbe, - } - - err := s.connectClient.RunWithProbes(&probes, runningChan) + err := s.connectClient.Run(runningChan) if err != nil { log.Debugf("run client connection exited with error: %v. Will retry in the background", err) } @@ -676,9 +659,13 @@ func (s *Server) Down(ctx context.Context, _ *proto.DownRequest) (*proto.DownRes // Status returns the daemon status func (s *Server) Status( - _ context.Context, + ctx context.Context, msg *proto.StatusRequest, ) (*proto.StatusResponse, error) { + if ctx.Err() != nil { + return nil, ctx.Err() + } + s.mutex.Lock() defer s.mutex.Unlock() @@ -707,14 +694,17 @@ func (s *Server) Status( } func (s *Server) runProbes() { - if time.Since(s.lastProbe) > probeThreshold { - managementHealthy := s.mgmProbe.Probe() - signalHealthy := s.signalProbe.Probe() - relayHealthy := s.relayProbe.Probe() - wgProbe := s.wgProbe.Probe() + if s.connectClient == nil { + return + } - // Update last time only if all probes were successful - if managementHealthy && signalHealthy && relayHealthy && wgProbe { + engine := s.connectClient.Engine() + if engine == nil { + return + } + + if time.Since(s.lastProbe) > probeThreshold { + if engine.RunHealthProbes() { s.lastProbe = time.Now() } } From 46766e7e24e6ab1e111aad9b11c5969a8e5e170a Mon Sep 17 00:00:00 2001 From: Maycon Santos Date: Tue, 28 Jan 2025 22:48:19 +0100 Subject: [PATCH 7/9] [misc] Update sign pipeline version (#3246) --- .github/workflows/release.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 183cdb02c..8f267ebdd 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -9,7 +9,7 @@ on: pull_request: env: - SIGN_PIPE_VER: "v0.0.17" + SIGN_PIPE_VER: "v0.0.18" GORELEASER_VER: "v2.3.2" PRODUCT_NAME: "NetBird" COPYRIGHT: "Wiretrustee UG (haftungsbeschreankt)" From e20be2397c0c7ee83b36c09c04d5258b3a10e642 Mon Sep 17 00:00:00 2001 From: Viktor Liu <17948409+lixmal@users.noreply.github.com> Date: Tue, 28 Jan 2025 23:25:22 +0100 Subject: [PATCH 8/9] [client] Add missing peer ACL flush (#3247) --- client/firewall/nftables/acl_linux.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/firewall/nftables/acl_linux.go b/client/firewall/nftables/acl_linux.go index fc5cc6873..aff9e9188 100644 --- a/client/firewall/nftables/acl_linux.go +++ b/client/firewall/nftables/acl_linux.go @@ -348,6 +348,10 @@ func (m *AclManager) addIOFiltering( UserData: userData, }) + if err := m.rConn.Flush(); err != nil { + return nil, fmt.Errorf(flushError, err) + } + rule := &Rule{ nftRule: nftRule, mangleRule: m.createPreroutingRule(expressions, userData), @@ -359,6 +363,7 @@ func (m *AclManager) addIOFiltering( if ipset != nil { m.ipsetStore.AddReferenceToIpset(ipset.Name) } + return rule, nil } From 771c99a523569576d4377f0eb8819fa85dd5ace2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 29 Jan 2025 18:25:06 +0100 Subject: [PATCH 9/9] [clien]t Bump golang.org/x/net from 0.30.0 to 0.33.0 (#3218) Bumps [golang.org/x/net](https://github.com/golang/net) from 0.30.0 to 0.33.0. - [Commits](https://github.com/golang/net/compare/v0.30.0...v0.33.0) --- updated-dependencies: - dependency-name: golang.org/x/net dependency-type: direct:production ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 895ad5618..e65296a53 100644 --- a/go.mod +++ b/go.mod @@ -92,7 +92,7 @@ require ( goauthentik.io/api/v3 v3.2023051.3 golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 golang.org/x/mobile v0.0.0-20231127183840-76ac6878050a - golang.org/x/net v0.30.0 + golang.org/x/net v0.33.0 golang.org/x/oauth2 v0.19.0 golang.org/x/sync v0.10.0 golang.org/x/term v0.28.0 diff --git a/go.sum b/go.sum index 2aae595f0..e3670b99e 100644 --- a/go.sum +++ b/go.sum @@ -883,8 +883,8 @@ golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.14.0/go.mod h1:PpSgVXXLK0OxS0F31C1/tv6XNguvCrnXIDrFMspZIUI= golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= -golang.org/x/net v0.30.0 h1:AcW1SDZMkb8IpzCdQUaIq2sP4sZ4zw+55h6ynffypl4= -golang.org/x/net v0.30.0/go.mod h1:2wGyMJ5iFasEhkwi13ChkO/t1ECNC4X4eBKkVFyYFlU= +golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I= +golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=