vpn.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615
  1. //go:generate go-bindata -pkg bindata -o bindata/bindata.go template/
  2. //go:generate protoc -I pb/ pb/user.proto pb/vpn.proto pb/network.proto --go_out=plugins=grpc:pb
  3. package ovpm
  4. import (
  5. "bytes"
  6. "fmt"
  7. "math/big"
  8. "os"
  9. "os/exec"
  10. "strings"
  11. "text/template"
  12. "time"
  13. "github.com/Sirupsen/logrus"
  14. "github.com/asaskevich/govalidator"
  15. "github.com/cad/ovpm/bindata"
  16. "github.com/cad/ovpm/pki"
  17. "github.com/cad/ovpm/supervisor"
  18. "github.com/google/uuid"
  19. "github.com/jinzhu/gorm"
  20. )
  21. // DBServer is database model for storing VPN server related stuff.
  22. type DBServer struct {
  23. gorm.Model
  24. Name string `gorm:"unique_index"` // Server name.
  25. SerialNumber string
  26. Hostname string // Server's ip address or FQDN
  27. Port string // Server's listening port
  28. Cert string // Server RSA certificate.
  29. Key string // Server RSA private key.
  30. CACert string // Root CA RSA certificate.
  31. CAKey string // Root CA RSA key.
  32. Net string // VPN network.
  33. Mask string // VPN network mask.
  34. CRL string // Certificate Revocation List
  35. }
  36. // CheckSerial takes a serial number and checks it against the current server's serial number.
  37. func (s *DBServer) CheckSerial(serial string) bool {
  38. return serial == s.SerialNumber
  39. }
  40. type _VPNServerConfig struct {
  41. CertPath string
  42. KeyPath string
  43. CACertPath string
  44. CAKeyPath string
  45. CCDPath string
  46. CRLPath string
  47. DHParamsPath string
  48. Net string
  49. Mask string
  50. Port string
  51. }
  52. // Init regenerates keys and certs for a Root CA, and saves them in the database.
  53. func Init(hostname string, port string) error {
  54. if port == "" {
  55. port = DefaultVPNPort
  56. }
  57. if !govalidator.IsNumeric(port) {
  58. return fmt.Errorf("validation error: port:`%s` should be numeric", port)
  59. }
  60. serverName := "default"
  61. if IsInitialized() {
  62. if err := Deinit(); err != nil {
  63. logrus.Errorf("server can not be deleted: %v", err)
  64. return err
  65. }
  66. }
  67. if !govalidator.IsHost(hostname) {
  68. return fmt.Errorf("validation error: hostname:`%s` should be either an ip address or a FQDN", hostname)
  69. }
  70. ca, err := pki.NewCA()
  71. if err != nil {
  72. return fmt.Errorf("can not create ca creds: %s", err)
  73. }
  74. srv, err := pki.NewServerCertHolder(ca)
  75. if err != nil {
  76. return fmt.Errorf("can not create server cert creds: %s", err)
  77. }
  78. serialNumber := uuid.New().String()
  79. serverInstance := DBServer{
  80. Name: serverName,
  81. SerialNumber: serialNumber,
  82. Hostname: hostname,
  83. Port: port,
  84. Cert: srv.Cert,
  85. Key: srv.Key,
  86. CACert: ca.Cert,
  87. CAKey: ca.Key,
  88. Net: _DefaultServerNetwork,
  89. Mask: _DefaultServerNetMask,
  90. }
  91. db.Create(&serverInstance)
  92. if db.NewRecord(&serverInstance) {
  93. return fmt.Errorf("can not create server instance on database")
  94. }
  95. users, err := GetAllUsers()
  96. if err != nil {
  97. return err
  98. }
  99. // Sign all users in the db with the new server
  100. for _, user := range users {
  101. err := user.Renew()
  102. logrus.Infof("user certificate changed for %s, you should run: $ ovpm user export-config --user %s", user.Username, user.Username)
  103. if err != nil {
  104. logrus.Errorf("can not sign user %s: %v", user.Username, err)
  105. continue
  106. }
  107. }
  108. Emit()
  109. logrus.Infof("server initialized")
  110. return nil
  111. }
  112. // Deinit deletes the server with the given serverName from the database and frees the allocated resources.
  113. func Deinit() error {
  114. if !IsInitialized() {
  115. return fmt.Errorf("server not found")
  116. }
  117. db.Unscoped().Delete(&DBServer{})
  118. db.Unscoped().Delete(&DBRevoked{})
  119. Emit()
  120. return nil
  121. }
  122. // DumpsClientConfig generates .ovpn file for the given vpn user and returns it as a string.
  123. func DumpsClientConfig(username string) (string, error) {
  124. var result bytes.Buffer
  125. user, err := GetUser(username)
  126. if err != nil {
  127. return "", err
  128. }
  129. server, err := GetServerInstance()
  130. if err != nil {
  131. return "", err
  132. }
  133. params := struct {
  134. Hostname string
  135. Port string
  136. CA string
  137. Key string
  138. Cert string
  139. NoGW bool
  140. }{
  141. Hostname: server.Hostname,
  142. Port: server.Port,
  143. CA: server.CACert,
  144. Key: user.Key,
  145. Cert: user.Cert,
  146. NoGW: user.NoGW,
  147. }
  148. data, err := bindata.Asset("template/client.ovpn.tmpl")
  149. if err != nil {
  150. return "", err
  151. }
  152. t, err := template.New("client.ovpn").Parse(string(data))
  153. if err != nil {
  154. return "", fmt.Errorf("can not parse client.ovpn.tmpl template: %s", err)
  155. }
  156. err = t.Execute(&result, params)
  157. if err != nil {
  158. return "", fmt.Errorf("can not render client.ovpn: %s", err)
  159. }
  160. return result.String(), nil
  161. }
  162. // DumpClientConfig generates .ovpn file for the given vpn user and dumps it to outPath.
  163. func DumpClientConfig(username, path string) error {
  164. result, err := DumpsClientConfig(username)
  165. if err != nil {
  166. return err
  167. }
  168. // Wite rendered content into openvpn server conf.
  169. return emitToFile(path, result, 0)
  170. }
  171. // GetSystemCA returns the system CA from the database if available.
  172. func GetSystemCA() (*pki.CA, error) {
  173. server := DBServer{}
  174. db.First(&server)
  175. if db.NewRecord(&server) {
  176. return nil, fmt.Errorf("server record does not exists in db")
  177. }
  178. return &pki.CA{
  179. CertHolder: pki.CertHolder{
  180. Cert: server.CACert,
  181. Key: server.CAKey,
  182. },
  183. }, nil
  184. }
  185. // vpnProc represents the OpenVPN process that is managed by the ovpm supervisor globally OpenVPN.
  186. var vpnProc supervisor.Supervisable
  187. // StartVPNProc starts the OpenVPN process.
  188. func StartVPNProc() {
  189. if !IsInitialized() {
  190. logrus.Error("can not launch OpenVPN because system is not initialized")
  191. return
  192. }
  193. if vpnProc == nil {
  194. panic(fmt.Sprintf("vpnProc is not initialized!"))
  195. }
  196. if vpnProc.Status() == supervisor.RUNNING {
  197. logrus.Error("OpenVPN is already started")
  198. return
  199. }
  200. vpnProc.Start()
  201. ensureNatEnabled()
  202. }
  203. // RestartVPNProc restarts the OpenVPN process.
  204. func RestartVPNProc() {
  205. if !IsInitialized() {
  206. logrus.Error("can not launch OpenVPN because system is not initialized")
  207. return
  208. }
  209. if vpnProc == nil {
  210. panic(fmt.Sprintf("vpnProc is not initialized!"))
  211. }
  212. vpnProc.Restart()
  213. ensureNatEnabled()
  214. }
  215. // StopVPNProc stops the OpenVPN process.
  216. func StopVPNProc() {
  217. if vpnProc == nil {
  218. panic(fmt.Sprintf("vpnProc is not initialized!"))
  219. }
  220. if vpnProc.Status() != supervisor.RUNNING {
  221. logrus.Error("OpenVPN is already not running")
  222. return
  223. }
  224. vpnProc.Stop()
  225. }
  226. // Emit generates all needed files for the OpenVPN server and dumps them to their corresponding paths defined in the config.
  227. func Emit() error {
  228. // Check dependencies
  229. if !checkOpenVPNExecutable() {
  230. return fmt.Errorf("openvpn executable can not be found! you should install OpenVPN on this machine")
  231. }
  232. if !checkOpenSSLExecutable() {
  233. return fmt.Errorf("openssl executable can not be found! you should install openssl on this machine")
  234. }
  235. if !checkIptablesExecutable() {
  236. return fmt.Errorf("iptables executable can not be found")
  237. }
  238. if !IsInitialized() {
  239. return fmt.Errorf("you should create a server first. e.g. $ ovpm vpn create-server")
  240. }
  241. if err := emitServerConf(); err != nil {
  242. return fmt.Errorf("can not emit server conf: %s", err)
  243. }
  244. if err := emitServerCert(); err != nil {
  245. return fmt.Errorf("can not emit server cert: %s", err)
  246. }
  247. if err := emitServerKey(); err != nil {
  248. return fmt.Errorf("can not emit server key: %s", err)
  249. }
  250. if err := emitCACert(); err != nil {
  251. return fmt.Errorf("can not emit ca cert : %s", err)
  252. }
  253. if err := emitCAKey(); err != nil {
  254. return fmt.Errorf("can not emit ca key: %s", err)
  255. }
  256. if err := emitDHParams(); err != nil {
  257. return fmt.Errorf("can not emit dhparams: %s", err)
  258. }
  259. if err := emitCCD(); err != nil {
  260. return fmt.Errorf("can not emit ccd: %s", err)
  261. }
  262. if err := emitIptables(); err != nil {
  263. return fmt.Errorf("can not emit iptables conf: %s", err)
  264. }
  265. if err := emitCRL(); err != nil {
  266. return fmt.Errorf("can not emit crl: %s", err)
  267. }
  268. logrus.Info("configurations emitted to the filesystem")
  269. if IsInitialized() {
  270. for {
  271. if vpnProc.Status() == supervisor.RUNNING || vpnProc.Status() == supervisor.STOPPED {
  272. logrus.Info("OpenVPN process is restarting")
  273. RestartVPNProc()
  274. break
  275. }
  276. time.Sleep(1 * time.Second)
  277. }
  278. }
  279. return nil
  280. }
  281. func emitToFile(path, content string, mode uint) error {
  282. // When testing don't emit files to the filesystem. Just pretend you did.
  283. if Testing {
  284. return nil
  285. }
  286. file, err := os.Create(path)
  287. if err != nil {
  288. return fmt.Errorf("Cannot create file %s: %v", path, err)
  289. }
  290. if mode != 0 {
  291. file.Chmod(os.FileMode(mode))
  292. }
  293. defer file.Close()
  294. fmt.Fprintf(file, content)
  295. return nil
  296. }
  297. func emitServerConf() error {
  298. serverInstance, err := GetServerInstance()
  299. if err != nil {
  300. return fmt.Errorf("can not retrieve server: %v", err)
  301. }
  302. port := DefaultVPNPort
  303. if serverInstance.Port != "" {
  304. port = serverInstance.Port
  305. }
  306. var result bytes.Buffer
  307. server := _VPNServerConfig{
  308. CertPath: _DefaultCertPath,
  309. KeyPath: _DefaultKeyPath,
  310. CACertPath: _DefaultCACertPath,
  311. CAKeyPath: _DefaultCAKeyPath,
  312. CCDPath: _DefaultVPNCCDPath,
  313. CRLPath: _DefaultCRLPath,
  314. DHParamsPath: _DefaultDHParamsPath,
  315. Net: _DefaultServerNetwork,
  316. Mask: _DefaultServerNetMask,
  317. Port: port,
  318. }
  319. data, err := bindata.Asset("template/server.conf.tmpl")
  320. if err != nil {
  321. return err
  322. }
  323. t, err := template.New("server.conf").Parse(string(data))
  324. if err != nil {
  325. return fmt.Errorf("can not parse server.conf.tmpl template: %s", err)
  326. }
  327. err = t.Execute(&result, server)
  328. if err != nil {
  329. return fmt.Errorf("can not render server.conf: %s", err)
  330. }
  331. // Wite rendered content into openvpn server conf.
  332. return emitToFile(_DefaultVPNConfPath, result.String(), 0)
  333. }
  334. // GetServerInstance returns the default server from the database.
  335. func GetServerInstance() (*DBServer, error) {
  336. var server DBServer
  337. db.First(&server)
  338. if db.NewRecord(server) {
  339. return nil, fmt.Errorf("can not retrieve server from db")
  340. }
  341. return &server, nil
  342. }
  343. // IsInitialized checks if there is a default server in the database or not.
  344. func IsInitialized() bool {
  345. var server DBServer
  346. db.First(&server)
  347. if db.NewRecord(server) {
  348. return false
  349. }
  350. return true
  351. }
  352. func emitServerKey() error {
  353. server, err := GetServerInstance()
  354. if err != nil {
  355. return err
  356. }
  357. // Write rendered content into key file.
  358. return emitToFile(_DefaultKeyPath, server.Key, 0600)
  359. }
  360. func emitServerCert() error {
  361. server, err := GetServerInstance()
  362. if err != nil {
  363. return err
  364. }
  365. // Write rendered content into the cert file.
  366. return emitToFile(_DefaultCertPath, server.Cert, 0)
  367. }
  368. func emitCRL() error {
  369. var revokedDBItems []*DBRevoked
  370. db.Find(&revokedDBItems)
  371. var revokedCertSerials []*big.Int
  372. for _, item := range revokedDBItems {
  373. bi := big.NewInt(0)
  374. bi.SetString(item.SerialNumber, 16)
  375. revokedCertSerials = append(revokedCertSerials, bi)
  376. }
  377. systemCA, err := GetSystemCA()
  378. if err != nil {
  379. return fmt.Errorf("can not emit CRL: %v", err)
  380. }
  381. crl, err := pki.NewCRL(systemCA, revokedCertSerials...)
  382. if err != nil {
  383. return fmt.Errorf("can not emit crl: %v", err)
  384. }
  385. return emitToFile(_DefaultCRLPath, crl, 0)
  386. }
  387. func emitCACert() error {
  388. server, err := GetServerInstance()
  389. if err != nil {
  390. return err
  391. }
  392. // Write rendered content into the ca cert file.
  393. return emitToFile(_DefaultCACertPath, server.CACert, 0)
  394. }
  395. func emitCAKey() error {
  396. server, err := GetServerInstance()
  397. if err != nil {
  398. return err
  399. }
  400. // Write rendered content into the ca key file.
  401. return emitToFile(_DefaultCAKeyPath, server.CAKey, 0600)
  402. }
  403. func emitCCD() error {
  404. users, err := GetAllUsers()
  405. if err != nil {
  406. return err
  407. }
  408. if !Testing {
  409. // Clean and then create and write rendered ccd data.
  410. err = os.RemoveAll(_DefaultVPNCCDPath)
  411. if err != nil {
  412. if os.IsNotExist(err) {
  413. } else {
  414. return err
  415. }
  416. }
  417. if _, err := os.Stat(_DefaultVPNCCDPath); err != nil {
  418. }
  419. err = os.Mkdir(_DefaultVPNCCDPath, 0755)
  420. if err != nil {
  421. if !os.IsExist(err) {
  422. return err
  423. }
  424. }
  425. }
  426. for _, user := range users {
  427. var result bytes.Buffer
  428. params := struct {
  429. IP string
  430. NetMask string
  431. }{IP: user.getIP().String(), NetMask: _DefaultServerNetMask}
  432. data, err := bindata.Asset("template/ccd.file.tmpl")
  433. if err != nil {
  434. return err
  435. }
  436. t, err := template.New("ccd.file.tmpl").Parse(string(data))
  437. if err != nil {
  438. return fmt.Errorf("can not parse ccd.file.tmpl template: %s", err)
  439. }
  440. err = t.Execute(&result, params)
  441. if err != nil {
  442. return fmt.Errorf("can not render ccd file %s: %s", user.Username, err)
  443. }
  444. err = emitToFile(_DefaultVPNCCDPath+user.Username, result.String(), 0)
  445. if err != nil {
  446. return err
  447. }
  448. }
  449. return nil
  450. }
  451. func emitDHParams() error {
  452. var result bytes.Buffer
  453. data, err := bindata.Asset("template/dh4096.pem.tmpl")
  454. if err != nil {
  455. return err
  456. }
  457. t, err := template.New("dh4096.pem.tmpl").Parse(string(data))
  458. if err != nil {
  459. return fmt.Errorf("can not parse dh4096.pem template: %s", err)
  460. }
  461. err = t.Execute(&result, nil)
  462. if err != nil {
  463. return fmt.Errorf("can not render dh4096.pem file: %s", err)
  464. }
  465. err = emitToFile(_DefaultDHParamsPath, result.String(), 0)
  466. if err != nil {
  467. return err
  468. }
  469. return nil
  470. }
  471. func emitIptables() error {
  472. return nil
  473. }
  474. func checkOpenVPNExecutable() bool {
  475. executable := getOpenVPNExecutable()
  476. if executable == "" {
  477. logrus.Error("openvpn is not installed ✘")
  478. return false
  479. }
  480. logrus.Debugf("openvpn executable detected: %s ✔", executable)
  481. return true
  482. }
  483. func getOpenVPNExecutable() string {
  484. cmd := exec.Command("which", "openvpn")
  485. output, err := cmd.Output()
  486. if err != nil {
  487. logrus.Errorf("openvpn is not installed: %s ✘", err)
  488. return ""
  489. }
  490. logrus.Debugf("openvpn executable detected: %s ✔", strings.TrimSpace(string(output[:])))
  491. return strings.TrimSpace(string(output[:]))
  492. }
  493. func checkOpenSSLExecutable() bool {
  494. cmd := exec.Command("which", "openssl")
  495. output, err := cmd.Output()
  496. if err != nil {
  497. logrus.Errorf("openssl is not installed: %s ✘", err)
  498. return false
  499. }
  500. logrus.Debugf("openssl executable detected: %s ✔", strings.TrimSpace(string(output[:])))
  501. return true
  502. }
  503. func checkIptablesExecutable() bool {
  504. cmd := exec.Command("which", "iptables")
  505. output, err := cmd.Output()
  506. if err != nil {
  507. logrus.Errorf("iptables is not installed: %s ✘", err)
  508. return false
  509. }
  510. logrus.Debugf("iptables executable detected: %s ✔", strings.TrimSpace(string(output[:])))
  511. return true
  512. }
  513. func ensureBaseDir() {
  514. if Testing {
  515. return
  516. }
  517. os.Mkdir(varBasePath, 0755)
  518. }
  519. func init() {
  520. ensureBaseDir()
  521. var err error
  522. vpnProc, err = supervisor.NewProcess(getOpenVPNExecutable(), varBasePath, []string{"--config", _DefaultVPNConfPath})
  523. if err != nil {
  524. logrus.Errorf("can not create process: %v", err)
  525. }
  526. }