1
0

vpn.go 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779
  1. //go:generate go-bindata -pkg bindata -o bindata/bindata.go template/
  2. //go:generate protoc -I pb/ -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis pb/user.proto pb/vpn.proto pb/network.proto --go_out=plugins=grpc:pb
  3. //go:generate protoc -I pb/ -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis pb/user.proto pb/vpn.proto pb/network.proto --grpc-gateway_out=logtostderr=true:pb
  4. //go:generate protoc -I pb/ -I$GOPATH/src/github.com/grpc-ecosystem/grpc-gateway/third_party/googleapis pb/user.proto pb/vpn.proto pb/network.proto --swagger_out=logtostderr=true:pb
  5. package ovpm
  6. import (
  7. "bytes"
  8. "fmt"
  9. "math/big"
  10. "net"
  11. "os"
  12. "os/exec"
  13. "strings"
  14. "text/template"
  15. "time"
  16. "github.com/Sirupsen/logrus"
  17. "github.com/asaskevich/govalidator"
  18. "github.com/cad/ovpm/bindata"
  19. "github.com/cad/ovpm/pki"
  20. "github.com/cad/ovpm/supervisor"
  21. "github.com/coreos/go-iptables/iptables"
  22. "github.com/google/uuid"
  23. "github.com/jinzhu/gorm"
  24. )
  25. // Possible VPN protocols.
  26. const (
  27. TCPProto string = "tcp"
  28. UDPProto string = "udp"
  29. )
  30. // DBServer is database model for storing VPN server related stuff.
  31. type DBServer struct {
  32. gorm.Model
  33. Name string `gorm:"unique_index"` // Server name.
  34. SerialNumber string
  35. Hostname string // Server's ip address or FQDN
  36. Port string // Server's listening port
  37. Proto string // Server's proto udp or tcp
  38. Cert string // Server RSA certificate.
  39. Key string // Server RSA private key.
  40. CACert string // Root CA RSA certificate.
  41. CAKey string // Root CA RSA key.
  42. Net string // VPN network.
  43. Mask string // VPN network mask.
  44. CRL string // Certificate Revocation List
  45. }
  46. // CheckSerial takes a serial number and checks it against the current server's serial number.
  47. func (s *DBServer) CheckSerial(serial string) bool {
  48. return serial == s.SerialNumber
  49. }
  50. type _VPNServerConfig struct {
  51. CertPath string
  52. KeyPath string
  53. CACertPath string
  54. CAKeyPath string
  55. CCDPath string
  56. CRLPath string
  57. DHParamsPath string
  58. Net string
  59. Mask string
  60. Port string
  61. Proto string
  62. }
  63. // Init regenerates keys and certs for a Root CA, gets initial settings for the VPN server
  64. // and saves them in the database.
  65. //
  66. // 'proto' can be either "udp" or "tcp" and if it's "" it defaults to "udp".
  67. //
  68. // 'ipblock' is a IP network in the CIDR form. VPN clients get their IP addresses from this network.
  69. // It defaults to const 'DefaultVPNNetwork'.
  70. //
  71. // Please note that, Init is potentially destructive procedure, it will cause invalidation of
  72. // existing .ovpn profiles of the current users. So it should be used carefully.
  73. func Init(hostname string, port string, proto string, ipblock string) error {
  74. if port == "" {
  75. port = DefaultVPNPort
  76. }
  77. switch proto {
  78. case "":
  79. proto = UDPProto
  80. case UDPProto:
  81. proto = UDPProto
  82. case TCPProto:
  83. proto = TCPProto
  84. default:
  85. return fmt.Errorf("validation error: proto:`%s` should be either 'tcp' or 'udp'", proto)
  86. }
  87. // vpn network to use.
  88. var ipnet *net.IPNet
  89. // If user didn't specify, pick the vpn network from defaults.
  90. if ipblock == "" {
  91. var err error
  92. _, ipnet, err = net.ParseCIDR(DefaultVPNNetwork)
  93. if err != nil {
  94. return fmt.Errorf("can not parse CIDR %s: %v", DefaultVPNNetwork, err)
  95. }
  96. }
  97. // Check if the user specified vpn network is valid.
  98. if ipblock != "" && !govalidator.IsCIDR(ipblock) {
  99. return fmt.Errorf("validation error: ipblock:`%s` should be a CIDR network", ipblock)
  100. }
  101. // Use user specified vpn network.
  102. if ipblock != "" {
  103. var err error
  104. _, ipnet, err = net.ParseCIDR(ipblock)
  105. if err != nil {
  106. return fmt.Errorf("can parse ipblock: %s", err)
  107. }
  108. }
  109. if !govalidator.IsNumeric(port) {
  110. return fmt.Errorf("validation error: port:`%s` should be numeric", port)
  111. }
  112. serverName := "default"
  113. if IsInitialized() {
  114. if err := Deinit(); err != nil {
  115. logrus.Errorf("server can not be deleted: %v", err)
  116. return err
  117. }
  118. }
  119. if !govalidator.IsHost(hostname) {
  120. return fmt.Errorf("validation error: hostname:`%s` should be either an ip address or a FQDN", hostname)
  121. }
  122. ca, err := pki.NewCA()
  123. if err != nil {
  124. return fmt.Errorf("can not create ca creds: %s", err)
  125. }
  126. srv, err := pki.NewServerCertHolder(ca)
  127. if err != nil {
  128. return fmt.Errorf("can not create server cert creds: %s", err)
  129. }
  130. serialNumber := uuid.New().String()
  131. serverInstance := DBServer{
  132. Name: serverName,
  133. SerialNumber: serialNumber,
  134. Hostname: hostname,
  135. Proto: proto,
  136. Port: port,
  137. Cert: srv.Cert,
  138. Key: srv.Key,
  139. CACert: ca.Cert,
  140. CAKey: ca.Key,
  141. Net: ipnet.IP.To4().String(),
  142. Mask: net.IP(ipnet.Mask).To4().String(),
  143. }
  144. db.Create(&serverInstance)
  145. if db.NewRecord(&serverInstance) {
  146. return fmt.Errorf("can not create server instance on database")
  147. }
  148. users, err := GetAllUsers()
  149. if err != nil {
  150. return err
  151. }
  152. // Sign all users in the db with the new server
  153. for _, user := range users {
  154. err := user.Renew()
  155. logrus.Infof("user certificate changed for %s, you should run: $ ovpm user export-config --user %s", user.Username, user.Username)
  156. if err != nil {
  157. logrus.Errorf("can not sign user %s: %v", user.Username, err)
  158. continue
  159. }
  160. }
  161. Emit()
  162. logrus.Infof("server initialized")
  163. return nil
  164. }
  165. // Deinit deletes the server with the given serverName from the database and frees the allocated resources.
  166. func Deinit() error {
  167. if !IsInitialized() {
  168. return fmt.Errorf("server not found")
  169. }
  170. db.Unscoped().Delete(&DBServer{})
  171. db.Unscoped().Delete(&DBRevoked{})
  172. Emit()
  173. return nil
  174. }
  175. // DumpsClientConfig generates .ovpn file for the given vpn user and returns it as a string.
  176. func DumpsClientConfig(username string) (string, error) {
  177. var result bytes.Buffer
  178. user, err := GetUser(username)
  179. if err != nil {
  180. return "", err
  181. }
  182. server, err := GetServerInstance()
  183. if err != nil {
  184. return "", err
  185. }
  186. params := struct {
  187. Hostname string
  188. Port string
  189. CA string
  190. Key string
  191. Cert string
  192. NoGW bool
  193. Proto string
  194. }{
  195. Hostname: server.Hostname,
  196. Port: server.Port,
  197. CA: server.CACert,
  198. Key: user.Key,
  199. Cert: user.Cert,
  200. NoGW: user.NoGW,
  201. Proto: server.GetProto(),
  202. }
  203. data, err := bindata.Asset("template/client.ovpn.tmpl")
  204. if err != nil {
  205. return "", err
  206. }
  207. t, err := template.New("client.ovpn").Parse(string(data))
  208. if err != nil {
  209. return "", fmt.Errorf("can not parse client.ovpn.tmpl template: %s", err)
  210. }
  211. err = t.Execute(&result, params)
  212. if err != nil {
  213. return "", fmt.Errorf("can not render client.ovpn: %s", err)
  214. }
  215. return result.String(), nil
  216. }
  217. // DumpClientConfig generates .ovpn file for the given vpn user and dumps it to outPath.
  218. func DumpClientConfig(username, path string) error {
  219. result, err := DumpsClientConfig(username)
  220. if err != nil {
  221. return err
  222. }
  223. // Wite rendered content into openvpn server conf.
  224. return emitToFile(path, result, 0)
  225. }
  226. // GetSystemCA returns the system CA from the database if available.
  227. func GetSystemCA() (*pki.CA, error) {
  228. server := DBServer{}
  229. db.First(&server)
  230. if db.NewRecord(&server) {
  231. return nil, fmt.Errorf("server record does not exists in db")
  232. }
  233. return &pki.CA{
  234. CertHolder: pki.CertHolder{
  235. Cert: server.CACert,
  236. Key: server.CAKey,
  237. },
  238. }, nil
  239. }
  240. // vpnProc represents the OpenVPN process that is managed by the ovpm supervisor globally OpenVPN.
  241. var vpnProc supervisor.Supervisable
  242. // StartVPNProc starts the OpenVPN process.
  243. func StartVPNProc() {
  244. if !IsInitialized() {
  245. logrus.Error("can not launch OpenVPN because system is not initialized")
  246. return
  247. }
  248. if vpnProc == nil {
  249. panic(fmt.Sprintf("vpnProc is not initialized!"))
  250. }
  251. if vpnProc.Status() == supervisor.RUNNING {
  252. logrus.Error("OpenVPN is already started")
  253. return
  254. }
  255. vpnProc.Start()
  256. ensureNatEnabled()
  257. }
  258. // RestartVPNProc restarts the OpenVPN process.
  259. func RestartVPNProc() {
  260. if !IsInitialized() {
  261. logrus.Error("can not launch OpenVPN because system is not initialized")
  262. return
  263. }
  264. if vpnProc == nil {
  265. panic(fmt.Sprintf("vpnProc is not initialized!"))
  266. }
  267. vpnProc.Restart()
  268. ensureNatEnabled()
  269. }
  270. // StopVPNProc stops the OpenVPN process.
  271. func StopVPNProc() {
  272. if vpnProc == nil {
  273. panic(fmt.Sprintf("vpnProc is not initialized!"))
  274. }
  275. if vpnProc.Status() != supervisor.RUNNING {
  276. logrus.Error("OpenVPN is already not running")
  277. return
  278. }
  279. vpnProc.Stop()
  280. }
  281. // Emit generates all needed files for the OpenVPN server and dumps them to their corresponding paths defined in the config.
  282. func Emit() error {
  283. // Check dependencies
  284. if !checkOpenVPNExecutable() {
  285. return fmt.Errorf("openvpn executable can not be found! you should install OpenVPN on this machine")
  286. }
  287. if !checkOpenSSLExecutable() {
  288. return fmt.Errorf("openssl executable can not be found! you should install openssl on this machine")
  289. }
  290. if !checkIptablesExecutable() {
  291. return fmt.Errorf("iptables executable can not be found")
  292. }
  293. if !IsInitialized() {
  294. return fmt.Errorf("you should create a server first. e.g. $ ovpm vpn create-server")
  295. }
  296. if err := emitServerConf(); err != nil {
  297. return fmt.Errorf("can not emit server conf: %s", err)
  298. }
  299. if err := emitServerCert(); err != nil {
  300. return fmt.Errorf("can not emit server cert: %s", err)
  301. }
  302. if err := emitServerKey(); err != nil {
  303. return fmt.Errorf("can not emit server key: %s", err)
  304. }
  305. if err := emitCACert(); err != nil {
  306. return fmt.Errorf("can not emit ca cert : %s", err)
  307. }
  308. if err := emitCAKey(); err != nil {
  309. return fmt.Errorf("can not emit ca key: %s", err)
  310. }
  311. if err := emitDHParams(); err != nil {
  312. return fmt.Errorf("can not emit dhparams: %s", err)
  313. }
  314. if err := emitCCD(); err != nil {
  315. return fmt.Errorf("can not emit ccd: %s", err)
  316. }
  317. if err := emitIptables(); err != nil {
  318. return fmt.Errorf("can not emit iptables: %s", err)
  319. }
  320. if err := emitCRL(); err != nil {
  321. return fmt.Errorf("can not emit crl: %s", err)
  322. }
  323. logrus.Info("configurations emitted to the filesystem")
  324. if IsInitialized() {
  325. for {
  326. if vpnProc.Status() == supervisor.RUNNING || vpnProc.Status() == supervisor.STOPPED {
  327. logrus.Info("OpenVPN process is restarting")
  328. RestartVPNProc()
  329. break
  330. }
  331. time.Sleep(1 * time.Second)
  332. }
  333. }
  334. return nil
  335. }
  336. func emitToFile(path, content string, mode uint) error {
  337. // When testing don't emit files to the filesystem. Just pretend you did.
  338. if Testing {
  339. return nil
  340. }
  341. file, err := os.Create(path)
  342. if err != nil {
  343. return fmt.Errorf("Cannot create file %s: %v", path, err)
  344. }
  345. if mode != 0 {
  346. file.Chmod(os.FileMode(mode))
  347. }
  348. defer file.Close()
  349. fmt.Fprintf(file, content)
  350. return nil
  351. }
  352. func emitServerConf() error {
  353. dbServer, err := GetServerInstance()
  354. if err != nil {
  355. return fmt.Errorf("can not get server instance: %v", err)
  356. }
  357. serverInstance, err := GetServerInstance()
  358. if err != nil {
  359. return fmt.Errorf("can not retrieve server: %v", err)
  360. }
  361. port := DefaultVPNPort
  362. if serverInstance.Port != "" {
  363. port = serverInstance.Port
  364. }
  365. proto := DefaultVPNProto
  366. if serverInstance.Proto != "" {
  367. proto = serverInstance.Proto
  368. }
  369. var result bytes.Buffer
  370. server := _VPNServerConfig{
  371. CertPath: _DefaultCertPath,
  372. KeyPath: _DefaultKeyPath,
  373. CACertPath: _DefaultCACertPath,
  374. CAKeyPath: _DefaultCAKeyPath,
  375. CCDPath: _DefaultVPNCCDPath,
  376. CRLPath: _DefaultCRLPath,
  377. DHParamsPath: _DefaultDHParamsPath,
  378. Net: dbServer.Net,
  379. Mask: dbServer.Mask,
  380. Port: port,
  381. Proto: proto,
  382. }
  383. data, err := bindata.Asset("template/server.conf.tmpl")
  384. if err != nil {
  385. return err
  386. }
  387. t, err := template.New("server.conf").Parse(string(data))
  388. if err != nil {
  389. return fmt.Errorf("can not parse server.conf.tmpl template: %s", err)
  390. }
  391. err = t.Execute(&result, server)
  392. if err != nil {
  393. return fmt.Errorf("can not render server.conf: %s", err)
  394. }
  395. // Wite rendered content into openvpn server conf.
  396. return emitToFile(_DefaultVPNConfPath, result.String(), 0)
  397. }
  398. // GetServerInstance returns the default server from the database.
  399. func GetServerInstance() (*DBServer, error) {
  400. var server DBServer
  401. db.First(&server)
  402. if db.NewRecord(server) {
  403. return nil, fmt.Errorf("can not retrieve server from db")
  404. }
  405. return &server, nil
  406. }
  407. // GetProto returns the current VPN proto.
  408. func (s *DBServer) GetProto() string {
  409. if s.Proto != "" {
  410. return s.Proto
  411. }
  412. return UDPProto
  413. }
  414. // IsInitialized checks if there is a default server in the database or not.
  415. func IsInitialized() bool {
  416. var server DBServer
  417. db.First(&server)
  418. if db.NewRecord(server) {
  419. return false
  420. }
  421. return true
  422. }
  423. func emitServerKey() error {
  424. server, err := GetServerInstance()
  425. if err != nil {
  426. return err
  427. }
  428. // Write rendered content into key file.
  429. return emitToFile(_DefaultKeyPath, server.Key, 0600)
  430. }
  431. func emitServerCert() error {
  432. server, err := GetServerInstance()
  433. if err != nil {
  434. return err
  435. }
  436. // Write rendered content into the cert file.
  437. return emitToFile(_DefaultCertPath, server.Cert, 0)
  438. }
  439. func emitCRL() error {
  440. var revokedDBItems []*DBRevoked
  441. db.Find(&revokedDBItems)
  442. var revokedCertSerials []*big.Int
  443. for _, item := range revokedDBItems {
  444. bi := big.NewInt(0)
  445. bi.SetString(item.SerialNumber, 16)
  446. revokedCertSerials = append(revokedCertSerials, bi)
  447. }
  448. systemCA, err := GetSystemCA()
  449. if err != nil {
  450. return fmt.Errorf("can not emit CRL: %v", err)
  451. }
  452. crl, err := pki.NewCRL(systemCA, revokedCertSerials...)
  453. if err != nil {
  454. return fmt.Errorf("can not emit crl: %v", err)
  455. }
  456. return emitToFile(_DefaultCRLPath, crl, 0)
  457. }
  458. func emitCACert() error {
  459. server, err := GetServerInstance()
  460. if err != nil {
  461. return err
  462. }
  463. // Write rendered content into the ca cert file.
  464. return emitToFile(_DefaultCACertPath, server.CACert, 0)
  465. }
  466. func emitCAKey() error {
  467. server, err := GetServerInstance()
  468. if err != nil {
  469. return err
  470. }
  471. // Write rendered content into the ca key file.
  472. return emitToFile(_DefaultCAKeyPath, server.CAKey, 0600)
  473. }
  474. func emitCCD() error {
  475. users, err := GetAllUsers()
  476. if err != nil {
  477. return err
  478. }
  479. // Filesystem related stuff. Skipping when testing.
  480. if !Testing {
  481. // Clean and then create and write rendered ccd data.
  482. err = os.RemoveAll(_DefaultVPNCCDPath)
  483. if err != nil {
  484. if os.IsNotExist(err) {
  485. } else {
  486. return err
  487. }
  488. }
  489. if _, err := os.Stat(_DefaultVPNCCDPath); err != nil {
  490. }
  491. err = os.Mkdir(_DefaultVPNCCDPath, 0755)
  492. if err != nil {
  493. if !os.IsExist(err) {
  494. return err
  495. }
  496. }
  497. }
  498. server, err := GetServerInstance()
  499. if err != nil {
  500. return fmt.Errorf("can not get server instance: %v", err)
  501. }
  502. // Render ccd templates for the users.
  503. for _, user := range users {
  504. var associatedRoutes [][3]string
  505. for _, network := range GetAllNetworks() {
  506. switch network.Type {
  507. case ROUTE:
  508. for _, assocUsername := range network.GetAssociatedUsernames() {
  509. if assocUsername == user.Username {
  510. via := network.Via
  511. ip, mask, err := net.ParseCIDR(network.CIDR)
  512. if err != nil {
  513. return err
  514. }
  515. associatedRoutes = append(associatedRoutes, [3]string{ip.To4().String(), net.IP(mask.Mask).To4().String(), via})
  516. }
  517. }
  518. }
  519. }
  520. var result bytes.Buffer
  521. params := struct {
  522. IP string
  523. NetMask string
  524. Routes [][3]string // [0] is IP, [1] is Netmask, [2] is Via
  525. RedirectGW bool
  526. }{IP: user.getIP().String(), NetMask: server.Mask, Routes: associatedRoutes, RedirectGW: !user.NoGW}
  527. data, err := bindata.Asset("template/ccd.file.tmpl")
  528. if err != nil {
  529. return err
  530. }
  531. t, err := template.New("ccd.file.tmpl").Parse(string(data))
  532. if err != nil {
  533. return fmt.Errorf("can not parse ccd.file.tmpl template: %s", err)
  534. }
  535. err = t.Execute(&result, params)
  536. if err != nil {
  537. return fmt.Errorf("can not render ccd file %s: %s", user.Username, err)
  538. }
  539. err = emitToFile(_DefaultVPNCCDPath+user.Username, result.String(), 0)
  540. if err != nil {
  541. return err
  542. }
  543. }
  544. return nil
  545. }
  546. func emitDHParams() error {
  547. var result bytes.Buffer
  548. data, err := bindata.Asset("template/dh4096.pem.tmpl")
  549. if err != nil {
  550. return err
  551. }
  552. t, err := template.New("dh4096.pem.tmpl").Parse(string(data))
  553. if err != nil {
  554. return fmt.Errorf("can not parse dh4096.pem template: %s", err)
  555. }
  556. err = t.Execute(&result, nil)
  557. if err != nil {
  558. return fmt.Errorf("can not render dh4096.pem file: %s", err)
  559. }
  560. err = emitToFile(_DefaultDHParamsPath, result.String(), 0)
  561. if err != nil {
  562. return err
  563. }
  564. return nil
  565. }
  566. func emitIptables() error {
  567. if Testing {
  568. return nil
  569. }
  570. ipt, err := iptables.NewWithProtocol(iptables.ProtocolIPv4)
  571. if err != nil {
  572. return fmt.Errorf("can not create new iptables object: %v", err)
  573. }
  574. for _, network := range GetAllNetworks() {
  575. associatedUsernames := network.GetAssociatedUsernames()
  576. switch network.Type {
  577. case SERVERNET:
  578. users, err := GetAllUsers()
  579. if err != nil {
  580. return err
  581. }
  582. for _, user := range users {
  583. var found bool
  584. for _, auser := range associatedUsernames {
  585. if user.Username == auser {
  586. found = true
  587. break
  588. }
  589. }
  590. userIP, _, err := net.ParseCIDR(user.GetIPNet())
  591. if err != nil {
  592. return err
  593. }
  594. _, networkIPNet, err := net.ParseCIDR(network.CIDR)
  595. if err != nil {
  596. return err
  597. }
  598. // get destination network's iface
  599. iface := interfaceOfIP(networkIPNet)
  600. if iface == nil {
  601. logrus.Warnf("network doesn't exist on server %s[SERVERNET]: cant find interface for %s", network.Name, networkIPNet.String())
  602. return nil
  603. }
  604. // enable nat for the user to the destination network n
  605. if found {
  606. err = ipt.AppendUnique("nat", "POSTROUTING", "-s", userIP.String(), "-o", iface.Name, "-j", "MASQUERADE")
  607. if err != nil {
  608. logrus.Error(err)
  609. return err
  610. }
  611. } else {
  612. err = ipt.Delete("nat", "POSTROUTING", "-s", userIP.String(), "-o", iface.Name, "-j", "MASQUERADE")
  613. if err != nil {
  614. logrus.Debug(err)
  615. }
  616. }
  617. }
  618. }
  619. }
  620. return nil
  621. }
  622. func checkOpenVPNExecutable() bool {
  623. executable := getOpenVPNExecutable()
  624. if executable == "" {
  625. logrus.Error("openvpn is not installed ✘")
  626. return false
  627. }
  628. logrus.Debugf("openvpn executable detected: %s ✔", executable)
  629. return true
  630. }
  631. func getOpenVPNExecutable() string {
  632. cmd := exec.Command("which", "openvpn")
  633. output, err := cmd.Output()
  634. if err != nil {
  635. logrus.Errorf("openvpn is not installed: %s ✘", err)
  636. return ""
  637. }
  638. logrus.Debugf("openvpn executable detected: %s ✔", strings.TrimSpace(string(output[:])))
  639. return strings.TrimSpace(string(output[:]))
  640. }
  641. func checkOpenSSLExecutable() bool {
  642. cmd := exec.Command("which", "openssl")
  643. output, err := cmd.Output()
  644. if err != nil {
  645. logrus.Errorf("openssl is not installed: %s ✘", err)
  646. return false
  647. }
  648. logrus.Debugf("openssl executable detected: %s ✔", strings.TrimSpace(string(output[:])))
  649. return true
  650. }
  651. func checkIptablesExecutable() bool {
  652. cmd := exec.Command("which", "iptables")
  653. output, err := cmd.Output()
  654. if err != nil {
  655. logrus.Errorf("iptables is not installed: %s ✘", err)
  656. return false
  657. }
  658. logrus.Debugf("iptables executable detected: %s ✔", strings.TrimSpace(string(output[:])))
  659. return true
  660. }
  661. func ensureBaseDir() {
  662. if Testing {
  663. return
  664. }
  665. os.Mkdir(varBasePath, 0755)
  666. }
  667. func init() {
  668. ensureBaseDir()
  669. var err error
  670. vpnProc, err = supervisor.NewProcess(getOpenVPNExecutable(), varBasePath, []string{"--config", _DefaultVPNConfPath})
  671. if err != nil {
  672. logrus.Errorf("can not create process: %v", err)
  673. }
  674. }