Skip to content

Commit

Permalink
Use upstream WireGuard (#1480)
Browse files Browse the repository at this point in the history
Use upstream https://github.com/WireGuard/wireguard-go and add needed changed to support it. Wireguard uses simple key value based configuration protocol which only supports passing it as a string.
  • Loading branch information
anjmao authored Jan 3, 2020
1 parent d1f5289 commit faf2e82
Show file tree
Hide file tree
Showing 15 changed files with 858 additions and 192 deletions.
2 changes: 0 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ module github.com/mysteriumnetwork/node

go 1.13

replace golang.zx2c4.com/wireguard => github.com/mysteriumnetwork/wireguard-go v0.0.0-20191114114228-1a3c4386eb23

require (
github.com/BurntSushi/toml v0.3.1
github.com/DataDog/zstd v1.4.1 // indirect
Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -438,8 +438,6 @@ github.com/mysteriumnetwork/metrics v0.0.0-20191002053948-084a00d6c6b2 h1:+MzoNo
github.com/mysteriumnetwork/metrics v0.0.0-20191002053948-084a00d6c6b2/go.mod h1:QI+154TA1KKdrSYAWpr50FP6AzHsbT3wJvFD5kSEQVE=
github.com/mysteriumnetwork/payments v0.0.11-0.20191120103343-ed922e3051db h1:OfCcf9GtFBAhTmet4yTnuF0ktdFBmPMq+kbgSUEEQHo=
github.com/mysteriumnetwork/payments v0.0.11-0.20191120103343-ed922e3051db/go.mod h1:khz9e+0ipI8uVAEBhTdSrvo5ByYcdkWtioqkj14Pf7Q=
github.com/mysteriumnetwork/wireguard-go v0.0.0-20191114114228-1a3c4386eb23 h1:fJGV0dFrt4+7d3y4e50xoRVOuZygnxkUhBeMXAfBlkI=
github.com/mysteriumnetwork/wireguard-go v0.0.0-20191114114228-1a3c4386eb23/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4=
github.com/nats-io/gnatsd v1.4.1 h1:RconcfDeWpKCD6QIIwiVFcvForlXpWeJP7i5/lDLy44=
github.com/nats-io/gnatsd v1.4.1/go.mod h1:nqco77VO78hLCJpIcVfygDP2rPGfsEHkGTUk94uh5DQ=
github.com/nats-io/go-nats v1.4.0 h1:HorYtzWLSxkmcEzAFmY6vJ20lFfeAPbrnkoAYgk8GSg=
Expand Down Expand Up @@ -751,6 +749,8 @@ golang.org/x/tools v0.0.0-20190911022129-16c5e0f7d110/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20190916130336-e45ffcd953cc h1:+GB9/q0gCzmtaIl6WdoJFMS3lPwrR6rpcMyY6jfQHAw=
golang.org/x/tools v0.0.0-20190916130336-e45ffcd953cc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wireguard v0.0.20191012 h1:sdX+y3hrHkW8KJkjY7ZgzpT5Tqo8XnBkH55U1klphko=
golang.zx2c4.com/wireguard v0.0.20191012/go.mod h1:P2HsVp8SKwZEufsnezXZA4GRX/T49/HlU7DGuelXsU4=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20190515223858-5ec88494b814 h1:uNqb91RyXmeqAhh0vWc9583TQ0OaT3dvPxGxd3z/8iU=
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20190515223858-5ec88494b814/go.mod h1:eJQAcrbllkYZEGZuBNQx0NsUz9y7j01OG3bgxUev834=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
Expand Down
25 changes: 25 additions & 0 deletions mobile/mysterium/fd_android.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// +build android
/*
* Copyright (C) 2020 The "MysteriumNetwork/node" Authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package mysterium

import "golang.zx2c4.com/wireguard/device"

func peekLookAtSocketFd4(d *device.Device) (fd int, err error) {
return d.PeekLookAtSocketFd4()
}
30 changes: 30 additions & 0 deletions mobile/mysterium/fd_default.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// +build !android

/*
* Copyright (C) 2020 The "MysteriumNetwork/node" Authors.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package mysterium

import (
"errors"

"golang.zx2c4.com/wireguard/device"
)

func peekLookAtSocketFd4(d *device.Device) (fd int, err error) {
return 0, errors.New("not implemented")
}
106 changes: 39 additions & 67 deletions mobile/mysterium/wireguard_connection_setup.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,10 @@
package mysterium

import (
"encoding/base64"
"bufio"
"encoding/json"
"net"
"strings"
"sync"
"time"

Expand Down Expand Up @@ -64,7 +65,7 @@ func (wcf *WireguardConnectionFactory) Create(stateChannel connection.StateChann
return nil, err
}

deviceFactory := func(options connection.ConnectOptions) (*device.DeviceApi, error) {
deviceFactory := func(options connection.ConnectOptions) (*device.Device, error) {
var config wireguard.ServiceConfig
err := json.Unmarshal(options.SessionConfig, &config)
if err != nil {
Expand All @@ -79,19 +80,19 @@ func (wcf *WireguardConnectionFactory) Create(stateChannel connection.StateChann
wcf.tunnelSetup.AddDNS("8.8.8.8")

//TODO this heavy linfting might go to doInit
tun, err := newTunnDevice(wcf.tunnelSetup, &config)
tunDevice, err := newTunnDevice(wcf.tunnelSetup, &config)
if err != nil {
return nil, err
}

devApi := device.UserspaceDeviceApi(tun)
devApi := device.NewDevice(tunDevice, device.NewLogger(device.LogLevelDebug, "[userspace-wg]"))
err = setupWireguardDevice(devApi, &config)
if err != nil {
devApi.Close()
return nil, err
}
devApi.Boot()
socket, err := devApi.GetNetworkSocket()
devApi.Up()
socket, err := peekLookAtSocketFd4(devApi)
if err != nil {
devApi.Close()
return nil, err
Expand All @@ -114,55 +115,29 @@ func (wcf *WireguardConnectionFactory) Create(stateChannel connection.StateChann
}, nil
}

type deviceFactory func(options connection.ConnectOptions) (*device.DeviceApi, error)
type deviceFactory func(options connection.ConnectOptions) (*device.Device, error)

func setupWireguardDevice(devApi *device.DeviceApi, config *wireguard.ServiceConfig) error {
err := devApi.SetListeningPort(0) //random port
if err != nil {
return err
}

privKeyArr, err := base64stringTo32ByteArray(config.Consumer.PrivateKey)
if err != nil {
return err
}
err = devApi.SetPrivateKey(device.NoisePrivateKey(privKeyArr))
if err != nil {
return err
func setupWireguardDevice(devApi *device.Device, config *wireguard.ServiceConfig) error {
deviceConfig := wireguard.DeviceConfig{
PrivateKey: config.Consumer.PrivateKey,
ListenPort: 0,
}

peerPubKeyArr, err := base64stringTo32ByteArray(config.Provider.PublicKey)
if err != nil {
return err
}

ep := config.Provider.Endpoint.String()
endpoint, err := device.CreateEndpoint(ep)
if err != nil {
if err := devApi.IpcSetOperation(bufio.NewReader(strings.NewReader(deviceConfig.Encode()))); err != nil {
return err
}

err = devApi.AddPeer(device.ExternalPeer{
PublicKey: device.NoisePublicKey(peerPubKeyArr),
RemoteEndpoint: endpoint,
peer := wireguard.Peer{
PublicKey: config.Provider.PublicKey,
Endpoint: &config.Provider.Endpoint,
KeepAlivePeriod: 20,
//all traffic through this peer (unfortunately 0.0.0.0/0 didn't work as it was treated as ipv6)
AllowedIPs: []string{"0.0.0.0/1", "128.0.0.0/1"},
})
return err
}

func base64stringTo32ByteArray(s string) (res [32]byte, err error) {
decoded, err := base64.StdEncoding.DecodeString(s)
if len(decoded) != 32 {
err = errors.New("unexpected key size")
}
if err != nil {
return
if err := devApi.IpcSetOperation(bufio.NewReader(strings.NewReader(peer.Encode()))); err != nil {
return err
}

copy(res[:], decoded)
return
return nil
}

func newTunnDevice(wgTunnSetup WireguardTunnelSetup, config *wireguard.ServiceConfig) (tun.Device, error) {
Expand Down Expand Up @@ -200,7 +175,7 @@ func newTunnDevice(wgTunnSetup WireguardTunnelSetup, config *wireguard.ServiceCo
type wireguardConnection struct {
privKey string
deviceFactory deviceFactory
device *device.DeviceApi
device *device.Device
stopChannel chan struct{}
stateChannel connection.StateChannel
statisticsChannel connection.StatisticsChannel
Expand Down Expand Up @@ -258,27 +233,28 @@ func (wg *wireguardConnection) GetConfig() (connection.ConsumerConfig, error) {
var _ connection.Connection = &wireguardConnection{}

func (wg *wireguardConnection) updateStatistics() {
var err error
defer func() {
if err != nil {
log.Error().Err(err).Msg("Error updating statistics")
}
}()

peers, err := wg.device.Peers()
stats, err := wg.getDeviceStats()
if err != nil {
log.Error().Err(err).Msg("Error updating statistics")
return
}
if len(peers) != 1 {
err = errors.New("exactly 1 peer expected")
return
}
peerStatistics := peers[0].Stats

wg.statisticsChannel <- consumer.SessionStatistics{
BytesSent: peerStatistics.Sent,
BytesReceived: peerStatistics.Received,
BytesSent: stats.BytesSent,
BytesReceived: stats.BytesReceived,
}
}

func (wg *wireguardConnection) getDeviceStats() (*wireguard.Stats, error) {
deviceState, err := wireguard.ParseUserspaceDevice(wg.device.IpcGetOperation)
if err != nil {
return nil, err
}
stats, err := wireguard.ParseDevicePeerStats(deviceState)
if err != nil {
return nil, err
}
return stats, nil
}

func (wg *wireguardConnection) doCleanup() {
Expand Down Expand Up @@ -308,17 +284,13 @@ func (wg *wireguardConnection) waitHandshake() error {
for {
select {
case <-time.After(20 * time.Millisecond):
peers, err := wg.device.Peers()
stats, err := wg.getDeviceStats()
if err != nil {
return errors.Wrap(err, "failed while waiting for a peer handshake")
return err
}
if len(peers) != 1 {
return errors.Wrap(errors.New("exactly 1 peer expected"), "failed while waiting for a peer handshake")
}
if peers[0].LastHanshake != 0 {
if !stats.LastHandshake.IsZero() {
return nil
}

case <-wg.stopChannel:
wg.doCleanup()
return errors.New("stop received")
Expand Down
6 changes: 5 additions & 1 deletion services/wireguard/connection/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,11 @@ func (c *Connection) Start(options connection.ConnectOptions) (err error) {
return errors.Wrap(err, "failed to start connection endpoint")
}

if err := c.connectionEndpoint.AddPeer(c.config.Provider.PublicKey, &c.config.Provider.Endpoint); err != nil {
peerInfo := wg.AddPeerOptions{
Endpoint: &c.config.Provider.Endpoint,
PublicKey: c.config.Provider.PublicKey,
}
if err := c.connectionEndpoint.AddPeer(c.connectionEndpoint.InterfaceName(), peerInfo); err != nil {
c.stateChannel <- connection.NotConnected
c.connection.Done()
removeAllowedIPRule()
Expand Down
Loading

0 comments on commit faf2e82

Please sign in to comment.