github.com/mysteriumnetwork/node@v0.0.0-20240516044423-365054f76801/services/wireguard/endpoint/userspace/client.go (about) 1 /* 2 * Copyright (C) 2018 The "MysteriumNetwork/node" Authors. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 */ 17 18 package userspace 19 20 import ( 21 "bufio" 22 "fmt" 23 "strings" 24 25 "github.com/pkg/errors" 26 "golang.zx2c4.com/wireguard/conn" 27 "golang.zx2c4.com/wireguard/device" 28 "golang.zx2c4.com/wireguard/tun" 29 30 "github.com/mysteriumnetwork/node/services/wireguard/connection/dns" 31 "github.com/mysteriumnetwork/node/services/wireguard/wgcfg" 32 "github.com/mysteriumnetwork/node/utils/actionstack" 33 "github.com/mysteriumnetwork/node/utils/netutil" 34 ) 35 36 type client struct { 37 tun tun.Device 38 devAPI *device.Device 39 dnsManager dns.Manager 40 } 41 42 // NewWireguardClient creates new wireguard user space client. 43 func NewWireguardClient() (*client, error) { 44 return &client{ 45 dnsManager: dns.NewManager(), 46 }, nil 47 } 48 49 func (c *client) ConfigureDevice(config wgcfg.DeviceConfig) (err error) { 50 rollback := actionstack.NewActionStack() 51 if c.tun, err = CreateTUN(config.IfaceName, config.Subnet); err != nil { 52 return errors.Wrap(err, "failed to create TUN device") 53 } 54 55 devAPI := device.NewDevice(c.tun, conn.NewDefaultBind(), device.NewLogger(device.LogLevelVerbose, "[userspace-wg]")) 56 c.devAPI = devAPI 57 rollback.Push(func() { 58 devAPI.Close() 59 c.devAPI = nil 60 }) 61 62 if err := c.configureDevice(config); err != nil { 63 rollback.Run() 64 return err 65 } 66 67 if config.Peer.Endpoint != nil { 68 if err := netutil.AddDefaultRoute(config.IfaceName); err != nil { 69 rollback.Run() 70 return fmt.Errorf("could not add default route for %s: %w", config.IfaceName, err) 71 } 72 } 73 74 return nil 75 } 76 77 func (c *client) ReConfigureDevice(config wgcfg.DeviceConfig) (err error) { 78 if err = netutil.AssignIP(config.IfaceName, config.Subnet); err != nil { 79 return fmt.Errorf("failed to assign IP address: %w", err) 80 } 81 82 return c.configureDevice(config) 83 } 84 85 func (c *client) configureDevice(config wgcfg.DeviceConfig) (err error) { 86 if err := c.setDeviceConfig(config.Encode()); err != nil { 87 return errors.Wrap(err, "failed to configure initial device") 88 } 89 90 c.devAPI.Up() 91 92 if err := c.dnsManager.Set(dns.Config{ 93 ScriptDir: config.DNSScriptDir, 94 IfaceName: config.IfaceName, 95 DNS: config.DNS, 96 }); err != nil { 97 return fmt.Errorf("could not set DNS: %w", err) 98 } 99 100 return nil 101 } 102 103 func (c *client) Close() error { 104 c.devAPI.Close() // c.devAPI.Close() closes c.tun too 105 if err := c.dnsManager.Clean(); err != nil { 106 return fmt.Errorf("could not clean DNS: %w", err) 107 } 108 return nil 109 } 110 111 func (c *client) PeerStats(string) (wgcfg.Stats, error) { 112 deviceState, err := ParseUserspaceDevice(c.devAPI.IpcGetOperation) 113 if err != nil { 114 return wgcfg.Stats{}, err 115 } 116 stats, err := ParseDevicePeerStats(deviceState) 117 if err != nil { 118 return wgcfg.Stats{}, err 119 } 120 return stats, nil 121 } 122 123 func (c *client) DestroyDevice(name string) error { 124 return destroyDevice(name) 125 } 126 127 func (c *client) setDeviceConfig(config string) error { 128 if err := c.devAPI.IpcSetOperation(bufio.NewReader(strings.NewReader(config))); err != nil { 129 return errors.Wrap(err, "failed to set device config") 130 } 131 return nil 132 }