main.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  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.StringSliceFlag{
  122. Name: "dns-forward-server",
  123. Usage: "List of DNS forward server, e.g. 8.8.8.8:53, 192.168.1.1:53 ...",
  124. EnvVar: "DNSFORWARDSERVER",
  125. Value: &cli.StringSlice{"8.8.8.8:53", "1.1.1.1:53"},
  126. },
  127. &cli.StringFlag{
  128. Name: "router",
  129. Usage: "Sends all packets to this node",
  130. EnvVar: "ROUTER",
  131. },
  132. &cli.StringFlag{
  133. Name: "interface",
  134. Usage: "Interface name",
  135. Value: "edgevpn0",
  136. EnvVar: "IFACE",
  137. }}, CommonFlags...)
  138. }
  139. func Main() func(c *cli.Context) error {
  140. return func(c *cli.Context) error {
  141. if c.Bool("g") {
  142. // Generates a new config and exit
  143. newData := edgevpn.GenerateNewConnectionData(c.Int("key-otp-interval"))
  144. if c.Bool("b") {
  145. fmt.Print(newData.Base64())
  146. } else {
  147. fmt.Println(newData.YAML())
  148. }
  149. os.Exit(0)
  150. }
  151. o, vpnOpts, ll := cliToOpts(c)
  152. // Egress and DHCP needs the Alive service
  153. // DHCP needs alive services enabled to all nodes, also those with a static IP.
  154. o = append(o,
  155. services.Alive(
  156. time.Duration(c.Int("aliveness-healthcheck-interval"))*time.Second,
  157. time.Duration(c.Int("aliveness-healthcheck-scrub-interval"))*time.Second,
  158. time.Duration(c.Int("aliveness-healthcheck-max-interval"))*time.Second)...)
  159. if c.Bool("dhcp") {
  160. // Adds DHCP server
  161. address, _, err := net.ParseCIDR(c.String("address"))
  162. if err != nil {
  163. return err
  164. }
  165. nodeOpts, vO := vpn.DHCP(ll, 15*time.Minute, c.String("lease-dir"), address.String())
  166. o = append(o, nodeOpts...)
  167. vpnOpts = append(vpnOpts, vO...)
  168. }
  169. if c.Bool("egress") {
  170. o = append(o, services.Egress(time.Duration(c.Int("egress-announce-time"))*time.Second)...)
  171. }
  172. dns := c.String("dns")
  173. if dns != "" {
  174. // Adds DNS Server
  175. o = append(o,
  176. services.DNS(ll, dns,
  177. c.Bool("dns-forwarder"),
  178. c.StringSlice("dns-forward-server"),
  179. c.Int("dns-cache-size"),
  180. )...)
  181. }
  182. bwc := metrics.NewBandwidthCounter()
  183. if c.Bool("api") {
  184. o = append(o, node.WithLibp2pAdditionalOptions(libp2p.BandwidthReporter(bwc)))
  185. }
  186. opts, err := vpn.Register(vpnOpts...)
  187. if err != nil {
  188. return err
  189. }
  190. e, err := edgevpn.New(append(o, opts...)...)
  191. if err != nil {
  192. return err
  193. }
  194. displayStart(ll)
  195. ctx := context.Background()
  196. if c.Bool("transient-conn") {
  197. ctx = network.WithUseTransient(ctx, "accept")
  198. }
  199. if c.Bool("api") {
  200. go api.API(ctx, c.String("api-listen"), 5*time.Second, 20*time.Second, e, bwc, c.Bool("debug"))
  201. }
  202. go handleStopSignals()
  203. return e.Start(ctx)
  204. }
  205. }