2019-08-15 09:19:40 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"bufio"
|
2019-08-16 15:23:19 +00:00
|
|
|
"errors"
|
2019-08-15 09:19:40 +00:00
|
|
|
"fmt"
|
|
|
|
"net"
|
2019-08-16 15:23:19 +00:00
|
|
|
"strconv"
|
2019-08-15 09:19:40 +00:00
|
|
|
"sync"
|
2019-08-16 15:23:19 +00:00
|
|
|
|
|
|
|
"github.com/pyke369/golang-support/rcache"
|
2019-08-15 09:19:40 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
type OpenVpnSrv struct {
|
2019-08-16 15:23:19 +00:00
|
|
|
Remote string `json:"active-vpn"`
|
|
|
|
Status string `json:"status"`
|
|
|
|
Provider string `json:"provider"`
|
|
|
|
Identifier string `json:"identifier"`
|
|
|
|
chanHold chan bool
|
|
|
|
m sync.RWMutex
|
|
|
|
ret chan []string
|
|
|
|
buf *bufio.ReadWriter
|
|
|
|
mgt *OpenVpnMgt
|
|
|
|
hold bool
|
2019-08-15 09:19:40 +00:00
|
|
|
}
|
|
|
|
|
2019-08-16 15:23:19 +00:00
|
|
|
func (v *OpenVpnSrv) Lock() {
|
|
|
|
v.m.Lock()
|
2019-08-15 09:19:40 +00:00
|
|
|
}
|
|
|
|
|
2019-08-16 15:23:19 +00:00
|
|
|
func (v *OpenVpnSrv) Unlock() {
|
|
|
|
v.m.Unlock()
|
2019-08-15 09:19:40 +00:00
|
|
|
}
|
|
|
|
|
2019-08-16 15:23:19 +00:00
|
|
|
func NewOpenVpnSrv(conn net.Conn, mgt *OpenVpnMgt) *OpenVpnSrv {
|
2019-08-15 09:19:40 +00:00
|
|
|
return &OpenVpnSrv{
|
|
|
|
buf: bufio.NewReadWriter(bufio.NewReader(conn), bufio.NewWriter(conn)),
|
|
|
|
chanHold: make(chan bool),
|
|
|
|
ret: make(chan []string),
|
2019-08-16 15:23:19 +00:00
|
|
|
mgt: mgt,
|
|
|
|
hold: false,
|
2019-08-15 09:19:40 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// send a command to the server. Set the channel to receive the response
|
2019-08-16 15:23:19 +00:00
|
|
|
func (v *OpenVpnSrv) sendCommand(msg []string) (error, []string) {
|
|
|
|
v.Lock()
|
2019-08-15 09:19:40 +00:00
|
|
|
for _, line := range msg {
|
2019-08-16 15:23:19 +00:00
|
|
|
if _, err := v.buf.WriteString(line + "\r\n"); err != nil {
|
|
|
|
v.Unlock()
|
2019-08-15 09:19:40 +00:00
|
|
|
return err, nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-16 15:23:19 +00:00
|
|
|
if err := v.buf.Flush(); err != nil {
|
2019-08-15 09:19:40 +00:00
|
|
|
return err, nil
|
|
|
|
}
|
2019-08-16 15:23:19 +00:00
|
|
|
v.Unlock()
|
2019-08-15 09:19:40 +00:00
|
|
|
|
|
|
|
// wait for the response
|
2019-08-16 15:23:19 +00:00
|
|
|
ret := <-v.ret
|
2019-08-15 09:19:40 +00:00
|
|
|
|
|
|
|
return nil, ret
|
|
|
|
}
|
|
|
|
|
2019-08-16 15:23:19 +00:00
|
|
|
func (v *OpenVpnSrv) Signal(signal string) error {
|
|
|
|
for _, valid := range []string{"SIGHUP", "SIGTERM"} {
|
|
|
|
if signal == valid {
|
|
|
|
err, _ := v.sendCommand([]string{fmt.Sprintf("signal %s", signal)})
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return errors.New("unknown signal")
|
2019-08-15 09:19:40 +00:00
|
|
|
}
|
|
|
|
|
2019-08-16 15:23:19 +00:00
|
|
|
func (v *OpenVpnSrv) GetPid() error {
|
|
|
|
err, infos := v.sendCommand([]string{"pid"})
|
|
|
|
if err != nil {
|
|
|
|
v.mgt.Debug(err)
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
pidRegexp := rcache.Get("^SUCCESS: pid=([0-9]+)$")
|
|
|
|
for _, line := range infos {
|
|
|
|
match := pidRegexp.FindStringSubmatch(line)
|
|
|
|
if len(match) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
if len(match) == 2 {
|
|
|
|
pid, err := strconv.Atoi(match[1])
|
|
|
|
if err == nil {
|
|
|
|
v.mgt.SetPid(v, pid)
|
|
|
|
v.mgt.Debug("Found PID", pid)
|
|
|
|
}
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
}
|
|
|
|
v.mgt.Debug("Can't find PID")
|
|
|
|
return errors.New("Can't find PID")
|
2019-08-15 09:19:40 +00:00
|
|
|
}
|
|
|
|
|
2019-08-16 15:23:19 +00:00
|
|
|
func (v *OpenVpnSrv) GetEcho() {
|
|
|
|
err, infos := v.sendCommand([]string{"echo all"})
|
|
|
|
if err != nil {
|
2019-08-15 09:19:40 +00:00
|
|
|
return
|
|
|
|
}
|
2019-08-16 15:23:19 +00:00
|
|
|
echoRegexp := rcache.Get("^[0-9]+,([A-Za-z0-9-]*):([A-Za-z0-9-]*)$")
|
|
|
|
for _, line := range infos {
|
|
|
|
match := echoRegexp.FindStringSubmatch(line)
|
|
|
|
if len(match) == 0 {
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
|
|
|
|
switch match[1] {
|
|
|
|
case "vpnidentifier":
|
|
|
|
v.Identifier = match[2]
|
|
|
|
case "vpnprovider":
|
|
|
|
if err := v.mgt.getServerList(match[2]); err != nil {
|
|
|
|
v.mgt.Debug(err)
|
|
|
|
|
|
|
|
continue
|
|
|
|
}
|
|
|
|
v.Provider = match[2]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-08-15 09:19:40 +00:00
|
|
|
}
|
|
|
|
|
2019-08-16 15:23:19 +00:00
|
|
|
func (v *OpenVpnSrv) Response(response []string) {
|
|
|
|
v.Lock()
|
|
|
|
v.ret <- response
|
|
|
|
v.Unlock()
|
2019-08-15 09:19:40 +00:00
|
|
|
}
|
|
|
|
|
2019-08-16 15:23:19 +00:00
|
|
|
func (v *OpenVpnSrv) GetLine() (string, error) {
|
|
|
|
return v.buf.ReadString('\n')
|
2019-08-15 09:19:40 +00:00
|
|
|
}
|
|
|
|
|
2019-08-16 15:23:19 +00:00
|
|
|
func (v *OpenVpnSrv) ValidRemote(server, port, proto string) {
|
|
|
|
if v.Remote != "" {
|
|
|
|
v.sendCommand([]string{fmt.Sprintf("remote MOD %s %s %s", v.Remote, port, proto)})
|
|
|
|
v.Status = "Connected"
|
|
|
|
return
|
|
|
|
}
|
|
|
|
v.Remote = server
|
|
|
|
v.sendCommand([]string{"remote ACCEPT"})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v *OpenVpnSrv) Version() (error, []string) {
|
|
|
|
return v.sendCommand([]string{"version"})
|
|
|
|
}
|
|
|
|
|
|
|
|
func (v *OpenVpnSrv) SetRemote(server string) error {
|
2019-08-15 09:19:40 +00:00
|
|
|
// already the active server, do nothing
|
2019-08-16 15:23:19 +00:00
|
|
|
if v.Remote == server {
|
2019-08-15 09:19:40 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-08-16 15:23:19 +00:00
|
|
|
if v.Remote != "" {
|
|
|
|
v.Remote = server
|
|
|
|
v.Signal("SIGHUP")
|
|
|
|
v.Status = "Reloaded"
|
2019-08-15 09:19:40 +00:00
|
|
|
}
|
|
|
|
|
2019-08-16 15:23:19 +00:00
|
|
|
v.Remote = server
|
2019-08-15 09:19:40 +00:00
|
|
|
|
|
|
|
// release Hold if necessary
|
2019-08-16 15:23:19 +00:00
|
|
|
v.ReleaseHold()
|
2019-08-15 09:19:40 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2019-08-16 15:23:19 +00:00
|
|
|
func (v *OpenVpnSrv) waitForRelase() {
|
|
|
|
v.Status = "Hold"
|
|
|
|
if v.hold {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
v.hold = true
|
|
|
|
<-v.chanHold
|
|
|
|
v.sendCommand([]string{"hold release"})
|
|
|
|
v.sendCommand([]string{"hold off"})
|
2019-08-15 09:19:40 +00:00
|
|
|
}
|
|
|
|
|
2019-08-16 15:23:19 +00:00
|
|
|
func (v *OpenVpnSrv) ReleaseHold() {
|
|
|
|
if !v.hold {
|
2019-08-15 09:19:40 +00:00
|
|
|
return
|
|
|
|
}
|
2019-08-16 15:23:19 +00:00
|
|
|
v.hold = false
|
|
|
|
v.chanHold <- true
|
|
|
|
v.Status = "Waiting for connexion"
|
2019-08-15 09:19:40 +00:00
|
|
|
}
|