diff options
author | Jason A. Donenfeld <Jason@zx2c4.com> | 2020-11-21 22:24:55 +0100 |
---|---|---|
committer | Jason A. Donenfeld <Jason@zx2c4.com> | 2020-11-22 22:00:32 +0100 |
commit | 602b5b2180c7bdb63f1c0aef47def0c92b9e1499 (patch) | |
tree | c3ef789b4e9868bd197f8a0584cd0a3acbc6b79b | |
parent | tunnel: enable {Pre,Post}{Up,Down} scripts gated behind admin knob (diff) | |
download | wireguard-windows-602b5b2180c7bdb63f1c0aef47def0c92b9e1499.tar.xz wireguard-windows-602b5b2180c7bdb63f1c0aef47def0c92b9e1499.zip |
manager: allow multiple tunnels if admin knob allows it
Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
-rw-r--r-- | adminregistry.md | 13 | ||||
-rw-r--r-- | manager/ipc_server.go | 51 |
2 files changed, 39 insertions, 25 deletions
diff --git a/adminregistry.md b/adminregistry.md index 1f4c8d44..8d7bc105 100644 --- a/adminregistry.md +++ b/adminregistry.md @@ -2,7 +2,8 @@ These are advanced configuration knobs that admins can set to do unusual things that are not recommended. There is no UI to enable these, and no such thing is -planned. Use at your own risk, and please make sure you know what you're doing. +planned. These registry keys may also be removed at some point in the future. +Use at your own risk, and please make sure you know what you're doing. #### `HKLM\Software\WireGuard\LimitedOperatorUI` @@ -25,3 +26,13 @@ tunnel configuration. Note that this execution is done as the Local System user, which runs with the highest permissions on the operating system, and is therefore a real target of malware. Therefore, you should enable this option only with the utmost trepidation. + +#### `HKLM\Software\WireGuard\MultipleSimultaneousTunnels` + +When this key is set to `DWORD(1)`, the UI may start multiple tunnels at the +same time; otherwise, an existing tunnel is stopped when a new one is started. +Note that it is always possible, regardless of this key, to start multiple +tunnels using `wireguard /installtunnelservice`; this controls only the semantics +of tunnel start requests coming from the UI. If all goes well, this key will be +removed and the logic of whether to stop existing tunnels will be based on +overlapping routes, but for now, this key provides a manual override. diff --git a/manager/ipc_server.go b/manager/ipc_server.go index bd495b1e..21018f45 100644 --- a/manager/ipc_server.go +++ b/manager/ipc_server.go @@ -88,34 +88,37 @@ func (s *ManagerService) RuntimeConfig(tunnelName string) (*conf.Config, error) } func (s *ManagerService) Start(tunnelName string) error { - // For now, enforce only one tunnel at a time. Later we'll remove this silly restriction. - trackedTunnelsLock.Lock() - tt := make([]string, 0, len(trackedTunnels)) - var inTransition string - for t, state := range trackedTunnels { - tt = append(tt, t) - if len(t) > 0 && (state == TunnelStarting || state == TunnelUnknown) { - inTransition = t - break + // TODO: Rather than being lazy and gating this behind a knob (yuck!), we should instead keep track of the routes + // of each tunnel, and only deactivate in the case of a tunnel with identical routes being added. + if !conf.AdminBool("MultipleSimultaneousTunnels") { + trackedTunnelsLock.Lock() + tt := make([]string, 0, len(trackedTunnels)) + var inTransition string + for t, state := range trackedTunnels { + tt = append(tt, t) + if len(t) > 0 && (state == TunnelStarting || state == TunnelUnknown) { + inTransition = t + break + } } - } - trackedTunnelsLock.Unlock() - if len(inTransition) != 0 { - return fmt.Errorf("Please allow the tunnel ā%sā to finish activating", inTransition) - } - go func() { - for _, t := range tt { - s.Stop(t) + trackedTunnelsLock.Unlock() + if len(inTransition) != 0 { + return fmt.Errorf("Please allow the tunnel ā%sā to finish activating", inTransition) } - for _, t := range tt { - state, err := s.State(t) - if err == nil && (state == TunnelStarted || state == TunnelStarting) { - log.Printf("[%s] Trying again to stop zombie tunnel", t) + go func() { + for _, t := range tt { s.Stop(t) - time.Sleep(time.Millisecond * 100) } - } - }() + for _, t := range tt { + state, err := s.State(t) + if err == nil && (state == TunnelStarted || state == TunnelStarting) { + log.Printf("[%s] Trying again to stop zombie tunnel", t) + s.Stop(t) + time.Sleep(time.Millisecond * 100) + } + } + }() + } time.AfterFunc(time.Second*10, cleanupStaleWintunInterfaces) // After that process is started -- it's somewhat asynchronous -- we install the new one. |