merge develop into master #21
@ -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 {
|
||||
|
@ -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 {
|
||||
|
@ -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
5
go.mod
@ -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
16
go.sum
@ -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
93
main.go
@ -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...")
|
||||
}
|
||||
|
42
tun/tun.go
42
tun/tun.go
@ -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:
|
||||
|
Loading…
Reference in New Issue
Block a user