forked from WireGuard/wireguard-go
-
Notifications
You must be signed in to change notification settings - Fork 273
/
Copy pathmain.go
249 lines (206 loc) · 6.52 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
package main
import (
"flag"
"fmt"
"github.com/uoosef/wireguard-go/psiphon"
"github.com/uoosef/wireguard-go/warp"
"github.com/uoosef/wireguard-go/wiresocks"
"log"
"net"
"os"
"os/signal"
"path/filepath"
"syscall"
"time"
)
func usage() {
log.Println("Usage: wiresocks [-v] [-b addr:port] [-l license] <config file path>")
flag.PrintDefaults()
}
func main() {
var (
verbose = flag.Bool("v", false, "verbose")
bindAddress = flag.String("b", "127.0.0.1:8086", "socks bind address")
endpoint = flag.String("e", "notset", "warp clean ip")
license = flag.String("k", "notset", "license key")
country = flag.String("country", "", "psiphon country code in ISO 3166-1 alpha-2 format")
psiphonEnabled = flag.Bool("cfon", false, "enable psiphonEnabled over warp")
gool = flag.Bool("gool", false, "enable warp gooling")
)
flag.Usage = usage
flag.Parse()
// check if user input is not correct
if (*psiphonEnabled && *gool) || (!*psiphonEnabled && *country != "") {
log.Println("Wrong command!")
flag.Usage()
return
}
//create necessary file structures
makeDirs()
//create identities
createPrimaryAndSecondaryIdentities(*license)
//Decide Working Scenario
if !*psiphonEnabled && !*gool {
// just run primary warp on bindAddress
runWarp(*bindAddress, *endpoint, "./primary/wgcf-profile.ini", *verbose, true, true)
} else if *psiphonEnabled && !*gool {
// run primary warp on a random tcp port and run psiphon on bind address
runWarpWithPsiphon(*bindAddress, *endpoint, *country, *verbose)
} else if !*psiphonEnabled && *gool {
// run warp in warp
runWarpInWarp(*bindAddress, *endpoint, *verbose)
}
//End Decide Working Scenario
// back where you where
if err := os.Chdir(".."); err != nil {
log.Fatal("Error changing to 'main' directory:", err)
}
}
func runWarp(bindAddress, endpoint, 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)
}
conf, err := wiresocks.ParseConfig(confPath, endpoint)
if err != nil {
log.Fatal(err)
}
tnet, err := wiresocks.StartWireguard(conf.Device, verbose)
if err != nil {
log.Fatal(err)
}
if startProxy {
go tnet.StartProxy(bindAddress)
}
// Wait for interrupt signal
if wait {
<-sigChan
}
return tnet, conf.Device.MTU
}
func runWarpWithPsiphon(bindAddress, endpoint, country string, verbose bool) {
// make a random bind address for warp
warpBindAddress, err := findFreePort("tcp")
if err != nil {
log.Fatal("There are no free tcp ports on Device!")
}
runWarp(warpBindAddress, endpoint, "./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)
// run psiphon
psiphonCtx := psiphon.RunPsiphon(warpBindAddress, bindAddress, country)
// Wait for interrupt signal
<-sigChan
psiphonCtx.Done()
}
func runWarpInWarp(bindAddress, endpoint string, verbose bool) {
// run secondary warp
vTUN, mtu := runWarp("", endpoint, "./secondary/wgcf-profile.ini", verbose, false, false)
// run virtual endpoint
virtualEndpointBindAddress, err := findFreePort("udp")
if err != nil {
log.Fatal("There are no free udp ports on Device!")
}
err = wiresocks.NewVtunUDPForwarder(virtualEndpointBindAddress, "162.159.195.1:2408", vTUN, mtu+100)
if err != nil {
log.Fatal(err)
}
// run primary warp
runWarp(bindAddress, virtualEndpointBindAddress, "./primary/wgcf-profile.ini", verbose, true, true)
}
func findFreePort(network string) (string, error) {
if network == "udp" {
addr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0")
if err != nil {
return "", err
}
conn, err := net.ListenUDP("udp", addr)
if err != nil {
return "", err
}
defer conn.Close()
return conn.LocalAddr().(*net.UDPAddr).String(), nil
}
// Listen on TCP port 0, which tells the OS to pick a free port.
listener, err := net.Listen(network, "127.0.0.1:0")
if err != nil {
return "", err // Return error if unable to listen on a port
}
defer listener.Close() // Ensure the listener is closed when the function returns
// Get the port from the listener's address
addr := listener.Addr().String()
return addr, nil
}
func createPrimaryAndSecondaryIdentities(license string) {
// make primary identity
warp.UpdatePath("./primary")
if !warp.CheckProfileExists(license) {
err := warp.LoadOrCreateIdentity(license)
if err != nil {
log.Fatalf("error: %v", err)
}
}
// make secondary
warp.UpdatePath("./secondary")
if !warp.CheckProfileExists(license) {
err := warp.LoadOrCreateIdentity(license)
if err != nil {
log.Fatalf("error: %v", err)
}
}
}
func makeDirs() {
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...")
if err := os.Mkdir(stuffDir, 0755); err != nil {
log.Fatal("Error creating 'stuff' directory:", err)
}
}
// Create 'primary' and 'secondary' directories if they don't exist
for _, dir := range []string{primaryDir, secondaryDir} {
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.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'")
}
func isPortOpen(address string, timeout time.Duration) bool {
// Try to establish a connection
conn, err := net.DialTimeout("tcp", address, timeout)
if err != nil {
return false
}
defer conn.Close()
return true
}
func waitForPortToGetsOpenOrTimeout(addressToCheck string) {
timeout := 5 * time.Second
checkInterval := 500 * time.Millisecond
// Set a deadline for when to stop checking
deadline := time.Now().Add(timeout)
for {
if time.Now().After(deadline) {
log.Fatalf("Timeout reached, port %s is not open", addressToCheck)
}
if isPortOpen(addressToCheck, checkInterval) {
log.Printf("Port %s is now open", addressToCheck)
break
}
time.Sleep(checkInterval)
}
}