12 Commits

Author SHA1 Message Date
octeep
2b116ffad6 Merge remote-tracking branch 'refs/remotes/origin/master' 2022-04-03 19:42:29 +01:00
octeep
6ab6551686 replace log.Panic with log.Fatal 2022-04-03 19:42:19 +01:00
octeep
6bdeffe3f2 Add IPv6 support 2022-04-03 19:35:08 +01:00
octeep
9224e79eea Update Dockerfile #32 2022-04-03 10:10:35 +01:00
octeep
d1711b02b6 Revert "add freebsd and openbsd to goreleaser"
This reverts commit e38b0155dd.
2022-04-01 01:16:38 +01:00
octeep
2fb865da94 Update README.md 2022-04-01 01:07:50 +01:00
octeep
00cb3dd99e Merge remote-tracking branch 'refs/remotes/origin/master' 2022-04-01 00:47:29 +01:00
octeep
0048d87cad add documentation 2022-04-01 00:47:14 +01:00
octeep
564dfe2c79 Create FUNDING.yml 2022-03-31 23:24:08 +01:00
octeep
f93e047f64 add pledge call on OpenBSD 2022-03-31 20:15:05 +01:00
octeep
863440f936 Trigger gorelease when v* tag is created 2022-03-31 20:14:13 +01:00
octeep
e38b0155dd add freebsd and openbsd to goreleaser 2022-03-31 18:32:34 +01:00
10 changed files with 125 additions and 43 deletions

3
.github/FUNDING.yml vendored Normal file
View File

@@ -0,0 +1,3 @@
# These are supported funding model platforms
liberapay: octeep

View File

@@ -2,6 +2,9 @@ name: Cross compile WirePorxy
on: on:
workflow_dispatch: workflow_dispatch:
create:
tags:
- v*
jobs: jobs:
WirePorxy: WirePorxy:

View File

