main.go 6.2 KB

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