merge develop into master #21

Merged
JakeHillion merged 149 commits from develop into master 2021-05-12 00:22:59 +01:00
7 changed files with 137 additions and 70 deletions
Showing only changes of commit 1944eb620a - Show all commits

View File

@ -5,16 +5,14 @@ import (
"fmt"
"mpbl3p/crypto"
"mpbl3p/crypto/sharedkey"
"mpbl3p/flags"
"mpbl3p/proxy"
"mpbl3p/tcp"
"mpbl3p/tun"
"mpbl3p/udp"
"mpbl3p/udp/congestion"
"time"
)
func (c Configuration) Build(o *flags.Options) (*proxy.Proxy, error) {
func (c Configuration) Build(source proxy.Source, sink proxy.Sink) (*proxy.Proxy, error) {
p := proxy.NewProxy(0)
var g func() proxy.MacGenerator
@ -42,18 +40,8 @@ func (c Configuration) Build(o *flags.Options) (*proxy.Proxy, error) {
}
}
ifName := o.InterfaceName
if ifName == "" {
ifName = "nc%d"
}
ss, err := tun.NewTun(ifName, 1500)
if err != nil {
return nil, err
}
p.Source = ss
p.Sink = ss
p.Source = source
p.Sink = sink
for _, peer := range c.Peers {
switch peer.Method {

View File

@ -40,6 +40,7 @@ type Configuration struct {
type Host struct {
Crypto string `validate:"required,oneof=None Blake2s"`
SharedKey string `validate:"required_if=Crypto Blake2s"`
MTU uint
}
type Peer struct {

View File

@ -1,33 +1,41 @@
package flags
import (
"errors"
"fmt"
"github.com/jessevdk/go-flags"
goflags "github.com/jessevdk/go-flags"
"os"
)
var PrintedHelpErr = goflags.ErrHelp
var NotEnoughArgs = errors.New("not enough arguments")
type Options struct {
Foreground bool `short:"f" long:"foreground" description:"Run in the foreground"`
ConfigFile string `short:"c" long:"config" description:"Configuration file location" value-name:"FILE"`
PidFile string `short:"p" long:"pid" description:"PID file location"`
InterfaceName string
Positional struct {
InterfaceName string `required:"yes" positional-arg-name:"INTERFACE-NAME" description:"Interface name"`
} `positional-args:"yes"`
}
func ParseFlags() (*Options, error) {
o := new(Options)
args, err := flags.Parse(o)
parser := goflags.NewParser(o, goflags.Default)
_, err := parser.Parse()
if err != nil {
parser.WriteHelp(os.Stdout)
return nil, err
}
if len(args) > 0 {
o.InterfaceName = args[0]
if o.ConfigFile == "" {
o.ConfigFile = fmt.Sprintf(DefaultConfigFile, o.InterfaceName)
}
if o.PidFile == "" {
o.PidFile = fmt.Sprintf(DefaultPidFile, o.InterfaceName)
}
if o.ConfigFile == "" {
o.ConfigFile = fmt.Sprintf(DefaultConfigFile, o.Positional.InterfaceName)
}
if o.PidFile == "" {
o.PidFile = fmt.Sprintf(DefaultPidFile, o.Positional.InterfaceName)
}
return o, err
return o, nil
}

5
go.mod
View File

@ -6,10 +6,9 @@ require (
github.com/JakeHillion/taptun v0.0.0-20210320133200-cf0ef75b1bff
github.com/go-playground/validator/v10 v10.4.1
github.com/jessevdk/go-flags v1.5.0
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
github.com/sevlyar/go-daemon v0.1.5
github.com/smartystreets/goconvey v1.6.4 // indirect
github.com/stretchr/testify v1.4.0
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9
golang.zx2c4.com/wireguard v0.0.20201118
gopkg.in/ini.v1 v1.62.0
)

16
go.sum
View File

@ -16,14 +16,10 @@ github.com/jessevdk/go-flags v1.5.0 h1:1jKYvbxEjfUl0fmqTCOfonvskHHXMjBySTLW4y9LF
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA=
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8=
github.com/leodido/go-urn v1.2.0 h1:hpXL4XnriNwQ/ABnpepYM/1vCLWNDfUNts8dX3xTG6Y=
github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/sevlyar/go-daemon v0.1.5 h1:Zy/6jLbM8CfqJ4x4RPr7MJlSKt90f00kNM1D401C+Qk=
github.com/sevlyar/go-daemon v0.1.5/go.mod h1:6dJpPatBT9eUwM5VCw9Bt6CdX9Tk6UWvhW3MebLDRKE=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
@ -32,18 +28,28 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9 h1:psW17arqaxU48Z5kZ0CQnkZWQJsqcURM6tKiBApRjXI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9 h1:phUcVbl53swtrUN8kQEXFhUxPlIlWyBfKmidCu7P95o=
golang.org/x/crypto v0.0.0-20201117144127-c1f2f97bffc9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b h1:uwuIcX0g4Yl1NC5XAz37xsr2lTtcqevgzYNVt49waME=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201117222635-ba5294a509c7/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4 h1:EZ2mChiOa8udjfp6rRmswTbtZN/QzUQp4ptM4rnjHvc=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.zx2c4.com/wireguard v0.0.20201118 h1:QL8y2C7uO8T6z1GY+UX/hSeWiYEBurQkXjOTRFtCvXU=
golang.zx2c4.com/wireguard v0.0.20201118/go.mod h1:Dz+cq5bnrai9EpgYj4GDof/+qaGzbRWbeaAOs1bUYa0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=

93
main.go
View File

@ -1,62 +1,109 @@
package main
import (
"github.com/sevlyar/go-daemon"
"errors"
"fmt"
"log"
"mpbl3p/config"
"mpbl3p/flags"
"mpbl3p/tun"
"os"
"os/signal"
"strconv"
"syscall"
)
const (
ENV_NC_TUN_FD = "NC_TUN_FD"
ENV_NC_CONFIG_PATH = "NC_CONFIG_PATH"
)
func main() {
log.SetFlags(log.Ldate | log.Ltime | log.Llongfile)
o, err := flags.ParseFlags()
if err != nil {
panic(err)
if _, exists := os.LookupEnv(ENV_NC_TUN_FD); !exists {
// we are the parent process
// 1) process arguments
// 2) validate config
// 2) create a tun adapter
// 3) spawn a child
// 4) exit
o, err := flags.ParseFlags()
if err != nil {
if errors.Is(err, flags.PrintedHelpErr) {
return
}
panic(err)
}
log.Println("loading config...")
c, err := config.LoadConfig(o.ConfigFile)
if err != nil {
panic(err)
}
log.Println("creating tun adapter...")
t, err := tun.NewTun(o.Positional.InterfaceName, int(c.Host.MTU))
if err != nil {
panic(err)
}
if o.Foreground {
if err := os.Setenv(ENV_NC_TUN_FD, fmt.Sprintf("%d", t.File().Fd())); err != nil {
panic(err)
}
if err := os.Setenv(ENV_NC_CONFIG_PATH, o.ConfigFile); err != nil {
panic(err)
}
goto FOREGROUND
}
return
}
// we are the child process
// 1) recreate tun adapter from file descriptor
// 2) launch proxy
FOREGROUND:
log.Println("loading config...")
c, err := config.LoadConfig(o.ConfigFile)
c, err := config.LoadConfig(os.Getenv(ENV_NC_CONFIG_PATH))
if err != nil {
panic(err)
}
log.Println("building config...")
p, err := c.Build(o)
log.Println("connecting tun adapter...")
tunFd, err := strconv.ParseUint(os.Getenv(ENV_NC_TUN_FD), 10, 64)
if err != nil {
panic(err)
}
log.Println("starting...")
p.Start()
log.Println("forking...")
ctx := &daemon.Context{
PidFileName: o.PidFile,
PidFilePerm: 0644,
}
d, err := ctx.Reborn()
t, err := tun.NewFromFile(uintptr(tunFd), int(c.Host.MTU))
if err != nil {
panic(err)
}
if d != nil {
return
}
defer func() {
if err := ctx.Release(); err != nil {
if err := t.Close(); err != nil {
panic(err)
}
}()
log.Println("building config...")
p, err := c.Build(t, t)
if err != nil {
panic(err)
}
log.Println("starting proxy...")
p.Start()
log.Println("proxy started")
signals := make(chan os.Signal)
signal.Notify(signals, syscall.SIGTERM, syscall.SIGINT)
<-signals
log.Println("exiting...")
}

View File

@ -1,7 +1,7 @@
package tun
import (
"github.com/JakeHillion/taptun"
wgtun "golang.zx2c4.com/wireguard/tun"
"io"
"log"
"mpbl3p/proxy"
@ -13,34 +13,45 @@ import (
)
type SourceSink struct {
tun *taptun.Tun
bufferSize int
tun wgtun.Device
mtu int
up bool
upMu sync.Mutex
}
func NewTun(namingScheme string, bufferSize int) (ss *SourceSink, err error) {
ss = &SourceSink{}
func NewTun(name string, mtu int) (t wgtun.Device, err error) {
return wgtun.CreateTUN(name, mtu)
}
ss.tun, err = taptun.NewTun(namingScheme)
func NewFromFile(fd uintptr, mtu int) (ss *SourceSink, err error) {
ss = new(SourceSink)
file := os.NewFile(fd, "")
ss.tun, err = wgtun.CreateTUNFromFile(file, mtu)
if err != nil {
return
}
ss.bufferSize = bufferSize
ss.mtu = mtu
ss.upMu.Lock()
go func() {
defer ss.upMu.Unlock()
for {
iface, err := net.InterfaceByName(ss.tun.String())
tunName, err := ss.tun.Name()
if err != nil {
panic(err)
}
iface, err := net.InterfaceByName(tunName)
if err != nil {
panic(err)
}
if strings.Contains(iface.Flags.String(), "up") {
log.Println("tun is up")
log.Println("wgtun is up")
ss.up = true
return
}
@ -51,15 +62,22 @@ func NewTun(namingScheme string, bufferSize int) (ss *SourceSink, err error) {
return
}
func (t *SourceSink) Close() error {
t.upMu.Lock()
t.up = false
return t.tun.Close()
}
func (t *SourceSink) Source() (proxy.Packet, error) {
if !t.up {
t.upMu.Lock()
t.upMu.Unlock()
}
buf := make([]byte, t.bufferSize)
buf := make([]byte, t.mtu)
read, err := t.tun.Read(buf)
read, err := t.tun.Read(buf, t.mtu)
if err != nil {
return nil, err
}
@ -79,7 +97,7 @@ func (t *SourceSink) Sink(packet proxy.Packet) error {
t.upMu.Unlock()
}
_, err := t.tun.Write(packet.Contents())
_, err := t.tun.Write(packet.Contents(), t.mtu)
if err != nil {
switch err.(type) {
case *os.PathError: