main.go 6.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. // Copyright © 2021 Ettore Di Giacinto <[email protected]>
  2. //
  3. // This program is free software; you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation; either version 2 of the License, or
  6. // (at your option) any later version.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License along
  14. // with this program; if not, see <http://www.gnu.org/licenses/>.
  15. package cmd
  16. import (
  17. "context"
  18. "fmt"
  19. "net"
  20. "os"
  21. "path/filepath"
  22. "time"
  23. "github.com/libp2p/go-libp2p-core/network"
  24. "github.com/mudler/edgevpn/api"
  25. edgevpn "github.com/mudler/edgevpn/pkg/node"
  26. "github.com/mudler/edgevpn/pkg/services"
  27. "github.com/mudler/edgevpn/pkg/vpn"
  28. "github.com/urfave/cli"
  29. )
  30. const Copyright string = ` edgevpn Copyright (C) 2021-2022 Ettore Di Giacinto
  31. This program comes with ABSOLUTELY NO WARRANTY.
  32. This is free software, and you are welcome to redistribute it
  33. under certain conditions.`
  34. func MainFlags() []cli.Flag {
  35. basedir, _ := os.UserHomeDir()
  36. if basedir == "" {
  37. basedir = os.TempDir()
  38. }
  39. return append([]cli.Flag{
  40. &cli.IntFlag{
  41. Name: "key-otp-interval",
  42. Usage: "Tweaks default otp interval (in seconds) when generating new tokens",
  43. Value: 9000,
  44. },
  45. &cli.BoolFlag{
  46. Name: "g",
  47. Usage: "Generates a new configuration and prints it on screen",
  48. },
  49. &cli.BoolFlag{
  50. Name: "b",
  51. Usage: "Encodes the new config in base64, so it can be used as a token",
  52. },
  53. &cli.BoolFlag{
  54. Name: "debug",
  55. Usage: "Starts API with pprof attached",
  56. },
  57. &cli.BoolFlag{
  58. Name: "api",
  59. Usage: "Starts also the API daemon locally for inspecting the network status",
  60. EnvVar: "API",
  61. },
  62. &cli.StringFlag{
  63. Name: "api-listen",
  64. Value: ":8080",
  65. Usage: "API listening port",
  66. EnvVar: "APILISTEN",
  67. },
  68. &cli.BoolFlag{
  69. Name: "dhcp",
  70. Usage: "Enables p2p ip negotiation (experimental)",
  71. EnvVar: "DHCP",
  72. },
  73. &cli.BoolFlag{
  74. Name: "transient-conn",
  75. Usage: "Allow transient connections",
  76. EnvVar: "TRANSIENTCONN",
  77. },
  78. &cli.StringFlag{
  79. Name: "lease-dir",
  80. Value: filepath.Join(basedir, ".edgevpn", "leases"),
  81. Usage: "DHCP leases directory",
  82. EnvVar: "DHCPLEASEDIR",
  83. },
  84. &cli.StringFlag{
  85. Name: "address",
  86. Usage: "VPN virtual address",
  87. EnvVar: "ADDRESS",
  88. Value: "10.1.0.1/24",
  89. },
  90. &cli.StringFlag{
  91. Name: "dns",
  92. Usage: "DNS listening address. Empty to disable dns server",
  93. EnvVar: "DNSADDRESS",
  94. Value: "",
  95. },
  96. &cli.BoolTFlag{
  97. Name: "dns-forwarder",
  98. Usage: "Enables dns forwarding",
  99. EnvVar: "DNSFORWARD",
  100. },
  101. &cli.BoolFlag{
  102. Name: "egress",
  103. Usage: "Enables nodes for egress",
  104. EnvVar: "EGRESS",
  105. },
  106. &cli.IntFlag{
  107. Name: "egress-announce-time",
  108. Usage: "Egress announce time (s)",
  109. EnvVar: "EGRESSANNOUNCE",
  110. Value: 200,
  111. },
  112. &cli.IntFlag{
  113. Name: "dns-cache-size",
  114. Usage: "DNS LRU cache size",
  115. EnvVar: "DNSCACHESIZE",
  116. Value: 200,
  117. },
  118. &cli.IntFlag{
  119. Name: "aliveness-healthcheck-interval",
  120. Usage: "Healthcheck interval",
  121. EnvVar: "HEALTHCHECKINTERVAL",
  122. Value: 120,
  123. },
  124. &cli.IntFlag{
  125. Name: "aliveness-healthcheck-scrub-interval",
  126. Usage: "Healthcheck scrub interval",
  127. EnvVar: "HEALTHCHECKSCRUBINTERVAL",
  128. Value: 600,
  129. },
  130. &cli.IntFlag{
  131. Name: "aliveness-healthcheck-max-interval",
  132. Usage: "Healthcheck max interval. Threshold after a node is determined offline",
  133. EnvVar: "HEALTHCHECKMAXINTERVAL",
  134. Value: 900,
  135. },
  136. &cli.StringSliceFlag{
  137. Name: "dns-forward-server",
  138. Usage: "List of DNS forward server, e.g. 8.8.8.8:53, 192.168.1.1:53 ...",
  139. EnvVar: "DNSFORWARDSERVER",
  140. Value: &cli.StringSlice{"8.8.8.8:53", "1.1.1.1:53"},
  141. },
  142. &cli.StringFlag{
  143. Name: "router",
  144. Usage: "Sends all packets to this node",
  145. EnvVar: "ROUTER",
  146. },
  147. &cli.StringFlag{
  148. Name: "interface",
  149. Usage: "Interface name",
  150. Value: "edgevpn0",
  151. EnvVar: "IFACE",
  152. }}, CommonFlags...)
  153. }
  154. func Main() func(c *cli.Context) error {
  155. return func(c *cli.Context) error {
  156. if c.Bool("g") {
  157. // Generates a new config and exit
  158. newData := edgevpn.GenerateNewConnectionData(c.Int("key-otp-interval"))
  159. if c.Bool("b") {
  160. fmt.Print(newData.Base64())
  161. } else {
  162. fmt.Println(newData.YAML())
  163. }
  164. os.Exit(0)
  165. }
  166. o, vpnOpts, ll := cliToOpts(c)
  167. // Egress and DHCP needs the Alive service
  168. // DHCP needs alive services enabled to all nodes, also those with a static IP.
  169. o = append(o,
  170. services.Alive(
  171. time.Duration(c.Int("aliveness-healthcheck-interval"))*time.Second,
  172. time.Duration(c.Int("aliveness-healthcheck-scrub-interval"))*time.Second,
  173. time.Duration(c.Int("aliveness-healthcheck-max-interval"))*time.Second)...)
  174. if c.Bool("dhcp") {
  175. // Adds DHCP server
  176. address, _, err := net.ParseCIDR(c.String("address"))
  177. if err != nil {
  178. return err
  179. }
  180. nodeOpts, vO := vpn.DHCP(ll, 15*time.Minute, c.String("lease-dir"), address.String())
  181. o = append(o, nodeOpts...)
  182. vpnOpts = append(vpnOpts, vO...)
  183. }
  184. if c.Bool("egress") {
  185. o = append(o, services.Egress(time.Duration(c.Int("egress-announce-time"))*time.Second)...)
  186. }
  187. dns := c.String("dns")
  188. if dns != "" {
  189. // Adds DNS Server
  190. o = append(o,
  191. services.DNS(ll, dns,
  192. c.Bool("dns-forwarder"),
  193. c.StringSlice("dns-forward-server"),
  194. c.Int("dns-cache-size"),
  195. )...)
  196. }
  197. opts, err := vpn.Register(vpnOpts...)
  198. if err != nil {
  199. return err
  200. }
  201. e, err := edgevpn.New(append(o, opts...)...)
  202. if err != nil {
  203. return err
  204. }
  205. displayStart(ll)
  206. ctx := context.Background()
  207. if c.Bool("transient-conn") {
  208. ctx = network.WithUseTransient(ctx, "accept")
  209. }
  210. if c.Bool("api") {
  211. go api.API(ctx, c.String("api-listen"), 5*time.Second, 20*time.Second, e, c.Bool("debug"))
  212. }
  213. return e.Start(ctx)
  214. }
  215. }