udp_bypass_windows.go 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. //go:build (amd64 || arm64) && !e2e_testing
  2. // +build amd64 arm64
  3. // +build !e2e_testing
  4. package udp
  5. import (
  6. "log/slog"
  7. "sync"
  8. "github.com/slackhq/nebula/config"
  9. "github.com/slackhq/nebula/wfp"
  10. )
  11. // wrapWithWDFBypass wraps a Conn so that the first ReloadConfig consults listen.windows_bypass_wdf
  12. // and installs a WFP PERMIT filter for the listener's bound UDP port. The session is released when Close runs.
  13. func wrapWithWDFBypass(l *slog.Logger, conn Conn) Conn {
  14. return &bypassConn{Conn: conn, l: l}
  15. }
  16. type bypassConn struct {
  17. Conn
  18. l *slog.Logger
  19. installOnce sync.Once
  20. session *wfp.Session
  21. }
  22. func (b *bypassConn) ReloadConfig(c *config.C, r *config.Reload) {
  23. // Only read on the first call, at startup
  24. r.RestartRequiredIfChanged("listen.windows_bypass_wdf")
  25. b.installOnce.Do(func() {
  26. if !c.GetBool("listen.windows_bypass_wdf", true) {
  27. return
  28. }
  29. addr, err := b.Conn.LocalAddr()
  30. if err != nil {
  31. b.l.Warn("Failed to query listener port for WFP bypass", "error", err)
  32. return
  33. }
  34. s, err := wfp.PermitUDPPort(addr.Port())
  35. if err != nil {
  36. b.l.Warn("Failed to install WFP bypass filters for listener", "error", err)
  37. return
  38. }
  39. b.l.Info("Installed WFP filters bypassing Windows Defender Firewall on UDP listener port",
  40. "port", addr.Port())
  41. b.session = s
  42. })
  43. b.Conn.ReloadConfig(c, r)
  44. }
  45. func (b *bypassConn) Close() error {
  46. if b.session != nil {
  47. b.session.Close()
  48. b.session = nil
  49. }
  50. return b.Conn.Close()
  51. }