Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

check ip restrictions earlier #22

Merged
merged 11 commits into from
Jan 20, 2025
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
23 changes: 12 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -189,35 +189,36 @@ To run a control server, use `connet control --config control-config.toml` comma
`control-config.toml` configuration specification:
```toml
[control]
addr = ":19190" # the address at which the control server will listen for connections, defaults to :19190
cert-file = "path/to/cert.pem" # the server certificate file, in pem format
key-file = "path/to/key.pem" # the server certificate private key file

client-tokens = ["client-token-1", "client-token-n"] # set of recognized client tokens
client-tokens-file = "path/to/client/tokens" # a file that contains a list of client tokens, one token per line
clients-addr = ":19190" # the address at which the control server will listen for client connections, defaults to :19190
clients-tokens = ["client-token-1", "client-token-n"] # set of recognized client tokens
clients-tokens-file = "path/to/client/tokens" # a file that contains a list of client tokens, one token per line
# one of client-tokens or client-tokens-file is required

relay-tokens = ["relay-token-1", "relay-token-n"] # set of recognized relay tokens
relay-tokens-file = "path/to/relay/token" # a file that contains a list of relay tokens, one token per line
relays-addr = ":19189" # the address at which the control server will listen for relay connections, defaults to :19189
relays-tokens = ["relay-token-1", "relay-token-n"] # set of recognized relay tokens
relays-tokens-file = "path/to/relay/token" # a file that contains a list of relay tokens, one token per line
# one of relay-tokens or relay-tokens-file is necessary when connecting relays

status-addr = "127.0.0.1:19180" # at what address the control server listens for status connections, disabled unless set
store-dir = "path/to/control-store" # where does this control server persist runtime information, defaults to a /tmp subdirectory

[control.client-ip-restriction] # defines restriction applicable for all client tokens, checked before verifying the token
[control.clients-ip-restriction] # defines restriction applicable for all client tokens, checked before verifying the token
allow-cidrs = [] # set of networks in CIDR format, to allow client connetctions from
deny-cidrs = [] # set of networks in CIDR format, to deny client connetctions from

[[control.client-token-restriction]] # defines restriction per client token, if specified must match the number of client tokens
[[control.clients-token-restriction]] # defines restriction per client token, if specified must match the number of client tokens
allow-cidrs = [] # set of networks in CIDR format, to allow client connetctions from
deny-cidrs = [] # set of networks in CIDR format, to deny client connetctions from
name-matches = "" # regular expression to check the name of the destination/source against

[control.relay-ip-restriction] # defines restriction applicable for all relay tokens, checked before verifying the token
[control.relays-ip-restriction] # defines restriction applicable for all relay tokens, checked before verifying the token
allow-cidrs = [] # set of networks in CIDR format, to allow relay connetctions from
deny-cidrs = [] # set of networks in CIDR format, to deny relay connetctions from

[[control.relay-token-ip-restriction]] # defines restriction per relay token, if specified must match the number of relay tokens
[[control.relays-token-ip-restriction]] # defines restriction per relay token, if specified must match the number of relay tokens
allow-cidrs = [] # set of networks in CIDR format, to allow relay connetctions from
deny-cidrs = [] # set of networks in CIDR format, to deny relay connetctions from
```
Expand Down Expand Up @@ -386,12 +387,12 @@ by adding account management and it is one of the easiest way to start.
- [x] Name access restrictions for clients
- [x] File http server
- [x] Use quic-go tracer, instead of ping (and duration estimation)
- [ ] error wrapping
- [x] Optimize global IP restrictions - check earlier

## Future

- [ ] UDP support
- [ ] Optimize global IP restrictions - check earlier
- [ ] error wrapping
- [ ] Gen config
- [ ] proxy proto support
- [ ] http source
126 changes: 69 additions & 57 deletions cmd/connet/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,10 +63,10 @@ type SourceConfig struct {
}

