forked from txthinking/brook
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vpn.go
120 lines (112 loc) · 2.54 KB
/
vpn.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
package brook
import (
"errors"
"fmt"
"log"
"net"
"os"
"os/signal"
"syscall"
"github.com/txthinking/brook/sysproxy"
"github.com/txthinking/gotun2socks"
"github.com/txthinking/gotun2socks/tun"
)
// VPN
type VPN struct {
Client *Client
Tunnel *Tunnel
Tun *gotun2socks.Tun2Socks
ServerIP string
TunGateway string
DefaultGateway string
}
// NewVPN
func NewVPN(addr, server, password string, tcpTimeout, tcpDeadline, udpDeadline, udpSessionTime int, tunDevice, tunIP, tunGateway, tunMask, defaultGateway string) (*VPN, error) {
h, _, err := net.SplitHostPort(addr)
if err != nil {
return nil, err
}
if h != "127.0.0.1" {
return nil, errors.New("Must listen on 127.0.0.1")
}
h, _, err = net.SplitHostPort(server)
if err != nil {
return nil, err
}
c, err := NewClient(addr, "127.0.0.1", server, password, tcpTimeout, tcpDeadline, udpDeadline, udpSessionTime)
if err != nil {
return nil, err
}
tl, err := NewTunnel("127.0.0.1:53", "8.8.8.8:53", server, password, tcpTimeout, tcpDeadline, udpDeadline)
if err != nil {
return nil, err
}
f, err := tun.OpenTunDevice(tunDevice, tunIP, tunGateway, tunMask, []string{"8.8.8.8"})
if err != nil {
return nil, err
}
t := gotun2socks.New(f, addr, []string{"8.8.8.8"}, true, true)
return &VPN{
Client: c,
Tunnel: tl,
Tun: t,
ServerIP: h,
TunGateway: tunGateway,
DefaultGateway: defaultGateway,
}, nil
}
// ListenAndServe starts to run VPN
func (v *VPN) ListenAndServe() error {
if err := sysproxy.SetDNSServer("127.0.0.1"); err != nil {
return err
}
if err := v.AddRoutes(); err != nil {
return err
}
errch := make(chan error)
go func() {
errch <- v.Client.ListenAndServe()
}()
go func() {
errch <- v.Tunnel.ListenAndServe()
}()
go func() {
v.Tun.Run()
}()
go func() {
sigs := make(chan os.Signal, 1)
signal.Notify(sigs, syscall.SIGINT, syscall.SIGTERM, syscall.SIGHUP, syscall.SIGQUIT)
<-sigs
errch <- nil
}()
fmt.Println("Ctrl-C to quit")
err := <-errch
if err := v.Shutdown(); err != nil {
return err
}
return err
}
// Shutdown stops VPN
func (v *VPN) Shutdown() error {
fmt.Println("Quitting...")
if err := sysproxy.SetDNSServer("8.8.8.8"); err != nil {
log.Println(err)
}
if err := v.DeleteRoutes(); err != nil {
log.Println(err)
}
if v.Client != nil {
if err := v.Client.Shutdown(); err != nil {
log.Println(err)
}
}
if v.Tunnel != nil {
if err := v.Tunnel.Shutdown(); err != nil {
log.Println(err)
}
}
if v.Tun != nil {
// v.Tun.Stop()
}
return nil
}