Skip to content

Commit

Permalink
better error handling and loging
Browse files Browse the repository at this point in the history
  • Loading branch information
uoosef committed Feb 9, 2024
1 parent 7b6da0e commit 6ffdfb0
Show file tree
Hide file tree
Showing 8 changed files with 208 additions and 107 deletions.
147 changes: 84 additions & 63 deletions app/app.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package app

import (
"context"
"errors"
"flag"
"fmt"
"github.com/bepass-org/wireguard-go/psiphon"
Expand All @@ -9,128 +11,147 @@ import (
"log"
"net"
"os"
"os/signal"
"path/filepath"
"syscall"
"time"
)

func RunWarp(psiphonEnabled, gool, scan, verbose bool, country, bindAddress, endpoint, license string) {
func RunWarp(psiphonEnabled, gool, scan, verbose bool, country, bindAddress, endpoint, license string, ctx context.Context) error {
// check if user input is not correct
if (psiphonEnabled && gool) || (!psiphonEnabled && country != "") {
log.Println("Wrong command!")
log.Println("Wrong combination of flags!")
flag.Usage()
return
return errors.New("wrong command")
}

//create necessary file structures
makeDirs()
if err := makeDirs(); err != nil {
return err
}

// Change the current working directory to 'stuff'
if err := os.Chdir("stuff"); err != nil {
log.Printf("Error changing to 'stuff' directory: %v\n", err)
return fmt.Errorf("Error changing to 'stuff' directory: %v\n", err)
}
log.Println("Changed working directory to 'stuff'")
defer func() {
// back where you where
if err := os.Chdir(".."); err != nil {
log.Fatal("Error changing to 'main' directory:", err)
}
}()

//create identities
createPrimaryAndSecondaryIdentities(license)
if err := createPrimaryAndSecondaryIdentities(license); err != nil {
return err
}

//Decide Working Scenario
endpoints := []string{endpoint, endpoint}

if scan {
endpoints = wiresocks.RunScan()
var err error
endpoints, err = wiresocks.RunScan(ctx)
if err != nil {
return err
}
log.Println("Cooling down please wait 5 seconds...")
time.Sleep(5 * time.Second)
}

if !psiphonEnabled && !gool {
// just run primary warp on bindAddress
runWarp(bindAddress, endpoints, "./primary/wgcf-profile.ini", verbose, true, true)
_, _, err := runWarp(bindAddress, endpoints, "./primary/wgcf-profile.ini", verbose, true, ctx, true)
return err
} else if psiphonEnabled && !gool {
// run primary warp on a random tcp port and run psiphon on bind address
runWarpWithPsiphon(bindAddress, endpoints, country, verbose)
return runWarpWithPsiphon(bindAddress, endpoints, country, verbose, ctx)
} else if !psiphonEnabled && gool {
// run warp in warp
runWarpInWarp(bindAddress, endpoints, verbose)
return runWarpInWarp(bindAddress, endpoints, verbose, ctx)
}

//End Decide Working Scenario

// back where you where
if err := os.Chdir(".."); err != nil {
log.Fatal("Error changing to 'main' directory:", err)
}
return fmt.Errorf("unknown error, it seems core related issue")
}

func runWarp(bindAddress string, endpoints []string, confPath string, verbose, wait bool, startProxy bool) (*wiresocks.VirtualTun, int) {
// Setup channel to listen for interrupt signal (Ctrl+C)
var sigChan chan os.Signal
if wait {
sigChan = make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
}

func runWarp(bindAddress string, endpoints []string, confPath string, verbose, startProxy bool, ctx context.Context, showServing bool) (*wiresocks.VirtualTun, int, error) {
conf, err := wiresocks.ParseConfig(confPath, endpoints[0])
if err != nil {
log.Fatal(err)
log.Println(err)
return nil, 0, err
}

tnet, err := wiresocks.StartWireguard(conf.Device, verbose)
tnet, err := wiresocks.StartWireguard(conf.Device, verbose, ctx)
if err != nil {
log.Fatal(err)
log.Println(err)
return nil, 0, err
}

if startProxy {
go tnet.StartProxy(bindAddress)
tnet.StartProxy(bindAddress)
}

// Wait for interrupt signal
if wait {
if showServing {
log.Printf("Serving on %s\n", bindAddress)
<-sigChan
}

return tnet, conf.Device.MTU
return tnet, conf.Device.MTU, nil
}

func runWarpWithPsiphon(bindAddress string, endpoints []string, country string, verbose bool) {
func runWarpWithPsiphon(bindAddress string, endpoints []string, country string, verbose bool, ctx context.Context) error {
// make a random bind address for warp
warpBindAddress, err := findFreePort("tcp")
if err != nil {
log.Fatal("There are no free tcp ports on Device!")
log.Println("There are no free tcp ports on Device!")
return err
}

runWarp(warpBindAddress, endpoints, "./primary/wgcf-profile.ini", verbose, false, true)

// Setup channel to listen for interrupt signal (Ctrl+C)
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, os.Interrupt, syscall.SIGTERM)
_, _, err = runWarp(warpBindAddress, endpoints, "./primary/wgcf-profile.ini", verbose, true, ctx, false)
if err != nil {
return err
}

// run psiphon
psiphonCtx := psiphon.RunPsiphon(warpBindAddress, bindAddress, country)
err = psiphon.RunPsiphon(warpBindAddress, bindAddress, country, ctx)
if err != nil {
log.Printf("unable to run psiphon %v", err)
return fmt.Errorf("unable to run psiphon %v", err)
}

log.Printf("Serving on %s\n", bindAddress)
// Wait for interrupt signal
<-sigChan

psiphonCtx.Done()
return nil
}

func runWarpInWarp(bindAddress string, endpoints []string, verbose bool) {
func runWarpInWarp(bindAddress string, endpoints []string, verbose bool, ctx context.Context) error {
// run secondary warp
vTUN, mtu := runWarp("", endpoints, "./secondary/wgcf-profile.ini", verbose, false, false)
vTUN, mtu, err := runWarp("", endpoints, "./secondary/wgcf-profile.ini", verbose, false, ctx, false)
if err != nil {
return err
}

// run virtual endpoint
virtualEndpointBindAddress, err := findFreePort("udp")
if err != nil {
log.Fatal("There are no free udp ports on Device!")
log.Println("There are no free udp ports on Device!")
return err
}
addr := endpoints[1]
if addr == "notset" {
addr, _ = wiresocks.ResolveIPPAndPort("engage.cloudflareclient.com:2408")
}
err = wiresocks.NewVtunUDPForwarder(virtualEndpointBindAddress, addr, vTUN, mtu+100)
err = wiresocks.NewVtunUDPForwarder(virtualEndpointBindAddress, addr, vTUN, mtu+100, ctx)
if err != nil {
log.Fatal(err)
log.Println(err)
return err
}

// run primary warp
runWarp(bindAddress, []string{virtualEndpointBindAddress}, "./primary/wgcf-profile.ini", verbose, true, true)
_, _, err = runWarp(bindAddress, []string{virtualEndpointBindAddress}, "./primary/wgcf-profile.ini", verbose, true, ctx, true)
if err != nil {
return err
}
return nil
}

func findFreePort(network string) (string, error) {
Expand Down Expand Up @@ -161,7 +182,7 @@ func findFreePort(network string) (string, error) {
return addr, nil
}

func createPrimaryAndSecondaryIdentities(license string) {
func createPrimaryAndSecondaryIdentities(license string) error {
// make primary identity
_license := license
if _license == "notset" {
Expand All @@ -171,29 +192,33 @@ func createPrimaryAndSecondaryIdentities(license string) {
if !warp.CheckProfileExists(license) {
err := warp.LoadOrCreateIdentity(_license)
if err != nil {
log.Fatalf("error: %v", err)
log.Printf("error: %v", err)
return fmt.Errorf("error: %v", err)
}
}
// make secondary
warp.UpdatePath("./secondary")
if !warp.CheckProfileExists(license) {
err := warp.LoadOrCreateIdentity(_license)
if err != nil {
log.Fatalf("error: %v", err)
log.Printf("error: %v", err)
return fmt.Errorf("error: %v", err)
}
}
return nil
}

func makeDirs() {
func makeDirs() error {
stuffDir := "stuff"
primaryDir := "primary"
secondaryDir := "secondary"

// Check if 'stuff' directory exists, if not create it
if _, err := os.Stat(stuffDir); os.IsNotExist(err) {
fmt.Println("'stuff' directory does not exist, creating it...")
log.Println("'stuff' directory does not exist, creating it...")
if err := os.Mkdir(stuffDir, 0755); err != nil {
log.Fatal("Error creating 'stuff' directory:", err)
log.Println("Error creating 'stuff' directory:", err)
return errors.New("Error creating 'stuff' directory:" + err.Error())
}
}

Expand All @@ -202,17 +227,13 @@ func makeDirs() {
if _, err := os.Stat(filepath.Join(stuffDir, dir)); os.IsNotExist(err) {
log.Printf("Creating '%s' directory...\n", dir)
if err := os.Mkdir(filepath.Join(stuffDir, dir), 0755); err != nil {
log.Fatalf("Error creating '%s' directory: %v\n", dir, err)
log.Printf("Error creating '%s' directory: %v\n", dir, err)
return fmt.Errorf("Error creating '%s' directory: %v\n", dir, err)
}
}
}
log.Println("'primary' and 'secondary' directories are ready")

// Change the current working directory to 'stuff'
if err := os.Chdir(stuffDir); err != nil {
log.Fatal("Error changing to 'stuff' directory:", err)
}
log.Println("Changed working directory to 'stuff'")
return nil
}
func isPortOpen(address string, timeout time.Duration) bool {
// Try to establish a connection
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ require (
github.com/refraction-networking/conjure v0.7.10-0.20231110193225-e4749a9dedc9
github.com/refraction-networking/utls v1.3.3
golang.org/x/crypto v0.18.0
golang.org/x/net v0.17.0
golang.org/x/net v0.20.0
golang.org/x/sys v0.16.0
golang.zx2c4.com/wintun v0.0.0-20230126152724-0fa3db229ce2
gvisor.dev/gvisor v0.0.0-20230927004350-cbd86285d259
Expand Down Expand Up @@ -74,9 +74,9 @@ require (
go.uber.org/mock v0.3.0 // indirect
golang.org/x/exp v0.0.0-20230725093048-515e97ebf090 // indirect
golang.org/x/exp/typeparams v0.0.0-20240119083558-1b970713d09a // indirect
golang.org/x/mod v0.12.0 // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect
golang.org/x/tools v0.13.0 // indirect
golang.org/x/tools v0.17.0 // indirect
google.golang.org/protobuf v1.31.0 // indirect
)
18 changes: 17 additions & 1 deletion main.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
package main

import (
"context"
"flag"
"github.com/bepass-org/wireguard-go/app"
"log"
"os"
"os/signal"
"syscall"
)

func usage() {
Expand All @@ -26,5 +30,17 @@ func main() {
flag.Usage = usage
flag.Parse()

app.RunWarp(*psiphonEnabled, *gool, *scan, *verbose, *country, *bindAddress, *endpoint, *license)
sigchan := make(chan os.Signal)
signal.Notify(sigchan, os.Interrupt, syscall.SIGTERM)
ctx := context.Background()

go func() {
err := app.RunWarp(*psiphonEnabled, *gool, *scan, *verbose, *country, *bindAddress, *endpoint, *license, ctx)
if err != nil {
log.Fatal(err)
}
}()

<-sigchan
ctx.Done()
}
35 changes: 22 additions & 13 deletions psiphon/p.go
Original file line number Diff line number Diff line change
Expand Up @@ -315,12 +315,11 @@ func (tunnel *Tunnel) Stop() {
psiphon.CloseDataStore()
}

func RunPsiphon(wgBind, localSocksPort, country string) context.Context {
ctx := context.Background()
func RunPsiphon(wgBind, localSocksPort, country string, ctx context.Context) error {
// Embedded configuration
host, port, err := net.SplitHostPort(localSocksPort)
if err != nil {
log.Fatal(err)
return err
}
if strings.HasPrefix(host, "127.0.0") {
host = ""
Expand Down Expand Up @@ -359,18 +358,28 @@ func RunPsiphon(wgBind, localSocksPort, country string) context.Context {
var tunnel *Tunnel
startTime := time.Now()

go func() {
for {
tunnel, err = StartTunnel(ctx, []byte(configJSON), "", p, nil, nil)
internalCtx := context.Background()

timeoutTimer := time.NewTimer(2 * time.Minute)
defer timeoutTimer.Stop()

for {
select {
case <-ctx.Done():
internalCtx.Done()
return fmt.Errorf("psiphon handshake operation canceled by user")
case <-timeoutTimer.C:
// Handle the internal timeout
internalCtx.Done()
return fmt.Errorf("psiphon handshake maximum time exceeded")
default:
tunnel, err = StartTunnel(internalCtx, []byte(configJSON), "", p, nil, nil)
if err == nil {
break
log.Println("Psiphon started successfully on port", tunnel.SOCKSProxyPort, "handshake operation took", int64(time.Since(startTime)/time.Millisecond), "milliseconds")
return nil
}
log.Error("Unable to start psiphon", err, "reconnecting...")
time.Sleep(2 * time.Second)
time.Sleep(1 * time.Second)
}

log.Println("Psiphon started successfully on port", tunnel.SOCKSProxyPort, "handshake operation took", int64(time.Since(startTime)/time.Millisecond), "milliseconds")
}()

return ctx
}
}
Loading

0 comments on commit 6ffdfb0

Please sign in to comment.