aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorJason A. Donenfeld <Jason@zx2c4.com>2020-11-21 22:24:55 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2020-11-22 22:00:32 +0100
commit602b5b2180c7bdb63f1c0aef47def0c92b9e1499 (patch)
treec3ef789b4e9868bd197f8a0584cd0a3acbc6b79b
parenttunnel: enable {Pre,Post}{Up,Down} scripts gated behind admin knob (diff)
downloadwireguard-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.md13
-rw-r--r--manager/ipc_server.go51
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.