Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ tokens-file = "path/to/client/tokens" # file that contains a list of client auth
tokens = ["client-token-1", "client-token-n"] # set of recognized client auth tokens
# one of tokens or tokens-file is required

endpoint-expiry-disable = false # disable keeping endpoint registrations alive after client disconnect (default false)
endpoint-expiry-timeout = "30s" # how long to keep endpoint registrations after client disconnect (default '30s')

status-addr = "127.0.0.1:19180" # address to listen for incoming status connections (TCP/HTTP, [host]:port) (disabled by default)
store-dir = "path/to/server-store" # directory for this server to persist runtime information, see Storage section for more info

Expand Down Expand Up @@ -247,6 +250,9 @@ clients-tokens-file = "path/to/client/tokens" # file containing a list of client
clients-tokens = ["client-token-1", "client-token-n"] # list of recognized client auth tokens
# one of client-tokens-file or client-tokens is required

endpoint-expiry-disable = false # disable keeping endpoint registrations alive after client disconnect (default false)
endpoint-expiry-timeout = "30s" # how long to keep endpoint registrations after client disconnect (default '30s')

relays-tokens-file = "path/to/relay/token" # file containing a list of relay auth tokens, one token per line
relays-tokens = ["relay-token-1", "relay-token-n"] # list of recognized relay auth tokens
# one of relay-tokens or relay-tokens-file is required if connecting relays
Expand Down Expand Up @@ -587,7 +593,6 @@ by adding account management and it is one of the easiest ways to start.
## Planlog

### Next
- [ ] do not discard client/peer/endpoint info immediately
- [ ] controlled server shutdown
- [ ] peer identity and support for options in p2p
- [ ] raw endpoint protocols
Expand All @@ -607,6 +612,9 @@ by adding account management and it is one of the easiest ways to start.

## Changelog

### v0.15.0
- [x] endpoint expiry: keep endpoint registrations alive for a grace period after client disconnect to smooth out reconnects

