Skip to content

Commit

Permalink
Merge pull request #36 from wiretrustee/avoid-proxy-when-local-net
Browse files Browse the repository at this point in the history
feature: initial implementation of avoiding local proxy if peers are …
  • Loading branch information
braginini authored Jun 25, 2021
2 parents 3c45da5 + 61a7f30 commit 3041ff4
Show file tree
Hide file tree
Showing 8 changed files with 253 additions and 29 deletions.
18 changes: 16 additions & 2 deletions connection/connection.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
ice "github.com/pion/ice/v2"
log "github.com/sirupsen/logrus"
"github.com/wiretrustee/wiretrustee/iface"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"sync"
"time"
Expand Down Expand Up @@ -93,6 +94,7 @@ func (conn *Connection) Open(timeout time.Duration) error {

// create an ice.Agent that will be responsible for negotiating and establishing actual peer-to-peer connection
a, err := ice.NewAgent(&ice.AgentConfig{
// MulticastDNSMode: ice.MulticastDNSModeQueryAndGather,
NetworkTypes: []ice.NetworkType{ice.NetworkTypeUDP4},
Urls: conn.Config.StunTurnURLS,
InterfaceFilter: func(s string) bool {
Expand Down Expand Up @@ -144,10 +146,23 @@ func (conn *Connection) Open(timeout time.Duration) error {
return err
}

err = conn.wgProxy.Start(remoteConn)
pair, err := conn.agent.GetSelectedCandidatePair()
if err != nil {
return err
}
// in case the remote peer is in the local network we don't need a Wireguard proxy, direct communication is possible.
if pair.Local.Type() == ice.CandidateTypeHost && pair.Remote.Type() == ice.CandidateTypeHost {
log.Debugf("remote peer %s is in the local network with an address %s", conn.Config.RemoteWgKey.String(), pair.Remote.Address())
err = conn.wgProxy.StartLocal(fmt.Sprintf("%s:%d", pair.Remote.Address(), iface.WgPort))
if err != nil {
return err
}
} else {
err = conn.wgProxy.Start(remoteConn)
if err != nil {
return err
}
}

log.Infof("opened connection to peer %s", conn.Config.RemoteWgKey.String())
case <-time.After(timeout):
Expand Down Expand Up @@ -298,7 +313,6 @@ func (conn *Connection) listenOnConnectionStateChanges() error {
}
log.Infof("will connect to peer %s via a selected connnection candidate pair %s", conn.Config.RemoteWgKey.String(), pair)
} else if state == ice.ConnectionStateDisconnected || state == ice.ConnectionStateFailed {
// todo do we really wanna have a connection restart within connection itself? Think of moving it outside
err := conn.Close()
if err != nil {
log.Warnf("error while closing connection to peer %s -> %s", conn.Config.RemoteWgKey.String(), err.Error())
Expand Down
9 changes: 9 additions & 0 deletions connection/wgproxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,15 @@ func (p *WgProxy) Close() error {
return nil
}

func (p *WgProxy) StartLocal(host string) error {
err := iface.UpdatePeer(p.iface, p.remoteKey, p.allowedIps, DefaultWgKeepAlive, host)
if err != nil {
log.Errorf("error while configuring Wireguard peer [%s] %s", p.remoteKey, err.Error())
return err
}
return nil
}

// Start starts a new proxy using the ICE connection
func (p *WgProxy) Start(remoteConn *ice.Conn) error {

Expand Down
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ require (
github.com/vishvananda/netlink v1.1.0
github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df
golang.org/x/crypto v0.0.0-20210506145944-38f3c27a63bf
golang.org/x/sys v0.0.0-20210510120138-977fb7262007
golang.zx2c4.com/wireguard v0.0.0-20210604143328-f9b48a961cd2
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20210506160403-92e472f520a5
golang.zx2c4.com/wireguard/windows v0.3.14
Expand Down
16 changes: 8 additions & 8 deletions iface/iface.go
Original file line number Diff line number Diff line change
@@ -1,27 +1,25 @@
package iface

import (
"net"
"time"

log "github.com/sirupsen/logrus"
"golang.zx2c4.com/wireguard/conn"
"golang.zx2c4.com/wireguard/device"
"golang.zx2c4.com/wireguard/tun"
"golang.zx2c4.com/wireguard/wgctrl"
"golang.zx2c4.com/wireguard/wgctrl/wgtypes"
"net"
"time"
)

const (
defaultMTU = 1280
WgPort = 51820
)

// Saves tun device object - is it required?
var tunIface tun.Device

// Create Creates a new Wireguard interface, sets a given IP and brings it up.
// Will reuse an existing one.
func Create(iface string, address string) error {
// CreateWithUserspace Creates a new Wireguard interface, using wireguard-go userspace implementation
func CreateWithUserspace(iface string, address string) error {
var err error
tunIface, err = tun.CreateTUN(iface, defaultMTU)
if err != nil {
Expand Down Expand Up @@ -52,7 +50,7 @@ func Create(iface string, address string) error {

log.Debugln("UAPI listener started")

err = assignAddr(address, tunIface)
err = assignAddr(address, iface)
if err != nil {
return err
}
Expand Down Expand Up @@ -85,10 +83,12 @@ func Configure(iface string, privateKey string) error {
return err
}
fwmark := 0
p := WgPort
cfg := wgtypes.Config{
PrivateKey: &key,
ReplacePeers: false,
FirewallMark: &fwmark,
ListenPort: &p,
}
err = wg.ConfigureDevice(iface, cfg)
if err != nil {
Expand Down
11 changes: 5 additions & 6 deletions iface/iface_darwin.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,18 @@ package iface

import (
log "github.com/sirupsen/logrus"
"golang.zx2c4.com/wireguard/tun"
"net"
"os/exec"
"strings"
)

//const (
// interfacePrefix = "utun"
//)
// Create Creates a new Wireguard interface, sets a given IP and brings it up.
func Create(iface string, address string) error {
return CreateWithUserspace(iface, address)
}

// assignAddr Adds IP address to the tunnel interface and network route based on the range provided
func assignAddr(address string, tunDevice tun.Device) error {
ifaceName, err := tunDevice.Name()
func assignAddr(address string, ifaceName string) error {
ip := strings.Split(address, "/")
cmd := exec.Command("ifconfig", ifaceName, "inet", address, ip[0])
if out, err := cmd.CombinedOutput(); err != nil {
Expand Down
70 changes: 61 additions & 9 deletions iface/iface_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,76 @@ package iface
import (
log "github.com/sirupsen/logrus"
"github.com/vishvananda/netlink"
"golang.zx2c4.com/wireguard/tun"

"os"
)

//const (
// interfacePrefix = "wg"
//)
// Create Creates a new Wireguard interface, sets a given IP and brings it up.
// Will reuse an existing one.
func Create(iface string, address string) error {

// assignAddr Adds IP address to the tunnel interface
func assignAddr(address string, tunDevice tun.Device) error {
var err error
if WireguardModExists() {
log.Debug("using kernel Wireguard module")
return CreateWithKernel(iface, address)
} else {
return CreateWithUserspace(iface, address)
}
}

// CreateWithKernel Creates a new Wireguard interface using kernel Wireguard module.
// Works for Linux and offers much better network performance
func CreateWithKernel(iface string, address string) error {
attrs := netlink.NewLinkAttrs()
attrs.Name, err = tunDevice.Name()
attrs.Name = iface

link := wgLink{
attrs: &attrs,
}

log.Debugf("adding device: %s", iface)
err := netlink.LinkAdd(&link)
if os.IsExist(err) {
log.Infof("interface %s already exists. Will reuse.", iface)
} else if err != nil {
return err
}

log.Debugf("adding address %s to interface: %s", address, iface)
addr, _ := netlink.ParseAddr(address)
err = netlink.AddrAdd(&link, addr)
if os.IsExist(err) {
log.Infof("interface %s already has the address: %s", iface, address)
} else if err != nil {
return err
}
err = assignAddr(address, iface)
if err != nil {
return err
}

// todo do a discovery
log.Debugf("setting MTU: %s", iface)
err = netlink.LinkSetMTU(&link, defaultMTU)
if err != nil {
log.Errorf("error setting MTU on interface: %s", iface)
return err
}

log.Debugf("bringing up interface: %s", iface)
err = netlink.LinkSetUp(&link)
if err != nil {
log.Errorf("error bringing up interface: %s", iface)
return err
}

return nil
}

// assignAddr Adds IP address to the tunnel interface
func assignAddr(address, name string) error {
var err error
attrs := netlink.NewLinkAttrs()
attrs.Name = name

link := wgLink{
attrs: &attrs,
}
Expand Down
13 changes: 9 additions & 4 deletions iface/iface_windows.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,21 @@ import (
"net"
)

// Create Creates a new Wireguard interface, sets a given IP and brings it up.
func Create(iface string, address string) error {
return CreateWithUserspace(iface, address)
}

// assignAddr Adds IP address to the tunnel interface and network route based on the range provided
func assignAddr(address string, tunDevice tun.Device) error {
ifaceName, err := tunDevice.Name()
nativeTunDevice := tunDevice.(*tun.NativeTun)
func assignAddr(address string, ifaceName string) error {

nativeTunDevice := tunIface.(*tun.NativeTun)
luid := winipcfg.LUID(nativeTunDevice.LUID())

ip, ipnet, _ := net.ParseCIDR(address)

log.Debugf("adding address %s to interface: %s", address, ifaceName)
err = luid.SetIPAddresses([]net.IPNet{{ip, ipnet.Mask}})
err := luid.SetIPAddresses([]net.IPNet{{ip, ipnet.Mask}})
if err != nil {
return err
}
Expand Down
Loading

0 comments on commit 3041ff4

Please sign in to comment.