mirror of
https://codeberg.org/cunicu/cunicu.git
synced 2025-09-26 21:01:14 +08:00
@@ -34,7 +34,7 @@ cunīcu's documentation can be found here: [cunicu.li/docs](https://cunicu.li/do
|
||||
|
||||
## Authors
|
||||
|
||||
- Steffen Vogel ([@stv0g](https://github.com/stv0g), Institute for Automation of Complex Power Systems, RWTH Aachen University)
|
||||
- Steffen Vogel ([@stv0g](https://github.com/stv0g), Institute for Automation of Complex Power Systems, RWTH Aachen University)
|
||||
|
||||
## License
|
||||
|
||||
|
@@ -10,7 +10,7 @@ import (
|
||||
"go.uber.org/zap/zapio"
|
||||
|
||||
"github.com/stv0g/cunicu/pkg/config"
|
||||
d "github.com/stv0g/cunicu/pkg/daemon"
|
||||
"github.com/stv0g/cunicu/pkg/daemon"
|
||||
"github.com/stv0g/cunicu/pkg/rpc"
|
||||
"github.com/stv0g/cunicu/pkg/util/terminal"
|
||||
)
|
||||
@@ -19,8 +19,8 @@ var (
|
||||
daemonCmd = &cobra.Command{
|
||||
Use: "daemon [interface-names...]",
|
||||
Short: "Start the daemon",
|
||||
Example: `$ cunicu daemon -u -x mysecretpass wg0`,
|
||||
Run: daemon,
|
||||
Example: `$ cunicu daemon -U -x mysecretpass wg0`,
|
||||
Run: daemonRun,
|
||||
ValidArgsFunction: cobra.NoFileCompletions,
|
||||
}
|
||||
|
||||
@@ -43,20 +43,22 @@ func init() {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := daemonCmd.MarkFlagFilename("config", "yaml", "json"); err != nil {
|
||||
if err := daemonCmd.MarkPersistentFlagFilename("config", "yaml", "json"); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
pf.VisitAll(func(f *pflag.Flag) {
|
||||
if f.Value.Type() == "bool" {
|
||||
daemonCmd.RegisterFlagCompletionFunc(f.Name, BooleanCompletions)
|
||||
if err := daemonCmd.RegisterFlagCompletionFunc(f.Name, BooleanCompletions); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
rootCmd.AddCommand(daemonCmd)
|
||||
}
|
||||
|
||||
func daemon(cmd *cobra.Command, args []string) {
|
||||
func daemonRun(cmd *cobra.Command, args []string) {
|
||||
io.WriteString(os.Stdout, Banner(color))
|
||||
|
||||
if err := cfg.Init(args); err != nil {
|
||||
@@ -76,7 +78,7 @@ func daemon(cmd *cobra.Command, args []string) {
|
||||
}
|
||||
|
||||
// Create daemon
|
||||
d, err := d.New(cfg)
|
||||
d, err := daemon.New(cfg)
|
||||
if err != nil {
|
||||
logger.Fatal("Failed to create daemon", zap.Error(err))
|
||||
}
|
||||
|
@@ -39,7 +39,10 @@ func init() {
|
||||
|
||||
func interfaceValidArg(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
// Establish RPC connection
|
||||
rpcConnect(cmd, args)
|
||||
if err := rpcConnect(cmd, args); err != nil {
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
|
||||
defer rpcDisconnect(cmd, args)
|
||||
|
||||
p := &rpcproto.GetStatusParams{}
|
||||
@@ -100,11 +103,15 @@ func invite(cmd *cobra.Command, args []string) {
|
||||
|
||||
if qrCode {
|
||||
buf := &bytes.Buffer{}
|
||||
cfg.Dump(buf)
|
||||
if err := cfg.Dump(buf); err != nil {
|
||||
logger.Fatal("Failed to dump config", zap.Error(err))
|
||||
}
|
||||
|
||||
terminal.QRCode(buf.String())
|
||||
} else {
|
||||
cfg.Dump(os.Stdout)
|
||||
if err := cfg.Dump(os.Stdout); err != nil {
|
||||
logger.Fatal("Failed to dump config", zap.Error(err))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -30,7 +30,7 @@ func init() {
|
||||
pf.VarP(&format, "format", "f", "Output `format` (one of: human, json)")
|
||||
pf.BoolVarP(&indent, "indent", "i", true, "Format and indent JSON ouput")
|
||||
|
||||
if err := daemonCmd.RegisterFlagCompletionFunc("format", cobra.FixedCompletions([]string{"human", "json"}, cobra.ShellCompDirectiveNoFileComp)); err != nil {
|
||||
if err := statusCmd.RegisterFlagCompletionFunc("format", cobra.FixedCompletions([]string{"human", "json"}, cobra.ShellCompDirectiveNoFileComp)); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -39,7 +39,9 @@ func init() {
|
||||
|
||||
func statusValidArgs(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
|
||||
// Establish RPC connection
|
||||
rpcConnect(cmd, args)
|
||||
if err := rpcConnect(cmd, args); err != nil {
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
defer rpcDisconnect(cmd, args)
|
||||
|
||||
p := &rpcproto.GetStatusParams{}
|
||||
|
@@ -48,7 +48,9 @@ func wgShowValidArgs(cmd *cobra.Command, args []string, toComplete string) ([]st
|
||||
if len(args) == 0 {
|
||||
comps = []string{"all", "interfaces"}
|
||||
|
||||
rpcConnect(cmd, args)
|
||||
if err := rpcConnect(cmd, args); err != nil {
|
||||
return nil, cobra.ShellCompDirectiveError
|
||||
}
|
||||
defer rpcDisconnect(cmd, args)
|
||||
|
||||
sts, err := rpcClient.GetStatus(context.Background(), &rpcproto.GetStatusParams{})
|
||||
|
@@ -7,13 +7,13 @@ sidebar_position: 99
|
||||
|
||||
There exist a suite of other peer-to-peer VPN solutions comparable to cunīcu:
|
||||
|
||||
- [Tinc-VPN](https://www.tinc-vpn.org/)
|
||||
- [weron](https://github.com/pojntfx/weron)
|
||||
- [Tailscale](https://tailscale.com/)
|
||||
- [Zerotier](https://www.zerotier.com/)
|
||||
- [netbird](https://netbird.io/) (formerly Wiretrustee)
|
||||
- [wg-dynamic](https://github.com/WireGuard/wg-dynamic/blob/master/docs/idea.md)
|
||||
- [Nebula](https://github.com/slackhq/nebula)
|
||||
- [Netmaker](https://www.netmaker.org/)
|
||||
- [Tinc-VPN](https://www.tinc-vpn.org/)
|
||||
- [weron](https://github.com/pojntfx/weron)
|
||||
- [Tailscale](https://tailscale.com/)
|
||||
- [Zerotier](https://www.zerotier.com/)
|
||||
- [netbird](https://netbird.io/) (formerly Wiretrustee)
|
||||
- [wg-dynamic](https://github.com/WireGuard/wg-dynamic/blob/master/docs/idea.md)
|
||||
- [Nebula](https://github.com/slackhq/nebula)
|
||||
- [Netmaker](https://www.netmaker.org/)
|
||||
|
||||
You might also want to have a look at [@HarvsG](https://github.com/HarvsG) [WireGuardMeshes](https://github.com/HarvsG/WireGuardMeshes) comparison.
|
@@ -108,4 +108,3 @@ sidebar_position: 20
|
||||
[rfc7064]: https://datatracker.ietf.org/doc/html/rfc7064
|
||||
|
||||
[rfc7065]: https://datatracker.ietf.org/doc/html/rfc7065
|
||||
|
||||
|
@@ -31,6 +31,6 @@ This addresses calculation can be performed with the [`cunicu addresses`](../usa
|
||||
|
||||
The following settings are automatically assigned if they have not been set before:
|
||||
|
||||
- **Private Key:** a new random private key will be generated.
|
||||
- **Listen port:** the next free port in the configured listen port range is used (see `wireguard.listen_port_range` setting).
|
||||
- **MTU:** is automatically determined from the endpoint addresses or the system default route.
|
||||
- **Private Key:** a new random private key will be generated.
|
||||
- **Listen port:** the next free port in the configured listen port range is used (see `wireguard.listen_port_range` setting).
|
||||
- **MTU:** is automatically determined from the endpoint addresses or the system default route.
|
||||
|
@@ -9,11 +9,11 @@ E.g. we can use cunīcu for the post-quantum safe exchange of pre-shared keys wi
|
||||
|
||||
Currently, the following features are implemented as separate modules:
|
||||
|
||||
- [Auto-configuration of missing interface settings and link-local IP addresses](./autocfg.md) (`autocfg`)
|
||||
- [Config Synchronization](./cfgsync.md) (`cfgsync`)
|
||||
- [Peer Discovery](./pdisc.md) (`pdisc`)
|
||||
- [Endpoint Discovery](./epdisc.md) (`epdisc`)
|
||||
- [Hooks](./hooks.md) (`hooks`)
|
||||
- [Hosts-file Synchronization](./hsync.md) (`hsync`)
|
||||
- [Pre-shared Key Establishment](./pske.md) (`pske`)
|
||||
- [Route Synchronization](./rtsync.md) (`rtsync`)
|
||||
- [Auto-configuration of missing interface settings and link-local IP addresses](./autocfg.md) (`autocfg`)
|
||||
- [Config Synchronization](./cfgsync.md) (`cfgsync`)
|
||||
- [Peer Discovery](./pdisc.md) (`pdisc`)
|
||||
- [Endpoint Discovery](./epdisc.md) (`epdisc`)
|
||||
- [Hooks](./hooks.md) (`hooks`)
|
||||
- [Hosts-file Synchronization](./hsync.md) (`hsync`)
|
||||
- [Pre-shared Key Establishment](./pske.md) (`pske`)
|
||||
- [Route Synchronization](./rtsync.md) (`rtsync`)
|
||||
|
@@ -7,7 +7,7 @@ title: Route Synchronization
|
||||
The route synchronization feature keeps the kernel routing table in sync with WireGuard's _AllowedIPs_ setting.
|
||||
|
||||
This synchronization is bi-directional:
|
||||
- Networks with are found in a Peers AllowedIP list will be installed as a kernel route.
|
||||
- Kernel routes with the peers link-local IP address as next-hop will be added to the Peers _AllowedIPs_ list.
|
||||
- Networks with are found in a Peers AllowedIP list will be installed as a kernel route.
|
||||
- Kernel routes with the peers link-local IP address as next-hop will be added to the Peers _AllowedIPs_ list.
|
||||
|
||||
This rather simple feature allows user to pair cunicu with a software routing daemon like [Bird2](https://bird.network.cz/) while using a single WireGuard interface with multiple peer-to-peer links.
|
||||
|
@@ -52,7 +52,7 @@ Once this has been done, the cunīcu logs should show a line `state=connected`.
|
||||
|
||||
## Authors
|
||||
|
||||
- Steffen Vogel ([@stv0g](https://github.com/stv0g), Institute for Automation of Complex Power Systems, RWTH Aachen University)
|
||||
- Steffen Vogel ([@stv0g](https://github.com/stv0g), Institute for Automation of Complex Power Systems, RWTH Aachen University)
|
||||
|
||||
## Join us
|
||||
|
||||
@@ -60,7 +60,7 @@ Please feel free to [join our Slack channel](https://join.slack.com/t/gophers/sh
|
||||
|
||||
## Name
|
||||
|
||||
The project name _cunīcu_ [kʊˈniːkʊ] is derived from the [latin noun cunīculus](https://en.wiktionary.org/wiki/cuniculus#Latin) which means rabbit, a rabbit burrow or underground tunnel. We have choosen it as a name for this project as _cunīcu_ builds tunnels between otherwise hard to reach network locations.
|
||||
The project name _cunīcu_ \[kʊˈniːkʊ\] is derived from the [latin noun cunīculus](https://en.wiktionary.org/wiki/cuniculus#Latin) which means rabbit, a rabbit burrow or underground tunnel. We have choosen it as a name for this project as _cunīcu_ builds tunnels between otherwise hard to reach network locations.
|
||||
It has been changed from the former name _wice_ in order to broaden the scope of the project and avoid any potential trademark violations.
|
||||
|
||||
## License
|
||||
|
@@ -13,24 +13,24 @@ import (
|
||||
"github.com/stv0g/cunicu/pkg/util/buildinfo"
|
||||
)
|
||||
|
||||
type remoteFileProvider struct {
|
||||
type RemoteFileProvider struct {
|
||||
url *url.URL
|
||||
etag string
|
||||
lastModified time.Time
|
||||
order []string
|
||||
}
|
||||
|
||||
func RemoteFileProvider(u *url.URL) *remoteFileProvider {
|
||||
return &remoteFileProvider{
|
||||
func NewRemoteFileProvider(u *url.URL) *RemoteFileProvider {
|
||||
return &RemoteFileProvider{
|
||||
url: u,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *remoteFileProvider) Read() (map[string]interface{}, error) {
|
||||
func (p *RemoteFileProvider) Read() (map[string]interface{}, error) {
|
||||
return nil, errors.New("this provider does not support parsers")
|
||||
}
|
||||
|
||||
func (p *remoteFileProvider) ReadBytes() ([]byte, error) {
|
||||
func (p *RemoteFileProvider) ReadBytes() ([]byte, error) {
|
||||
if p.url.Scheme != "https" {
|
||||
host, _, err := net.SplitHostPort(p.url.Host)
|
||||
if err != nil {
|
||||
@@ -81,12 +81,14 @@ func (p *remoteFileProvider) ReadBytes() ([]byte, error) {
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
func (p *remoteFileProvider) Order() []string {
|
||||
func (p *RemoteFileProvider) Order() []string {
|
||||
return p.order
|
||||
}
|
||||
|
||||
func (p *remoteFileProvider) Version() any {
|
||||
p.hasChanged()
|
||||
func (p *RemoteFileProvider) Version() any {
|
||||
if _, err := p.hasChanged(); err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if p.etag != "" {
|
||||
return p.etag
|
||||
@@ -99,7 +101,7 @@ func (p *remoteFileProvider) Version() any {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p *remoteFileProvider) hasChanged() (bool, error) {
|
||||
func (p *RemoteFileProvider) hasChanged() (bool, error) {
|
||||
client := &http.Client{
|
||||
Timeout: 5 * time.Second,
|
||||
}
|
||||
@@ -130,19 +132,19 @@ func (p *remoteFileProvider) hasChanged() (bool, error) {
|
||||
return resp.StatusCode == 200, nil
|
||||
}
|
||||
|
||||
type localFileProvider struct {
|
||||
type LocalFileProvider struct {
|
||||
*file.File
|
||||
|
||||
order []string
|
||||
}
|
||||
|
||||
func LocalFileProvider(u *url.URL) *localFileProvider {
|
||||
return &localFileProvider{
|
||||
func NewLocalFileProvider(u *url.URL) *LocalFileProvider {
|
||||
return &LocalFileProvider{
|
||||
File: file.Provider(u.Path),
|
||||
}
|
||||
}
|
||||
|
||||
func (p *localFileProvider) ReadBytes() ([]byte, error) {
|
||||
func (p *LocalFileProvider) ReadBytes() ([]byte, error) {
|
||||
buf, err := p.File.ReadBytes()
|
||||
|
||||
if err == nil {
|
||||
@@ -152,6 +154,6 @@ func (p *localFileProvider) ReadBytes() ([]byte, error) {
|
||||
return buf, err
|
||||
}
|
||||
|
||||
func (p *localFileProvider) Order() []string {
|
||||
func (p *LocalFileProvider) Order() []string {
|
||||
return p.order
|
||||
}
|
||||
|
@@ -94,7 +94,7 @@ func (p *lookupProvider) SubProviders() []koanf.Provider {
|
||||
if err != nil {
|
||||
p.logger.Warn("failed to parse URL for configuration file", zap.Error(err))
|
||||
} else {
|
||||
ps = append(ps, RemoteFileProvider(u))
|
||||
ps = append(ps, NewRemoteFileProvider(u))
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -83,7 +83,7 @@ type Provider struct {
|
||||
// - command line flags
|
||||
func (c *Config) GetProviders() ([]koanf.Provider, error) {
|
||||
ps := []koanf.Provider{
|
||||
StructsProvider(&DefaultSettings, "koanf"),
|
||||
NewStructsProvider(&DefaultSettings, "koanf"),
|
||||
WireGuardProvider(),
|
||||
}
|
||||
|
||||
@@ -97,12 +97,13 @@ func (c *Config) GetProviders() ([]koanf.Provider, error) {
|
||||
if len(c.Files) == 0 {
|
||||
searchPath := []string{"/etc", "/etc/cunicu"}
|
||||
|
||||
if cwd, err := os.Getwd(); err != nil {
|
||||
cwd, err := os.Getwd()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get working directory")
|
||||
} else {
|
||||
searchPath = append(searchPath, cwd)
|
||||
}
|
||||
|
||||
searchPath = append(searchPath, cwd)
|
||||
|
||||
if cfgDir := os.Getenv("CUNICU_CONFIG_DIR"); cfgDir != "" {
|
||||
searchPath = append(searchPath, cfgDir)
|
||||
}
|
||||
@@ -125,9 +126,9 @@ func (c *Config) GetProviders() ([]koanf.Provider, error) {
|
||||
var p koanf.Provider
|
||||
switch u.Scheme {
|
||||
case "http", "https":
|
||||
p = RemoteFileProvider(u)
|
||||
p = NewRemoteFileProvider(u)
|
||||
case "":
|
||||
p = LocalFileProvider(u)
|
||||
p = NewLocalFileProvider(u)
|
||||
default:
|
||||
return nil, fmt.Errorf("unsupported scheme '%s' for config file", u.Scheme)
|
||||
}
|
||||
@@ -138,7 +139,7 @@ func (c *Config) GetProviders() ([]koanf.Provider, error) {
|
||||
// Add a runtime configuration file if it exists
|
||||
if fi, err := os.Stat(RuntimeConfigFile); err == nil && !fi.IsDir() {
|
||||
ps = append(ps,
|
||||
LocalFileProvider(&url.URL{
|
||||
NewLocalFileProvider(&url.URL{
|
||||
Path: RuntimeConfigFile,
|
||||
}),
|
||||
)
|
||||
|
@@ -41,7 +41,7 @@ func (s *Source) Load() error {
|
||||
func load(p koanf.Provider) (*koanf.Koanf, []string, error) {
|
||||
var q koanf.Parser
|
||||
switch p.(type) {
|
||||
case *remoteFileProvider, *localFileProvider:
|
||||
case *RemoteFileProvider, *LocalFileProvider:
|
||||
q = yaml.Parser()
|
||||
default:
|
||||
q = nil
|
||||
@@ -68,15 +68,16 @@ func load(p koanf.Provider) (*koanf.Koanf, []string, error) {
|
||||
|
||||
if s, ok := p.(SubProvidable); ok {
|
||||
for _, p := range s.SubProviders() {
|
||||
if d, m, err := load(p); err != nil {
|
||||
d, m, err := load(p)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
} else {
|
||||
if err := k.Merge(d); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to merge config: %w", err)
|
||||
}
|
||||
|
||||
o = append(o, m...)
|
||||
}
|
||||
|
||||
if err := k.Merge(d); err != nil {
|
||||
return nil, nil, fmt.Errorf("failed to merge config: %w", err)
|
||||
}
|
||||
|
||||
o = append(o, m...)
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -4,24 +4,24 @@ import (
|
||||
"errors"
|
||||
)
|
||||
|
||||
type structsProvider struct {
|
||||
type StructsProvider struct {
|
||||
value any
|
||||
tag string
|
||||
}
|
||||
|
||||
// StructsProvider is very similar koanf's struct provider
|
||||
// but slightly adjusted to our needs.
|
||||
func StructsProvider(v any, t string) *structsProvider {
|
||||
return &structsProvider{
|
||||
func NewStructsProvider(v any, t string) *StructsProvider {
|
||||
return &StructsProvider{
|
||||
value: v,
|
||||
tag: t,
|
||||
}
|
||||
}
|
||||
|
||||
func (p *structsProvider) ReadBytes() ([]byte, error) {
|
||||
func (p *StructsProvider) ReadBytes() ([]byte, error) {
|
||||
return nil, errors.New("this provider requires no parser")
|
||||
}
|
||||
|
||||
func (p *structsProvider) Read() (map[string]any, error) {
|
||||
func (p *StructsProvider) Read() (map[string]any, error) {
|
||||
return Map(p.value, p.tag), nil
|
||||
}
|
||||
|
@@ -93,7 +93,9 @@ func (d *Daemon) Run() error {
|
||||
|
||||
go d.watcher.Watch()
|
||||
|
||||
d.watcher.Sync()
|
||||
if err := d.watcher.Sync(); err != nil {
|
||||
return fmt.Errorf("initial sync failed: %w", err)
|
||||
}
|
||||
|
||||
out:
|
||||
for {
|
||||
|
@@ -1,4 +1,3 @@
|
||||
// Package feat contains several sub-packages each implementing a dedicated feature.
|
||||
package daemon
|
||||
|
||||
import (
|
||||
|
@@ -194,7 +194,7 @@ func (e *Interface) PeerByPublicKey(pk crypto.Key) *Peer {
|
||||
// Endpoint returns the best guess about our own endpoint
|
||||
func (e *Interface) Endpoint() (*net.UDPAddr, error) {
|
||||
var ep *net.UDPAddr
|
||||
var bestPrio uint32 = 0
|
||||
var bestPrio uint32
|
||||
|
||||
for _, p := range e.Peers {
|
||||
cs, err := p.agent.GetLocalCandidates()
|
||||
|
@@ -400,14 +400,17 @@ func (p *Peer) Marshal() *protoepdisc.Peer {
|
||||
}
|
||||
|
||||
for _, cps := range p.agent.GetCandidatePairsStats() {
|
||||
cps := cps
|
||||
q.CandidatePairStats = append(q.CandidatePairStats, protoepdisc.NewCandidatePairStats(&cps))
|
||||
}
|
||||
|
||||
for _, cs := range p.agent.GetLocalCandidatesStats() {
|
||||
cs := cs
|
||||
q.LocalCandidateStats = append(q.LocalCandidateStats, protoepdisc.NewCandidateStats(&cs))
|
||||
}
|
||||
|
||||
for _, cs := range p.agent.GetRemoteCandidatesStats() {
|
||||
cs := cs
|
||||
q.RemoteCandidateStats = append(q.RemoteCandidateStats, protoepdisc.NewCandidateStats(&cs))
|
||||
}
|
||||
}
|
||||
@@ -429,16 +432,16 @@ func (p *Peer) Reachability() protoepdisc.Reachability {
|
||||
case ice.CandidateTypeServerReflexive:
|
||||
if cp.Remote.NetworkType().IsTCP() {
|
||||
return protoepdisc.Reachability_DIRECT_TCP
|
||||
} else {
|
||||
return protoepdisc.Reachability_DIRECT_UDP
|
||||
}
|
||||
|
||||
return protoepdisc.Reachability_DIRECT_UDP
|
||||
|
||||
case ice.CandidateTypeRelay:
|
||||
if cp.Remote.NetworkType().IsTCP() {
|
||||
return protoepdisc.Reachability_RELAY_TCP
|
||||
} else {
|
||||
return protoepdisc.Reachability_RELAY_UDP
|
||||
}
|
||||
|
||||
return protoepdisc.Reachability_RELAY_UDP
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -104,6 +104,8 @@ func (pd *Interface) sendPeerDescription(chg pdiscproto.PeerDescriptionChange, p
|
||||
|
||||
// Static addresses
|
||||
for _, addr := range pd.Settings.Addresses {
|
||||
addr := addr
|
||||
|
||||
_, bits := addr.Mask.Size()
|
||||
addr.Mask = net.CIDRMask(bits, bits)
|
||||
|
||||
@@ -112,6 +114,8 @@ func (pd *Interface) sendPeerDescription(chg pdiscproto.PeerDescriptionChange, p
|
||||
|
||||
// Auto-generated prefixes
|
||||
for _, pfx := range pd.Settings.Prefixes {
|
||||
pfx := pfx
|
||||
|
||||
addr := pk.IPAddress(pfx)
|
||||
|
||||
_, bits := addr.Mask.Size()
|
||||
|
@@ -25,7 +25,10 @@ func (rs *Interface) OnPeerAdded(p *core.Peer) {
|
||||
rs.gwMap[gw] = p
|
||||
}
|
||||
|
||||
rs.syncKernel() // Initial sync
|
||||
// Initial sync
|
||||
if err := rs.syncKernel(); err != nil {
|
||||
rs.logger.Error("Failed to synchronize kernel routing table", zap.Error(err))
|
||||
}
|
||||
|
||||
p.OnModified(rs)
|
||||
}
|
||||
|
@@ -65,7 +65,7 @@ func (p *Peer) Dump(wr io.Writer, verbosity int) error {
|
||||
}
|
||||
|
||||
if p.SelectedCandidatePair != nil {
|
||||
if _, err := terminal.FprintKV(wr, "candidate-pair", p.SelectedCandidatePair.ToString()); err != nil {
|
||||
if _, err := terminal.FprintKV(wr, "candidate pair", p.SelectedCandidatePair.ToString()); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
@@ -84,7 +84,7 @@ func (s *EndpointDiscoveryServer) RestartPeer(ctx context.Context, params *rpcpr
|
||||
}
|
||||
|
||||
func (s *EndpointDiscoveryServer) SendConnectionStates(stream rpcproto.Daemon_StreamEventsServer) {
|
||||
s.daemon.ForEachInterface(func(di *daemon.Interface) error {
|
||||
if err := s.daemon.ForEachInterface(func(di *daemon.Interface) error {
|
||||
i := s.Interface(di)
|
||||
|
||||
for _, p := range i.Peers {
|
||||
@@ -102,12 +102,14 @@ func (s *EndpointDiscoveryServer) SendConnectionStates(stream rpcproto.Daemon_St
|
||||
if err := stream.Send(e); err == io.EOF {
|
||||
continue
|
||||
} else if err != nil {
|
||||
s.logger.Error("Failed to send", zap.Error(err))
|
||||
s.logger.Error("Failed to send connection states", zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}); err != nil {
|
||||
s.logger.Error("Failed to send connection states", zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
func (s *EndpointDiscoveryServer) OnConnectionStateChange(p *epdisc.Peer, new, prev icex.ConnectionState) {
|
||||
|
@@ -14,7 +14,7 @@ function request() {
|
||||
}
|
||||
|
||||
function undraft_release() {
|
||||
request releases/$1 -X PATCH -d '{ "draft": false }' | \
|
||||
request "releases/$1" -X PATCH -d '{ "draft": false }' | \
|
||||
jq .
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ function download_asset() {
|
||||
|
||||
curl --silent \
|
||||
--location \
|
||||
--output ${ASSET_NAME} \
|
||||
--output "${ASSET_NAME}" \
|
||||
--header "Authorization: Bearer ${GITHUB_TOKEN}" \
|
||||
--header "Accept:application/octet-stream" \
|
||||
"https://api.github.com/repos/${REPO}/releases/assets/${ASSET_ID}"
|
||||
@@ -37,7 +37,7 @@ function download_asset() {
|
||||
function upload_asset() {
|
||||
RELEASE_ID=$1
|
||||
FILENAME=$2
|
||||
MIME_TYPE=$(file -b --mime-type ${FILENAME})
|
||||
MIME_TYPE=$(file -b --mime-type "${FILENAME}")
|
||||
|
||||
curl --silent \
|
||||
--location \
|
||||
@@ -45,7 +45,7 @@ function upload_asset() {
|
||||
--header "Content-Type: ${MIME_TYPE}" \
|
||||
--header "Accept: application/vnd.github+json" \
|
||||
--header "Authorization: Bearer ${GITHUB_TOKEN}" \
|
||||
--data-binary @${FILENAME} \
|
||||
--data-binary "@${FILENAME}" \
|
||||
"https://uploads.github.com/repos/${REPO}/releases/${RELEASE_ID}/assets?name=${FILENAME}" | \
|
||||
jq .
|
||||
}
|
||||
|
@@ -2,39 +2,39 @@
|
||||
|
||||
This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
|
||||
|
||||
### Installation
|
||||
## Installation
|
||||
|
||||
```
|
||||
```bash
|
||||
$ yarn
|
||||
```
|
||||
|
||||
### Local Development
|
||||
## Local Development
|
||||
|
||||
```
|
||||
```bash
|
||||
$ yarn start
|
||||
```
|
||||
|
||||
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
|
||||
|
||||
### Build
|
||||
## Build
|
||||
|
||||
```
|
||||
```bash
|
||||
$ yarn build
|
||||
```
|
||||
|
||||
This command generates static content into the `build` directory and can be served using any static contents hosting service.
|
||||
|
||||
### Deployment
|
||||
## Deployment
|
||||
|
||||
Using SSH:
|
||||
|
||||
```
|
||||
```bash
|
||||
$ USE_SSH=true yarn deploy
|
||||
```
|
||||
|
||||
Not using SSH:
|
||||
|
||||
```
|
||||
```bash
|
||||
$ GIT_USER=<Your GitHub username> yarn deploy
|
||||
```
|
||||
|
||||
|
@@ -23,7 +23,7 @@ The project has now its dedicated [website](https://cunicu.li), [GitHub organiza
|
||||
Feel free to follow us there for updates!
|
||||
|
||||
You might also have realized that the project name has changed. We decided to rebrand from the previous name _wice_ to avoid any potential trademark issues with the WireGuard project as well as another small German company named _WICE_.
|
||||
The project name _cunīcu_ [kʊˈniːkʊ] is derived from the [latin noun cunīculus](https://en.wiktionary.org/wiki/cuniculus#Latin) which means rabbit, a rabbit burrow or underground tunnel. We have choosen it as a name for this project as _cunīcu_ builds tunnels between otherwise hard to reach network locations.
|
||||
The project name _cunīcu_ \[kʊˈniːkʊ\] is derived from the [latin noun cunīculus](https://en.wiktionary.org/wiki/cuniculus#Latin) which means rabbit, a rabbit burrow or underground tunnel. We have choosen it as a name for this project as _cunīcu_ builds tunnels between otherwise hard to reach network locations.
|
||||
|
||||
This also gave us the opportunity to redesign the logo which you find further down in the sticker design.
|
||||
|
||||
|
Reference in New Issue
Block a user