Fix concurrency on the client (#183)

* reworked peer connection establishment logic eliminating race conditions and deadlocks while running many peers
This commit is contained in:
Mikhail Bragin
2022-01-10 18:43:13 +01:00
committed by GitHub
parent 828410b34c
commit 319632ffe8
25 changed files with 1216 additions and 898 deletions

View File

@@ -17,8 +17,6 @@ const (
var (
tunIface tun.Device
// todo check after move the WgPort constant to the client
WgPort = 51820
)
// CreateWithUserspace Creates a new Wireguard interface, using wireguard-go userspace implementation
@@ -103,7 +101,7 @@ func Exists(iface string) (*bool, error) {
// Configure configures a Wireguard interface
// The interface must exist before calling this method (e.g. call interface.Create() before)
func Configure(iface string, privateKey string) error {
func Configure(iface string, privateKey string, port int) error {
log.Debugf("configuring Wireguard interface %s", iface)
@@ -113,12 +111,11 @@ func Configure(iface string, privateKey string) error {
return err
}
fwmark := 0
p := WgPort
config := wgtypes.Config{
PrivateKey: &key,
ReplacePeers: false,
FirewallMark: &fwmark,
ListenPort: &p,
ListenPort: &port,
}
return configureDevice(iface, config)
@@ -235,7 +232,7 @@ func RemovePeer(iface string, peerKey string) error {
return configureDevice(iface, config)
}
// Closes the User Space tunnel interface
// CloseWithUserspace closes the User Space tunnel interface
func CloseWithUserspace() error {
return tunIface.Close()
}

View File

@@ -40,7 +40,7 @@ func addRoute(iface string, ipNet *net.IPNet) error {
}
// Closes the tunnel interface
func Close() error {
func Close(iFace string) error {
name, err := tunIface.Name()
if err != nil {
return err

View File

@@ -1,10 +1,8 @@
package iface
import (
"fmt"
log "github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
"golang.zx2c4.com/wireguard/wgctrl"
"os"
)
@@ -131,34 +129,14 @@ func (w *wgLink) Type() string {
return "wireguard"
}
// Closes the tunnel interface
func Close() error {
// Close closes the tunnel interface
func Close(iFace string) error {
if tunIface != nil {
return CloseWithUserspace()
} else {
var iface = ""
wg, err := wgctrl.New()
if err != nil {
return err
}
defer wg.Close()
devList, err := wg.Devices()
if err != nil {
return err
}
for _, wgDev := range devList {
// todo check after move the WgPort constant to the client
if wgDev.ListenPort == WgPort {
iface = wgDev.Name
break
}
}
if iface == "" {
return fmt.Errorf("Wireguard Interface not found")
}
attrs := netlink.NewLinkAttrs()
attrs.Name = iface
attrs.Name = iFace
link := wgLink{
attrs: &attrs,

View File

@@ -14,6 +14,7 @@ import (
const (
key = "0PMI6OkB5JmB+Jj/iWWHekuQRx+bipZirWCWKFXexHc="
peerPubKey = "Ok0mC0qlJyXEPKh2UFIpsI2jG0L7LRpC3sLAusSJ5CQ="
WgPort = 51820
)
func init() {
@@ -29,7 +30,7 @@ func Test_CreateInterface(t *testing.T) {
t.Fatal(err)
}
defer func() {
err = Close()
err = Close(ifaceName)
if err != nil {
t.Error(err)
}
@@ -44,13 +45,6 @@ func Test_CreateInterface(t *testing.T) {
t.Error(err)
}
}()
d, err := wg.Device(ifaceName)
if err != nil {
t.Fatal(err)
}
// todo move the WgPort constant to the client
WgPort = d.ListenPort
}
func Test_ConfigureInterface(t *testing.T) {
ifaceName := "utun1000"
@@ -60,13 +54,13 @@ func Test_ConfigureInterface(t *testing.T) {
t.Fatal(err)
}
defer func() {
err = Close()
err = Close(ifaceName)
if err != nil {
t.Error(err)
}
}()
err = Configure(ifaceName, key)
err = Configure(ifaceName, key, WgPort)
if err != nil {
t.Fatal(err)
}
@@ -99,12 +93,12 @@ func Test_UpdatePeer(t *testing.T) {
t.Fatal(err)
}
defer func() {
err = Close()
err = Close(ifaceName)
if err != nil {
t.Error(err)
}
}()
err = Configure(ifaceName, key)
err = Configure(ifaceName, key, WgPort)
if err != nil {
t.Fatal(err)
}
@@ -151,12 +145,12 @@ func Test_UpdatePeerEndpoint(t *testing.T) {
t.Fatal(err)
}
defer func() {
err = Close()
err = Close(ifaceName)
if err != nil {
t.Error(err)
}
}()
err = Configure(ifaceName, key)
err = Configure(ifaceName, key, WgPort)
if err != nil {
t.Fatal(err)
}
@@ -192,12 +186,12 @@ func Test_RemovePeer(t *testing.T) {
t.Fatal(err)
}
defer func() {
err = Close()
err = Close(ifaceName)
if err != nil {
t.Error(err)
}
}()
err = Configure(ifaceName, key)
err = Configure(ifaceName, key, WgPort)
if err != nil {
t.Fatal(err)
}
@@ -235,13 +229,7 @@ func Test_Close(t *testing.T) {
}
}()
d, err := wg.Device(ifaceName)
if err != nil {
t.Fatal(err)
}
// todo move the WgPort constant to the client
WgPort = d.ListenPort
err = Close()
err = Close(ifaceName)
if err != nil {
t.Fatal(err)
}

View File

@@ -41,6 +41,6 @@ func getUAPI(iface string) (net.Listener, error) {
}
// Closes the tunnel interface
func Close() error {
func Close(iFace string) error {
return CloseWithUserspace()
}