-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.go
131 lines (109 loc) · 2.94 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
package main
import (
"flag"
"fmt"
"io"
"log"
"os"
"path"
"regexp"
"runtime"
"strconv"
"awsvpn/awsvpn"
"awsvpn/openvpn"
)
const (
defaultPort = 443
defaultProto = "udp"
)
var (
confRemoteRegexp = regexp.MustCompile(`(?m)^remote\s+(\S+)`)
confPortRegexp = regexp.MustCompile(`(?m)(^remote\s+\S+\s+|port\s+)([0-9]+)`)
confProtoRegexp = regexp.MustCompile(`(?m)(^remote\s+\S+\s+[0-9]+\s+|proto\s+)(tcp[46]?|udp[46]?)`)
caSectionRegexp = regexp.MustCompile(`(?s)<ca>(.*)</ca>`)
)
func defaultOpenVPNConfig() string {
home, err := os.UserHomeDir()
if err != nil {
log.Fatalln(err)
}
return path.Join(home, ".awsvpn.ovpn")
}
func defaultBrowser() string {
switch runtime.GOOS {
case "windows": // no idea what else to use here :)
return "explorer.exe"
case "darwin": // better override it with "open -g -a YOUR_BROWSER_NAME"
return "open"
default: // let's try good old xdg
return "xdg-open"
}
}
func defaultOpenVPNClient() string {
switch runtime.GOOS {
case "windows": // no idea how this thing works :)
return "C:\\Program Files\\OpenVPN\\OpenVPN.exe"
case "darwin": // using native AWS client
return "/Applications/AWS VPN Client/AWS VPN Client.app/Contents/Resources/openvpn/acvc-openvpn"
default: // assuming it's a *nix OS, and we have a customly build OpenVPN client
return "/opt/aws-openvpn/bin/openvpn"
}
}
var (
configPath = flag.String("config", defaultOpenVPNConfig(), "Absolute path to the config file (OpenVPN-compatible)")
browserCmd = flag.String("browser", defaultBrowser(), "Command used to open the authorization URL")
openVPNCommand = flag.String("openvpn", defaultOpenVPNClient(), "Absolute path to the OpenVPN binary")
)
func parseOpenVPNConfig(cmd string, cfgPath string) (*openvpn.Config, error) {
f, err := os.Open(cfgPath)
if err != nil {
return nil, fmt.Errorf("config: %w", err)
}
defer f.Close()
b, err := io.ReadAll(f)
if err != nil {
return nil, fmt.Errorf("config: %w", err)
}
// ca
ca := caSectionRegexp.FindSubmatch(b)
if ca == nil {
return nil, fmt.Errorf("config: <ca> section not found in the config")
}
// remote
remote := confRemoteRegexp.FindSubmatch(b)
if remote == nil {
return nil, fmt.Errorf("config: remote not found in the config")
}
cfg := &openvpn.Config{
Command: cmd,
CACertificate: string(ca[1]),
Remote: string(remote[1]),
Port: defaultPort,
Proto: defaultProto,
}
// port
if p := confPortRegexp.FindSubmatch(b); p != nil {
port, err := strconv.Atoi(string(p[2]))
if err != nil {
return nil, fmt.Errorf("config: invalid port: %s", string(p[2]))
}
cfg.Port = port
}
// proto
if p := confProtoRegexp.FindSubmatch(b); p != nil {
cfg.Proto = string(p[2])
}
return cfg, nil
}
func main() {
flag.Parse()
cfg, err := parseOpenVPNConfig(*openVPNCommand, *configPath)
if err != nil {
log.Fatal(err)
}
app, err := awsvpn.NewApp(*cfg, *browserCmd)
if err != nil {
log.Fatalln(err)
}
app.Start()
}