@@ -1,4 +1,8 @@
# wireproxy # wireproxy
[![ISC licensed](https://img.shields.io/badge/license-ISC-blue)](./LICENSE)
[![Build status](https://github.com/octeep/wireproxy/actions/workflows/build.yml/badge.svg)](https://github.com/octeep/wireproxy/actions)
[![Documentation](https://img.shields.io/badge/godoc-wireproxy-blue)](https://pkg.go.dev/github.com/octeep/wireproxy)
A wireguard client that exposes itself as a socks5 proxy or tunnels. A wireguard client that exposes itself as a socks5 proxy or tunnels.
# What is this # What is this
@@ -20,6 +24,10 @@ anything.
- TCP static routing for client and server - TCP static routing for client and server
- SOCKS5 proxy (currently only CONNECT is supported) - SOCKS5 proxy (currently only CONNECT is supported)
# TODO
- UDP Support in SOCKS5
- UDP static routing
# Usage # Usage
``` ```
./wireproxy -c [path to config] ./wireproxy -c [path to config]
@@ -108,6 +116,9 @@ WGConfig = <path to the wireguard config>
... ...
``` ```
## Donation
<noscript><a href="https://liberapay.com/octeep/donate"><img alt="Donate using Liberapay" src="https://liberapay.com/assets/widgets/donate.svg"></a></noscript>
## Stargazers over time ## Stargazers over time

View File

@@ -8,18 +8,33 @@ import (
"github.com/akamensky/argparse" "github.com/akamensky/argparse"
"github.com/octeep/wireproxy" "github.com/octeep/wireproxy"
"suah.dev/protect"
) )
// an argument to denote that this process was spawned by -d
const daemonProcess = "daemon-process" const daemonProcess = "daemon-process"
// attempts to pledge and panic if it fails
// this does nothing on non-OpenBSD systems
func pledgeOrPanic(promises string) {
err := protect.Pledge(promises)
if err != nil {
log.Fatal(err)
}
}
func main() { func main() {
// only allow standard stdio operation, file reading, networking, and exec
pledgeOrPanic("stdio rpath inet dns proc exec")
isDaemonProcess := len(os.Args) > 1 && os.Args[1] == daemonProcess isDaemonProcess := len(os.Args) > 1 && os.Args[1] == daemonProcess
args := os.Args args := os.Args
if isDaemonProcess { if isDaemonProcess {
// remove proc and exec if they are not needed
pledgeOrPanic("stdio rpath inet dns")
args = []string{args[0]} args = []string{args[0]}
args = append(args, os.Args[2:]...) args = append(args, os.Args[2:]...)
} }
parser := argparse.NewParser("wireproxy", "Userspace wireguard client for proxying") parser := argparse.NewParser("wireproxy", "Userspace wireguard client for proxying")
config := parser.String("c", "config", &argparse.Options{Required: true, Help: "Path of configuration file"}) config := parser.String("c", "config", &argparse.Options{Required: true, Help: "Path of configuration file"})
@@ -32,9 +47,14 @@ func main() {
return return
} }
if !*daemon {
// remove proc and exec if they are not needed
pledgeOrPanic("stdio rpath inet dns")
}
conf, err := wireproxy.ParseConfig(*config) conf, err := wireproxy.ParseConfig(*config)
if err != nil { if err != nil {
log.Panic(err) log.Fatal(err)
} }
if *configTest { if *configTest {
@@ -64,9 +84,12 @@ func main() {
return return
} }
// no file access is allowed from now on, only networking
pledgeOrPanic("stdio inet dns")
tnet, err := wireproxy.StartWireguard(conf.Device) tnet, err := wireproxy.StartWireguard(conf.Device)
if err != nil { if err != nil {
log.Panic(err) log.Fatal(err)
} }
for _, spawner := range conf.Routines { for _, spawner := range conf.Routines {

View File

@@ -12,6 +12,7 @@ import (
"golang.zx2c4.com/go118/netip" "golang.zx2c4.com/go118/netip"
) )
// DeviceConfig contains the information to initiate a wireguard connection
type DeviceConfig struct { type DeviceConfig struct {
SelfSecretKey string SelfSecretKey string
SelfEndpoint []netip.Addr SelfEndpoint []netip.Addr
@@ -160,6 +161,7 @@ func resolveIPPAndPort(addr string) (string, error) {
return net.JoinHostPort(ip.String(), port), nil return net.JoinHostPort(ip.String(), port), nil
} }
// ParseInterface parses the [Interface] section and extract the information into `device`
func ParseInterface(cfg *ini.File, device *DeviceConfig) error { func ParseInterface(cfg *ini.File, device *DeviceConfig) error {
sections, err := cfg.SectionsByName("Interface") sections, err := cfg.SectionsByName("Interface")
if len(sections) != 1 || err != nil { if len(sections) != 1 || err != nil {
@@ -197,6 +199,7 @@ func ParseInterface(cfg *ini.File, device *DeviceConfig) error {
return nil return nil
} }
// ParsePeer parses the [Peer] section and extract the information into `device`
func ParsePeer(cfg *ini.File, device *DeviceConfig) error { func ParsePeer(cfg *ini.File, device *DeviceConfig) error {
sections, err := cfg.SectionsByName("Peer") sections, err := cfg.SectionsByName("Peer")
if len(sections) != 1 || err != nil { if len(sections) != 1 || err != nil {
@@ -292,6 +295,8 @@ func parseSocks5Config(section *ini.Section) (RoutineSpawner, error) {
return config, nil return config, nil
} }
// Takes a function that parses an individual section into a config, and apply it on all
// specified sections
func parseRoutinesConfig(routines *[]RoutineSpawner, cfg *ini.File, sectionName string, f func(*ini.Section) (RoutineSpawner, error)) error { func parseRoutinesConfig(routines *[]RoutineSpawner, cfg *ini.File, sectionName string, f func(*ini.Section) (RoutineSpawner, error)) error {
sections, err := cfg.SectionsByName(sectionName) sections, err := cfg.SectionsByName(sectionName)
if err != nil { if err != nil {
@@ -310,6 +315,7 @@ func parseRoutinesConfig(routines *[]RoutineSpawner, cfg *ini.File, sectionName
return nil return nil
} }
// ParseConfig takes the path of a configuration file and parses it into Configuration
func ParseConfig(path string) (*Configuration, error) { func ParseConfig(path string) (*Configuration, error) {
iniOpt := ini.LoadOptions{ iniOpt := ini.LoadOptions{
Insensitive: true, Insensitive: true,

View File

@@ -11,4 +11,4 @@ RUN apk upgrade
COPY --from=go-build /go/wireproxy/wireproxy /usr/bin/ COPY --from=go-build /go/wireproxy/wireproxy /usr/bin/
VOLUME [ "/etc/wireproxy"] VOLUME [ "/etc/wireproxy"]
ENTRYPOINT [ "/usr/bin/wireproxy", "/etc/wireproxy/config" ] ENTRYPOINT [ "/usr/bin/wireproxy", "--config", "/etc/wireproxy/config" ]

1
go.mod
View File

@@ -21,4 +21,5 @@ require (
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 // indirect
golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect golang.org/x/time v0.0.0-20210220033141-f8bda1e9f3ba // indirect
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
suah.dev/protect v1.2.0 // indirect
) )

3
go.sum
View File

@@ -744,6 +744,7 @@ golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20210314195730-07df6a141424/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210314195730-07df6a141424/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210917161153-d61c044b1678/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211110154304-99a53858aa08/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -999,3 +1000,5 @@ sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:w
sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw= sigs.k8s.io/structured-merge-diff/v4 v4.0.3/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc= sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
suah.dev/protect v1.2.0 h1:4G4V43yVYXCjLFzaE9QJR0fLo3rf5vNBS9YxyoI19DU=
suah.dev/protect v1.2.0/go.mod h1:Ocn1yqUskqe/is6N2bxQxtT+fegbvQsOFyHbJAQu9XE=

View File

@@ -4,11 +4,11 @@ import (
"context" "context"
"crypto/subtle" "crypto/subtle"
"errors" "errors"
"fmt"
"io" "io"
"log" "log"
"math/rand" "math/rand"
"net" "net"
"os"
"strconv" "strconv"
"github.com/armon/go-socks5" "github.com/armon/go-socks5"
@@ -17,20 +17,28 @@ import (
"golang.zx2c4.com/wireguard/tun/netstack" "golang.zx2c4.com/wireguard/tun/netstack"
) )
// errorLogger is the logger to print error message
var errorLogger = log.New(os.Stderr, "ERROR: ", log.LstdFlags)
// CredentialValidator stores the authentication data of a socks5 proxy
type CredentialValidator struct { type CredentialValidator struct {
username string username string
password string password string
} }
// VirtualTun stores a reference to netstack network and DNS configuration
type VirtualTun struct { type VirtualTun struct {
tnet *netstack.Net tnet *netstack.Net
systemDNS bool systemDNS bool
} }
// RoutineSpawner spawns a routine (e.g. socks5, tcp static routes) after the configuration is parsed
type RoutineSpawner interface { type RoutineSpawner interface {
SpawnRoutine(vt *VirtualTun) SpawnRoutine(vt *VirtualTun)
} }
// LookupAddr lookups a hostname.
// DNS traffic may or may not be routed depending on VirtualTun's setting
func (d VirtualTun) LookupAddr(ctx context.Context, name string) ([]string, error) { func (d VirtualTun) LookupAddr(ctx context.Context, name string) ([]string, error) {
if d.systemDNS { if d.systemDNS {
return net.DefaultResolver.LookupHost(ctx, name) return net.DefaultResolver.LookupHost(ctx, name)
@@ -39,23 +47,15 @@ func (d VirtualTun) LookupAddr(ctx context.Context, name string) ([]string, erro
} }
} }
// ResolveAddrPort resolves a hostname and returns an AddrPort.
// DNS traffic may or may not be routed depending on VirtualTun's setting
func (d VirtualTun) ResolveAddrPort(saddr string) (*netip.AddrPort, error) { func (d VirtualTun) ResolveAddrPort(saddr string) (*netip.AddrPort, error) {
name, sport, err := net.SplitHostPort(saddr) name, sport, err := net.SplitHostPort(saddr)
if err != nil { if err != nil {
return nil, err return nil, err
} }
addrs, err := d.LookupAddr(context.Background(), name) addr, err := d.ResolveAddrWithContext(context.Background(), name)
if err != nil {
return nil, err
}
size := len(addrs)
if size == 0 {
return nil, errors.New("no address found for: " + name)
}
addr, err := netip.ParseAddr(addrs[rand.Intn(size)])
if err != nil { if err != nil {
return nil, err return nil, err
} }
@@ -65,34 +65,54 @@ func (d VirtualTun) ResolveAddrPort(saddr string) (*netip.AddrPort, error) {
return nil, &net.OpError{Op: "dial", Err: errors.New("port must be numeric")} return nil, &net.OpError{Op: "dial", Err: errors.New("port must be numeric")}
} }
addrPort := netip.AddrPortFrom(addr, uint16(port)) addrPort := netip.AddrPortFrom(*addr, uint16(port))
return &addrPort, nil return &addrPort, nil
} }
func (d VirtualTun) Resolve(ctx context.Context, name string) (context.Context, net.IP, error) { // ResolveAddrPort resolves a hostname and returns an AddrPort.
var addrs []string // DNS traffic may or may not be routed depending on VirtualTun's setting
var err error func (d VirtualTun) ResolveAddrWithContext(ctx context.Context, name string) (*netip.Addr, error) {
addrs, err := d.LookupAddr(ctx, name)
addrs, err = d.LookupAddr(ctx, name)
if err != nil { if err != nil {
return ctx, nil, err return nil, err
} }
size := len(addrs) size := len(addrs)
if size == 0 { if size == 0 {
return ctx, nil, errors.New("no address found for: " + name) return nil, errors.New("no address found for: " + name)
} }
addr := addrs[rand.Intn(size)] rand.Shuffle(size, func(i, j int) {
ip := net.ParseIP(addr) addrs[i], addrs[j] = addrs[j], addrs[i]
if ip == nil { })
return ctx, nil, errors.New("invalid address: " + addr)
var addr netip.Addr
for _, saddr := range addrs {
addr, err = netip.ParseAddr(saddr)
if err == nil {
break
}
} }
return ctx, ip, err if err != nil {
return nil, err
} }
return &addr, nil
}
// ResolveAddrPort resolves a hostname and returns an IP.
// DNS traffic may or may not be routed depending on VirtualTun's setting
func (d VirtualTun) Resolve(ctx context.Context, name string) (context.Context, net.IP, error) {
addr, err := d.ResolveAddrWithContext(ctx, name)
if err != nil {
return nil, nil, err
}
return ctx, addr.AsSlice(), nil
}
// Spawns a socks5 server.
func (config *Socks5Config) SpawnRoutine(vt *VirtualTun) { func (config *Socks5Config) SpawnRoutine(vt *VirtualTun) {
conf := &socks5.Config{Dial: vt.tnet.DialContext, Resolver: vt} conf := &socks5.Config{Dial: vt.tnet.DialContext, Resolver: vt}
if username := config.Username; username != "" { if username := config.Username; username != "" {
@@ -102,33 +122,38 @@ func (config *Socks5Config) SpawnRoutine(vt *VirtualTun) {
} }
server, err := socks5.New(conf) server, err := socks5.New(conf)
if err != nil { if err != nil {
log.Panic(err) log.Fatal(err)
} }
if err := server.ListenAndServe("tcp", config.BindAddress); err != nil { if err := server.ListenAndServe("tcp", config.BindAddress); err != nil {
log.Panic(err) log.Fatal(err)
} }
} }
// Valid checks the authentication data in CredentialValidator and compare them
// to username and password in constant time.
func (c CredentialValidator) Valid(username, password string) bool { func (c CredentialValidator) Valid(username, password string) bool {
u := subtle.ConstantTimeCompare([]byte(c.username), []byte(username)) u := subtle.ConstantTimeCompare([]byte(c.username), []byte(username))
p := subtle.ConstantTimeCompare([]byte(c.password), []byte(password)) p := subtle.ConstantTimeCompare([]byte(c.password), []byte(password))
return u&p == 1 return u&p == 1
} }
// connForward copy data from `from` to `to`, then close both stream.
func connForward(bufSize int, from io.ReadWriteCloser, to io.ReadWriteCloser) { func connForward(bufSize int, from io.ReadWriteCloser, to io.ReadWriteCloser) {
buf := make([]byte, bufSize) buf := make([]byte, bufSize)
_, err := io.CopyBuffer(to, from, buf) _, err := io.CopyBuffer(to, from, buf)
if err != nil { if err != nil {
to.Close() errorLogger.Printf("Cannot forward traffic: %s\n", err.Error())
return
} }
_ = from.Close()
_ = to.Close()
} }
// tcpClientForward starts a new connection via wireguard and forward traffic from `conn`
func tcpClientForward(tnet *netstack.Net, target *net.TCPAddr, conn net.Conn) { func tcpClientForward(tnet *netstack.Net, target *net.TCPAddr, conn net.Conn) {
sconn, err := tnet.DialTCP(target) sconn, err := tnet.DialTCP(target)
if err != nil { if err != nil {
fmt.Printf("[ERROR] TCP Client Tunnel to %s: %s\n", target, err.Error()) errorLogger.Printf("TCP Client Tunnel to %s: %s\n", target, err.Error())
return return
} }
@@ -136,31 +161,33 @@ func tcpClientForward(tnet *netstack.Net, target *net.TCPAddr, conn net.Conn) {
go connForward(1024, conn, sconn) go connForward(1024, conn, sconn)
} }
// Spawns a local TCP server which acts as a proxy to the specified target
func (conf *TCPClientTunnelConfig) SpawnRoutine(vt *VirtualTun) { func (conf *TCPClientTunnelConfig) SpawnRoutine(vt *VirtualTun) {
raddr, err := vt.ResolveAddrPort(conf.Target) raddr, err := vt.ResolveAddrPort(conf.Target)
if err != nil { if err != nil {
log.Panic(err) log.Fatal(err)
} }
tcpAddr := TCPAddrFromAddrPort(*raddr) tcpAddr := TCPAddrFromAddrPort(*raddr)
server, err := net.ListenTCP("tcp", conf.BindAddress) server, err := net.ListenTCP("tcp", conf.BindAddress)
if err != nil { if err != nil {
log.Panic(err) log.Fatal(err)
} }
for { for {
conn, err := server.Accept() conn, err := server.Accept()
if err != nil { if err != nil {
log.Panic(err) log.Fatal(err)
} }
go tcpClientForward(vt.tnet, tcpAddr, conn) go tcpClientForward(vt.tnet, tcpAddr, conn)
} }
} }
// tcpServerForward starts a new connection locally and forward traffic from `conn`
func tcpServerForward(target *net.TCPAddr, conn net.Conn) { func tcpServerForward(target *net.TCPAddr, conn net.Conn) {
sconn, err := net.DialTCP("tcp", nil, target) sconn, err := net.DialTCP("tcp", nil, target)
if err != nil { if err != nil {
fmt.Printf("[ERROR] TCP Server Tunnel to %s: %s\n", target, err.Error()) errorLogger.Printf("TCP Server Tunnel to %s: %s\n", target, err.Error())
return return
} }
@@ -168,23 +195,24 @@ func tcpServerForward(target *net.TCPAddr, conn net.Conn) {
go connForward(1024, conn, sconn) go connForward(1024, conn, sconn)
} }
// Spawns a TCP server on wireguard which acts as a proxy to the specified target
func (conf *TCPServerTunnelConfig) SpawnRoutine(vt *VirtualTun) { func (conf *TCPServerTunnelConfig) SpawnRoutine(vt *VirtualTun) {
raddr, err := vt.ResolveAddrPort(conf.Target) raddr, err := vt.ResolveAddrPort(conf.Target)
if err != nil { if err != nil {
log.Panic(err) log.Fatal(err)
} }
tcpAddr := TCPAddrFromAddrPort(*raddr) tcpAddr := TCPAddrFromAddrPort(*raddr)
addr := &net.TCPAddr{Port: conf.ListenPort} addr := &net.TCPAddr{Port: conf.ListenPort}
server, err := vt.tnet.ListenTCP(addr) server, err := vt.tnet.ListenTCP(addr)
if err != nil { if err != nil {
log.Panic(err) log.Fatal(err)
} }
for { for {
conn, err := server.Accept() conn, err := server.Accept()
if err != nil { if err != nil {
log.Panic(err) log.Fatal(err)
} }
go tcpServerForward(tcpAddr, conn) go tcpServerForward(tcpAddr, conn)
} }

View File

@@ -9,6 +9,7 @@ import (
"golang.zx2c4.com/wireguard/tun/netstack" "golang.zx2c4.com/wireguard/tun/netstack"
) )
// DeviceSetting contains the parameters for setting up a tun interface
type DeviceSetting struct { type DeviceSetting struct {
ipcRequest string ipcRequest string
dns []netip.Addr dns []netip.Addr
@@ -16,18 +17,21 @@ type DeviceSetting struct {
mtu int mtu int
} }
// serialize the config into an IPC request and DeviceSetting
func createIPCRequest(conf *DeviceConfig) (*DeviceSetting, error) { func createIPCRequest(conf *DeviceConfig) (*DeviceSetting, error) {
request := fmt.Sprintf(`private_key=%s request := fmt.Sprintf(`private_key=%s
public_key=%s public_key=%s
endpoint=%s endpoint=%s
persistent_keepalive_interval=%d persistent_keepalive_interval=%d
preshared_key=%s preshared_key=%s
allowed_ip=0.0.0.0/0`, conf.SelfSecretKey, conf.PeerPublicKey, conf.PeerEndpoint, conf.KeepAlive, conf.PreSharedKey) allowed_ip=0.0.0.0/0
allowed_ip=::0/0`, conf.SelfSecretKey, conf.PeerPublicKey, conf.PeerEndpoint, conf.KeepAlive, conf.PreSharedKey)
setting := &DeviceSetting{ipcRequest: request, dns: conf.DNS, deviceAddr: conf.SelfEndpoint, mtu: conf.MTU} setting := &DeviceSetting{ipcRequest: request, dns: conf.DNS, deviceAddr: conf.SelfEndpoint, mtu: conf.MTU}
return setting, nil return setting, nil
} }
// StartWireguard creates a tun interface on netstack given a configuration
func StartWireguard(conf *DeviceConfig) (*VirtualTun, error) { func StartWireguard(conf *DeviceConfig) (*VirtualTun, error) {
setting, err := createIPCRequest(conf) setting, err := createIPCRequest(conf)
if err != nil { if err != nil {