### v0.14.0
- [x] rewrite relay to not depend on control connection
- [x] complete migration to relay v2
Expand Down
11 changes: 11 additions & 0 deletions cmd/connet/control.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ type ControlConfig struct {
ClientsTokens []string `toml:"clients-tokens"`
ClientsTokenRestrictions []TokenRestriction `toml:"clients-token-restriction"`

EndpointExpiryDisable bool `toml:"endpoint-expiry-disable"`
EndpointExpiryTimeout durationValue `toml:"endpoint-expiry-timeout"`

RelaysIngresses []ControlIngress `toml:"relays-ingress"`
RelaysTokensFile string `toml:"relays-tokens-file"`
RelaysTokens []string `toml:"relays-tokens"`
Expand Down Expand Up @@ -72,6 +75,9 @@ func controlCmd() *cobra.Command {
cmd.Flags().StringArrayVar(&clientIngress.AllowCIDRs, "clients-allow-cidr", nil, "list of allowed networks for client connections (CIDR format)")
cmd.Flags().StringArrayVar(&clientIngress.DenyCIDRs, "clients-deny-cidr", nil, "list of denied networks for client connections (CIDR format)")

cmd.Flags().BoolVar(&flagsConfig.Control.EndpointExpiryDisable, "endpoint-expiry-disable", false, "disable keeping endpoint registrations alive after client disconnect (default false)")
cmd.Flags().Var(&flagsConfig.Control.EndpointExpiryTimeout, "endpoint-expiry-timeout", "how long to keep endpoint registrations after client disconnect (default '30s')")

cmd.Flags().StringVar(&flagsConfig.Control.RelaysTokensFile, "relays-tokens-file", "", "file containing a list of relay auth tokens (token per line)")
cmd.Flags().StringArrayVar(&flagsConfig.Control.RelaysTokens, "relays-tokens", nil, "list of relay auth tokens (fallback when 'relay-tokens-file' is not specified)")

Expand Down Expand Up @@ -146,6 +152,8 @@ func controlRun(ctx context.Context, cfg ControlConfig, logger *slog.Logger) err
return err
}

controlCfg.ClientsEndpointExpiry = resolveEndpointExpiry(cfg.EndpointExpiryDisable, cfg.EndpointExpiryTimeout)

var usedRelaysDefault bool
for ix, ingressCfg := range cfg.RelaysIngresses {
if ingressCfg.Addr == "" && !usedRelaysDefault {
Expand Down Expand Up @@ -268,6 +276,9 @@ func (c *ControlConfig) merge(o ControlConfig) {
}
c.ClientsTokenRestrictions = mergeSlices(c.ClientsTokenRestrictions, o.ClientsTokenRestrictions)

c.EndpointExpiryDisable = c.EndpointExpiryDisable || o.EndpointExpiryDisable
c.EndpointExpiryTimeout = override(c.EndpointExpiryTimeout, o.EndpointExpiryTimeout)

c.RelaysIngresses = mergeSlices(c.RelaysIngresses, o.RelaysIngresses)
if len(o.RelaysTokens) > 0 || o.RelaysTokensFile != "" { // new config completely overrides tokens
c.RelaysTokens = o.RelaysTokens
Expand Down
10 changes: 10 additions & 0 deletions cmd/connet/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,3 +307,13 @@ func (d *durationValue) String() string { return (*time.Duration)(d).String() }
func (d *durationValue) get() time.Duration {
return time.Duration(*d)
}

func resolveEndpointExpiry(disabled bool, timeout durationValue) time.Duration {
if disabled {
return 0
}
if d := timeout.get(); d > 0 {
return d
}
return 30 * time.Second
}
14 changes: 14 additions & 0 deletions cmd/connet/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ type ServerConfig struct {
Tokens []string `toml:"tokens"`
TokenRestrictions []TokenRestriction `toml:"token-restriction"`

EndpointExpiryDisable bool `toml:"endpoint-expiry-disable"`
EndpointExpiryTimeout durationValue `toml:"endpoint-expiry-timeout"`

RelayIngresses []RelayIngress `toml:"relay-ingress"`

StatusAddr string `toml:"status-addr"`
Expand Down Expand Up @@ -45,6 +48,9 @@ func serverCmd() *cobra.Command {
cmd.Flags().StringArrayVar(&clientIngress.AllowCIDRs, "allow-cidr", nil, "list of allowed networks for client connections (CIDR format)")
cmd.Flags().StringArrayVar(&clientIngress.DenyCIDRs, "deny-cidr", nil, "list of denied networks for client connections (CIDR format)")

cmd.Flags().BoolVar(&flagsConfig.Server.EndpointExpiryDisable, "endpoint-expiry-disable", false, "disable keeping endpoint registrations alive after client disconnect (default false)")
cmd.Flags().Var(&flagsConfig.Server.EndpointExpiryTimeout, "endpoint-expiry-timeout", "how long to keep endpoint registrations after client disconnect (default '30s')")

var relayIngress RelayIngress
cmd.Flags().StringVar(&relayIngress.Addr, "relay-addr", "", "relay clients server address (UDP/QUIC, [host]:port) (defaults to ':19191')")
cmd.Flags().StringArrayVar(&relayIngress.Hostports, "relay-hostport", nil, `list of host[:port]s advertised by the control server for clients to connect to this relay
Expand All @@ -64,9 +70,11 @@ func serverCmd() *cobra.Command {
if !clientIngress.isZero() {
flagsConfig.Server.Ingresses = append(flagsConfig.Server.Ingresses, clientIngress)
}

if !relayIngress.isZero() {
flagsConfig.Server.RelayIngresses = append(flagsConfig.Server.RelayIngresses, relayIngress)
}

cfg.merge(flagsConfig)

logger, err := logger(cfg)
Expand Down Expand Up @@ -116,6 +124,9 @@ func serverRun(ctx context.Context, cfg ServerConfig, logger *slog.Logger) error
}
opts = append(opts, server.ClientsAuthenticator(clientAuth))

endpointExpiry := resolveEndpointExpiry(cfg.EndpointExpiryDisable, cfg.EndpointExpiryTimeout)
opts = append(opts, server.ClientsEndpointExpiry(endpointExpiry))

var usedRelayDefault bool
for ix, ingressCfg := range cfg.RelayIngresses {
if ingressCfg.Addr == "" && !usedRelayDefault {
Expand Down Expand Up @@ -159,6 +170,9 @@ func (c *ServerConfig) merge(o ServerConfig) {
}
c.TokenRestrictions = mergeSlices(c.TokenRestrictions, o.TokenRestrictions)

c.EndpointExpiryDisable = c.EndpointExpiryDisable || o.EndpointExpiryDisable
c.EndpointExpiryTimeout = override(c.EndpointExpiryTimeout, o.EndpointExpiryTimeout)

c.RelayIngresses = mergeSlices(c.RelayIngresses, o.RelayIngresses)

c.StatusAddr = override(c.StatusAddr, o.StatusAddr)
Expand Down
16 changes: 13 additions & 3 deletions server/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"log/slog"
"net"
"os"
"time"

"github.com/connet-dev/connet/model"
"github.com/connet-dev/connet/server/control"
Expand All @@ -13,8 +14,9 @@ import (
)

type serverConfig struct {
clientsIngresses []control.Ingress
clientsAuth control.ClientAuthenticator
clientsIngresses []control.Ingress
clientsAuth control.ClientAuthenticator
clientsEndpointExpiry time.Duration

relayIngresses []relay.Ingress

Expand All @@ -24,7 +26,8 @@ type serverConfig struct {

func newServerConfig(opts []Option) (*serverConfig, error) {
cfg := &serverConfig{
logger: slog.Default(),
clientsEndpointExpiry: 30 * time.Second,
logger: slog.Default(),
}
for _, opt := range opts {
if err := opt(cfg); err != nil {
Expand Down Expand Up @@ -100,6 +103,13 @@ func ClientsAuthenticator(clientsAuth control.ClientAuthenticator) Option {
}
}

func ClientsEndpointExpiry(d time.Duration) Option {
return func(cfg *serverConfig) error {
cfg.clientsEndpointExpiry = d
return nil
}
}

func RelayIngress(icfg relay.Ingress) Option {
return func(cfg *serverConfig) error {
cfg.relayIngresses = append(cfg.relayIngresses, icfg)
Expand Down
Loading