type ServerConfig struct {
Addr string `toml:"addr"`
Cert string `toml:"cert-file"`
Key string `toml:"key-file"`

Addr string `toml:"addr"`
IPRestriction IPRestriction `toml:"ip-restriction"`
Tokens []string `toml:"tokens"`
TokensFile string `toml:"tokens-file"`
Expand All @@ -80,19 +80,20 @@ type ServerConfig struct {
}

type ControlConfig struct {
Addr string `toml:"addr"`
Cert string `toml:"cert-file"`
Key string `toml:"key-file"`

ClientIPRestriction IPRestriction `toml:"client-ip-restriction"`
ClientTokens []string `toml:"client-tokens"`
ClientTokensFile string `toml:"client-tokens-file"`
ClientTokenRestrictions []TokenRestriction `toml:"client-token-restriction"`
ClientsAddr string `toml:"clients-addr"`
ClientsIPRestriction IPRestriction `toml:"clients-ip-restriction"`
ClientsTokens []string `toml:"clients-tokens"`
ClientsTokensFile string `toml:"clients-tokens-file"`
ClientsTokenRestrictions []TokenRestriction `toml:"clients-token-restriction"`

RelayIPRestriction IPRestriction `toml:"relay-ip-restriction"`
RelayTokens []string `toml:"relay-tokens"`
RelayTokensFile string `toml:"relay-tokens-file"`
RelayTokenIPRestrictions []IPRestriction `toml:"relay-token-ip-restriction"`
RelaysAddr string `toml:"relays-addr"`
RelaysIPRestriction IPRestriction `toml:"relays-ip-restriction"`
RelaysTokens []string `toml:"relays-tokens"`
RelaysTokensFile string `toml:"relays-tokens-file"`
RelaysTokenIPRestrictions []IPRestriction `toml:"relays-token-ip-restriction"`

StatusAddr string `toml:"status-addr"`
StoreDir string `toml:"store-dir"`
Expand Down Expand Up @@ -266,19 +267,20 @@ func controlCmd() *cobra.Command {
cmd.Flags().StringVar(&flagsConfig.LogLevel, "log-level", "", "log level to use")
cmd.Flags().StringVar(&flagsConfig.LogFormat, "log-format", "", "log formatter to use")

cmd.Flags().StringVar(&flagsConfig.Control.Addr, "addr", "", "control server addr to use")
cmd.Flags().StringVar(&flagsConfig.Control.Cert, "cert-file", "", "control server cert to use")
cmd.Flags().StringVar(&flagsConfig.Control.Key, "key-file", "", "control server key to use")

cmd.Flags().StringArrayVar(&flagsConfig.Control.ClientTokens, "client-tokens", nil, "client tokens for clients to connect")
cmd.Flags().StringVar(&flagsConfig.Control.ClientTokensFile, "client-tokens-file", "", "client tokens file to load")
cmd.Flags().StringSliceVar(&flagsConfig.Control.ClientIPRestriction.AllowCIDRs, "client-allow-cidr", nil, "cidr to allow client connections from")
cmd.Flags().StringSliceVar(&flagsConfig.Control.ClientIPRestriction.DenyCIDRs, "client-deny-cidr", nil, "cidr to deny client connections from")
cmd.Flags().StringVar(&flagsConfig.Control.ClientsAddr, "clients-addr", "", "control client server addr to use")
cmd.Flags().StringArrayVar(&flagsConfig.Control.ClientsTokens, "clients-tokens", nil, "client tokens for clients to connect")
cmd.Flags().StringVar(&flagsConfig.Control.ClientsTokensFile, "clients-tokens-file", "", "client tokens file to load")
cmd.Flags().StringSliceVar(&flagsConfig.Control.ClientsIPRestriction.AllowCIDRs, "clients-allow-cidr", nil, "cidr to allow client connections from")
cmd.Flags().StringSliceVar(&flagsConfig.Control.ClientsIPRestriction.DenyCIDRs, "clients-deny-cidr", nil, "cidr to deny client connections from")

cmd.Flags().StringArrayVar(&flagsConfig.Control.RelayTokens, "relay-tokens", nil, "relay tokens for clients to connect")
cmd.Flags().StringVar(&flagsConfig.Control.RelayTokensFile, "relay-tokens-file", "", "relay tokens file to load")
cmd.Flags().StringSliceVar(&flagsConfig.Control.RelayIPRestriction.AllowCIDRs, "relay-allow-cidr", nil, "cidr to allow relay connections from")
cmd.Flags().StringSliceVar(&flagsConfig.Control.RelayIPRestriction.DenyCIDRs, "relay-deny-cidr", nil, "cidr to deny relay connections from")
cmd.Flags().StringVar(&flagsConfig.Control.RelaysAddr, "relays-addr", "", "control relay server addr to use")
cmd.Flags().StringArrayVar(&flagsConfig.Control.RelaysTokens, "relays-tokens", nil, "relay tokens for clients to connect")
cmd.Flags().StringVar(&flagsConfig.Control.RelaysTokensFile, "relays-tokens-file", "", "relay tokens file to load")
cmd.Flags().StringSliceVar(&flagsConfig.Control.RelaysIPRestriction.AllowCIDRs, "relays-allow-cidr", nil, "cidr to allow relay connections from")
cmd.Flags().StringSliceVar(&flagsConfig.Control.RelaysIPRestriction.DenyCIDRs, "relays-deny-cidr", nil, "cidr to deny relay connections from")

cmd.Flags().StringVar(&flagsConfig.Control.StatusAddr, "status-addr", "", "status server address to listen")
cmd.Flags().StringVar(&flagsConfig.Control.StoreDir, "store-dir", "", "storage dir, /tmp subdirectory if empty")
Expand Down Expand Up @@ -490,10 +492,10 @@ func serverRun(ctx context.Context, cfg ServerConfig, logger *slog.Logger) error
var opts []connet.ServerOption

if cfg.Addr != "" {
opts = append(opts, connet.ServerControlAddress(cfg.Addr))
opts = append(opts, connet.ServerClientsAddress(cfg.Addr))
}
if cfg.Cert != "" {
opts = append(opts, connet.ServerControlCertificate(cfg.Cert, cfg.Key))
opts = append(opts, connet.ServerCertificate(cfg.Cert, cfg.Key))
}

if len(cfg.IPRestriction.AllowCIDRs) > 0 || len(cfg.IPRestriction.DenyCIDRs) > 0 {
Expand Down Expand Up @@ -542,15 +544,6 @@ func controlRun(ctx context.Context, cfg ControlConfig, logger *slog.Logger) err
Logger: logger,
}

if cfg.Addr == "" {
cfg.Addr = ":19190"
}
addr, err := net.ResolveUDPAddr("udp", cfg.Addr)
if err != nil {
return kleverr.Newf("control address cannot be resolved: %w", err)
}
controlCfg.Addr = addr

if cfg.Cert != "" {
cert, err := tls.LoadX509KeyPair(cfg.Cert, cfg.Key)
if err != nil {
Expand All @@ -559,51 +552,69 @@ func controlRun(ctx context.Context, cfg ControlConfig, logger *slog.Logger) err
controlCfg.Cert = cert
}

if len(cfg.ClientIPRestriction.AllowCIDRs) > 0 || len(cfg.ClientIPRestriction.DenyCIDRs) > 0 {
iprestr, err := restr.ParseIP(cfg.ClientIPRestriction.AllowCIDRs, cfg.ClientIPRestriction.DenyCIDRs)
if cfg.ClientsAddr == "" {
cfg.ClientsAddr = ":19190"
}
clientAddr, err := net.ResolveUDPAddr("udp", cfg.ClientsAddr)
if err != nil {
return kleverr.Newf("client address cannot be resolved: %w", err)
}
controlCfg.ClientsAddr = clientAddr

if len(cfg.ClientsIPRestriction.AllowCIDRs) > 0 || len(cfg.ClientsIPRestriction.DenyCIDRs) > 0 {
iprestr, err := restr.ParseIP(cfg.ClientsIPRestriction.AllowCIDRs, cfg.ClientsIPRestriction.DenyCIDRs)
if err != nil {
return err
}
controlCfg.ClientRestr = iprestr
controlCfg.ClientsRestr = iprestr
}

iprestr, namerestr, err := parseTokenRestrictions(cfg.ClientTokenRestrictions)
iprestr, namerestr, err := parseTokenRestrictions(cfg.ClientsTokenRestrictions)
if err != nil {
return err
}
if cfg.ClientTokensFile != "" {
tokens, terr := loadTokens(cfg.ClientTokensFile)
if cfg.ClientsTokensFile != "" {
tokens, terr := loadTokens(cfg.ClientsTokensFile)
if terr != nil {
return terr
}
controlCfg.ClientAuth, err = selfhosted.NewClientAuthenticatorRestricted(tokens, iprestr, namerestr)
controlCfg.ClientsAuth, err = selfhosted.NewClientAuthenticatorRestricted(tokens, iprestr, namerestr)
} else {
controlCfg.ClientAuth, err = selfhosted.NewClientAuthenticatorRestricted(cfg.ClientTokens, iprestr, namerestr)
controlCfg.ClientsAuth, err = selfhosted.NewClientAuthenticatorRestricted(cfg.ClientsTokens, iprestr, namerestr)
}
if err != nil {
return err
}

if len(cfg.RelayIPRestriction.AllowCIDRs) > 0 || len(cfg.RelayIPRestriction.DenyCIDRs) > 0 {
iprestr, err := restr.ParseIP(cfg.RelayIPRestriction.AllowCIDRs, cfg.RelayIPRestriction.DenyCIDRs)
if cfg.RelaysAddr == "" {
cfg.RelaysAddr = ":19189"
}
relayAddr, err := net.ResolveUDPAddr("udp", cfg.RelaysAddr)
if err != nil {
return kleverr.Newf("relay address cannot be resolved: %w", err)
}
controlCfg.RelaysAddr = relayAddr

if len(cfg.RelaysIPRestriction.AllowCIDRs) > 0 || len(cfg.RelaysIPRestriction.DenyCIDRs) > 0 {
iprestr, err := restr.ParseIP(cfg.RelaysIPRestriction.AllowCIDRs, cfg.RelaysIPRestriction.DenyCIDRs)
if err != nil {
return err
}
controlCfg.RelayRestr = iprestr
controlCfg.RelaysRestr = iprestr
}

relayRestr, err := parseIPRestrictions(cfg.RelayTokenIPRestrictions)
relayRestr, err := parseIPRestrictions(cfg.RelaysTokenIPRestrictions)
if err != nil {
return err
}
if cfg.RelayTokensFile != "" {
tokens, terr := loadTokens(cfg.RelayTokensFile)
if cfg.RelaysTokensFile != "" {
tokens, terr := loadTokens(cfg.RelaysTokensFile)
if terr != nil {
return terr
}
controlCfg.RelayAuth, err = selfhosted.NewRelayAuthenticatorRestricted(tokens, relayRestr)
controlCfg.RelaysAuth, err = selfhosted.NewRelayAuthenticatorRestricted(tokens, relayRestr)
} else {
controlCfg.RelayAuth, err = selfhosted.NewRelayAuthenticator(cfg.RelayTokens...)
controlCfg.RelaysAuth, err = selfhosted.NewRelayAuthenticator(cfg.RelaysTokens...)
}
if err != nil {
return err
Expand Down Expand Up @@ -664,7 +675,7 @@ func relayRun(ctx context.Context, cfg RelayConfig, logger *slog.Logger) error {
relayCfg.Hostport = model.HostPort{Host: cfg.Hostname, Port: uint16(serverAddr.Port)}

if cfg.ControlAddr == "" {
cfg.ControlAddr = "localhost:19190"
cfg.ControlAddr = "localhost:19189"
}
controlAddr, err := net.ResolveUDPAddr("udp", cfg.ControlAddr)
if err != nil {
Expand Down Expand Up @@ -823,19 +834,20 @@ func (c *ServerConfig) merge(o ServerConfig) {
}

func (c *ControlConfig) merge(o ControlConfig) {
c.Addr = override(c.Addr, o.Addr)
c.Cert = override(c.Cert, o.Cert)
c.Key = override(c.Key, o.Key)

c.ClientIPRestriction.AllowCIDRs = append(c.ClientIPRestriction.AllowCIDRs, o.ClientIPRestriction.AllowCIDRs...)
c.ClientIPRestriction.DenyCIDRs = append(c.ClientIPRestriction.DenyCIDRs, o.ClientIPRestriction.DenyCIDRs...)
c.ClientTokens = append(c.ClientTokens, o.ClientTokens...)
c.ClientTokensFile = override(c.ClientTokensFile, o.ClientTokensFile)

c.RelayIPRestriction.AllowCIDRs = append(c.RelayIPRestriction.AllowCIDRs, o.RelayIPRestriction.AllowCIDRs...)
c.RelayIPRestriction.DenyCIDRs = append(c.RelayIPRestriction.DenyCIDRs, o.RelayIPRestriction.DenyCIDRs...)
c.RelayTokens = append(c.RelayTokens, o.RelayTokens...)
c.RelayTokensFile = override(c.RelayTokensFile, o.RelayTokensFile)
c.ClientsAddr = override(c.ClientsAddr, o.ClientsAddr)
c.ClientsIPRestriction.AllowCIDRs = append(c.ClientsIPRestriction.AllowCIDRs, o.ClientsIPRestriction.AllowCIDRs...)
c.ClientsIPRestriction.DenyCIDRs = append(c.ClientsIPRestriction.DenyCIDRs, o.ClientsIPRestriction.DenyCIDRs...)
c.ClientsTokens = append(c.ClientsTokens, o.ClientsTokens...)
c.ClientsTokensFile = override(c.ClientsTokensFile, o.ClientsTokensFile)

c.RelaysAddr = override(c.RelaysAddr, o.RelaysAddr)
c.RelaysIPRestriction.AllowCIDRs = append(c.RelaysIPRestriction.AllowCIDRs, o.RelaysIPRestriction.AllowCIDRs...)
c.RelaysIPRestriction.DenyCIDRs = append(c.RelaysIPRestriction.DenyCIDRs, o.RelaysIPRestriction.DenyCIDRs...)
c.RelaysTokens = append(c.RelaysTokens, o.RelaysTokens...)
c.RelaysTokensFile = override(c.RelaysTokensFile, o.RelaysTokensFile)

c.StatusAddr = override(c.StatusAddr, o.StatusAddr)
c.StoreDir = override(c.StoreDir, o.StoreDir)
Expand Down
Loading
Loading