|
@@ -3,7 +3,9 @@ package nebula
|
|
import (
|
|
import (
|
|
"context"
|
|
"context"
|
|
"errors"
|
|
"errors"
|
|
|
|
+ "fmt"
|
|
"io"
|
|
"io"
|
|
|
|
+ "net"
|
|
"os"
|
|
"os"
|
|
"runtime"
|
|
"runtime"
|
|
"sync/atomic"
|
|
"sync/atomic"
|
|
@@ -68,6 +70,8 @@ type Interface struct {
|
|
closed int32
|
|
closed int32
|
|
relayManager *relayManager
|
|
relayManager *relayManager
|
|
|
|
|
|
|
|
+ sendRecvErrorConfig sendRecvErrorConfig
|
|
|
|
+
|
|
// rebindCount is used to decide if an active tunnel should trigger a punch notification through a lighthouse
|
|
// rebindCount is used to decide if an active tunnel should trigger a punch notification through a lighthouse
|
|
rebindCount int8
|
|
rebindCount int8
|
|
version string
|
|
version string
|
|
@@ -84,6 +88,40 @@ type Interface struct {
|
|
l *logrus.Logger
|
|
l *logrus.Logger
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+type sendRecvErrorConfig uint8
|
|
|
|
+
|
|
|
|
+const (
|
|
|
|
+ sendRecvErrorAlways sendRecvErrorConfig = iota
|
|
|
|
+ sendRecvErrorNever
|
|
|
|
+ sendRecvErrorPrivate
|
|
|
|
+)
|
|
|
|
+
|
|
|
|
+func (s sendRecvErrorConfig) ShouldSendRecvError(ip net.IP) bool {
|
|
|
|
+ switch s {
|
|
|
|
+ case sendRecvErrorPrivate:
|
|
|
|
+ return ip.IsPrivate()
|
|
|
|
+ case sendRecvErrorAlways:
|
|
|
|
+ return true
|
|
|
|
+ case sendRecvErrorNever:
|
|
|
|
+ return false
|
|
|
|
+ default:
|
|
|
|
+ panic(fmt.Errorf("invalid sendRecvErrorConfig value: %d", s))
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
+func (s sendRecvErrorConfig) String() string {
|
|
|
|
+ switch s {
|
|
|
|
+ case sendRecvErrorAlways:
|
|
|
|
+ return "always"
|
|
|
|
+ case sendRecvErrorNever:
|
|
|
|
+ return "never"
|
|
|
|
+ case sendRecvErrorPrivate:
|
|
|
|
+ return "private"
|
|
|
|
+ default:
|
|
|
|
+ return fmt.Sprintf("invalid(%d)", s)
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
func NewInterface(ctx context.Context, c *InterfaceConfig) (*Interface, error) {
|
|
func NewInterface(ctx context.Context, c *InterfaceConfig) (*Interface, error) {
|
|
if c.Outside == nil {
|
|
if c.Outside == nil {
|
|
return nil, errors.New("no outside connection")
|
|
return nil, errors.New("no outside connection")
|
|
@@ -232,6 +270,7 @@ func (f *Interface) RegisterConfigChangeCallbacks(c *config.C) {
|
|
c.RegisterReloadCallback(f.reloadCA)
|
|
c.RegisterReloadCallback(f.reloadCA)
|
|
c.RegisterReloadCallback(f.reloadCertKey)
|
|
c.RegisterReloadCallback(f.reloadCertKey)
|
|
c.RegisterReloadCallback(f.reloadFirewall)
|
|
c.RegisterReloadCallback(f.reloadFirewall)
|
|
|
|
+ c.RegisterReloadCallback(f.reloadSendRecvError)
|
|
for _, udpConn := range f.writers {
|
|
for _, udpConn := range f.writers {
|
|
c.RegisterReloadCallback(udpConn.ReloadConfig)
|
|
c.RegisterReloadCallback(udpConn.ReloadConfig)
|
|
}
|
|
}
|
|
@@ -309,6 +348,30 @@ func (f *Interface) reloadFirewall(c *config.C) {
|
|
Info("New firewall has been installed")
|
|
Info("New firewall has been installed")
|
|
}
|
|
}
|
|
|
|
|
|
|
|
+func (f *Interface) reloadSendRecvError(c *config.C) {
|
|
|
|
+ if c.InitialLoad() || c.HasChanged("listen.send_recv_error") {
|
|
|
|
+ stringValue := c.GetString("listen.send_recv_error", "always")
|
|
|
|
+
|
|
|
|
+ switch stringValue {
|
|
|
|
+ case "always":
|
|
|
|
+ f.sendRecvErrorConfig = sendRecvErrorAlways
|
|
|
|
+ case "never":
|
|
|
|
+ f.sendRecvErrorConfig = sendRecvErrorNever
|
|
|
|
+ case "private":
|
|
|
|
+ f.sendRecvErrorConfig = sendRecvErrorPrivate
|
|
|
|
+ default:
|
|
|
|
+ if c.GetBool("listen.send_recv_error", true) {
|
|
|
|
+ f.sendRecvErrorConfig = sendRecvErrorAlways
|
|
|
|
+ } else {
|
|
|
|
+ f.sendRecvErrorConfig = sendRecvErrorNever
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ f.l.WithField("sendRecvError", f.sendRecvErrorConfig.String()).
|
|
|
|
+ Info("Loaded send_recv_error config")
|
|
|
|
+ }
|
|
|
|
+}
|
|
|
|
+
|
|
func (f *Interface) emitStats(ctx context.Context, i time.Duration) {
|
|
func (f *Interface) emitStats(ctx context.Context, i time.Duration) {
|
|
ticker := time.NewTicker(i)
|
|
ticker := time.NewTicker(i)
|
|
defer ticker.Stop()
|
|
defer ticker.Stop()
|