A More Secure Internet Connection for Your Home https://fen.gg
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

177 lines
6.7 KiB

  1. package main
  2. //
  3. // Fengg Security Gateway Server Application
  4. // Copyright (C) 2020 Lukas Matt <support@fen.gg>
  5. //
  6. // This program is free software: you can redistribute it and/or modify
  7. // it under the terms of the GNU General Public License as published by
  8. // the Free Software Foundation, either version 3 of the License.
  9. //
  10. // This program is distributed in the hope that it will be useful,
  11. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. // GNU General Public License for more details.
  14. //
  15. // You should have received a copy of the GNU General Public License
  16. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. //
  18. import (
  19. "time"
  20. "io/ioutil"
  21. "runtime"
  22. "tea.fen.gg/fengg/server/config"
  23. "tea.fen.gg/fengg/server/handler"
  24. "tea.fen.gg/fengg/server/types"
  25. "tea.fen.gg/fengg/server/helper"
  26. "github.com/rs/zerolog"
  27. "github.com/gin-contrib/pprof"
  28. "github.com/gin-gonic/contrib/static"
  29. "github.com/gin-gonic/gin"
  30. "github.com/gin-gonic/gin/binding"
  31. "gopkg.in/go-playground/validator.v9"
  32. "github.com/gin-contrib/sessions"
  33. "github.com/gin-contrib/sessions/cookie"
  34. customLog "github.com/gin-contrib/logger"
  35. sentry "github.com/getsentry/sentry-go"
  36. )
  37. func main() {
  38. runtime.GOMAXPROCS(runtime.NumCPU())
  39. // initialize sentry if DSN is configured
  40. if config.App.Sentry.DSN != "" {
  41. err := sentry.Init(sentry.ClientOptions{Dsn: config.App.Sentry.DSN})
  42. if err != nil {
  43. logger.Fatal().Err(err).Msg("cannot initialize sentry app")
  44. }
  45. defer sentry.Flush(2 * time.Second)
  46. }
  47. // downgrade zerolog level if gin is in release mode
  48. if gin.Mode() == "release" {
  49. zerolog.SetGlobalLevel(zerolog.InfoLevel)
  50. }
  51. router := gin.New()
  52. if validatorV9, ok := binding.Validator.Engine().(*validator.Validate); ok {
  53. validatorV9.RegisterValidation("iporcidr", helper.IporcidrValidator)
  54. validatorV9.RegisterValidation("privatekey", helper.PrivateKeyValidator)
  55. validatorV9.RegisterValidation("publickey", helper.PublicKeyValidator)
  56. validatorV9.RegisterValidation("fingerprint", helper.FingerprintValidator)
  57. validatorV9.RegisterValidation("ip", helper.IpValidator)
  58. validatorV9.RegisterValidation("ipnet", helper.IpnetValidator)
  59. } else {
  60. logger.Fatal().Msg("cannot access gin's binding engine")
  61. }
  62. // only use profiler in development mode
  63. if gin.Mode() != "release" {
  64. pprof.Register(router, "/pprof")
  65. router.Use(customLog.SetLogger(customLog.Config{
  66. Logger: &logger,
  67. }))
  68. }
  69. // use cookie based sessions for e.g. user authentication
  70. store := cookie.NewStore([]byte(config.App.Session.Secret))
  71. router.Use(sessions.Sessions("session", store))
  72. apiGroup := router.Group(config.App.ApiPath)
  73. notifications := apiGroup.Group(
  74. "notifications", handler.AuthenticationHandler(types.Blocking))
  75. {
  76. notifications.GET("/", handler.NotificationHandler)
  77. notifications.POST("/:id/reviewed/:action", handler.NotificationUpdateHandler)
  78. }
  79. system := apiGroup.Group("system")
  80. {
  81. system.GET("/info", handler.SystemInfoHandler)
  82. system.GET("/statistics", handler.AuthenticationHandler(types.Blocking), handler.SystemStatisticsHandler)
  83. settings := system.Group("settings", handler.AuthenticationHandler(types.Blocking))
  84. {
  85. settings.GET("/whitelist", handler.SettingsWLGETHandler)
  86. settings.POST("/whitelist", handler.SettingsWLPOSTHandler)
  87. settings.GET("/portal", handler.SettingsPTLGETHandler)
  88. settings.POST("/portal", handler.SettingsPTLPOSTHandler)
  89. settings.GET("/wifi/station", handler.SettingsWifiSTAGETHandler)
  90. settings.POST("/wifi/station", handler.SettingsWifiSTAPOSTHandler)
  91. settings.GET("/wifi/accesspoint", handler.SettingsWifiAPGETHandler)
  92. settings.POST("/wifi/accesspoint", handler.SettingsWifiAPPOSTHandler)
  93. // bearer authentication
  94. bearer := settings.Group("bearer")
  95. {
  96. bearer.GET("/", handler.BearerGETHandler)
  97. bearer.DELETE("/:id", handler.BearerDELETEHandler)
  98. }
  99. // network configuration objects
  100. settings.GET("/networks", handler.NetworksGETHandler)
  101. settings.POST("/networks", handler.NetworksPOSTHandler)
  102. settings.DELETE("/networks/network/:networkID", handler.NetworksDELETEHandler)
  103. // ethernet interfaces
  104. settings.GET("/interfaces", handler.InterfacesGETHandler)
  105. settings.POST("/interfaces", handler.InterfacesPOSTHandler)
  106. }
  107. wifi := system.Group("wifi", handler.AuthenticationHandler(types.Blocking))
  108. {
  109. wifi.GET("/scan", handler.WifiScanHandler)
  110. }
  111. worker := system.Group("worker", handler.AuthenticationHandler(types.Blocking))
  112. {
  113. worker.GET("/info", handler.WorkerInfoHandler)
  114. }
  115. }
  116. connections := apiGroup.Group("connections", handler.AuthenticationHandler(types.Blocking))
  117. {
  118. connections.GET("/", handler.ConnectionHandler)
  119. }
  120. exceptions := apiGroup.Group("exceptions", handler.AuthenticationHandler(types.Blocking))
  121. {
  122. exceptions.GET("/", handler.ExceptionHandler)
  123. exceptions.GET("/pattern/:patternID", handler.ExceptionPatternHandler)
  124. exceptions.POST("/create/:patternID", handler.ExceptionCreateHandler)
  125. }
  126. profiles := apiGroup.Group("profiles", handler.AuthenticationHandler(types.Blocking))
  127. {
  128. profiles.GET("/", handler.ProfileHandler)
  129. profiles.GET("/r2/", handler.ProfileR2Handler)
  130. profiles.GET("/r2/:id", handler.ProfileR2ByIDHandler)
  131. }
  132. users := apiGroup.Group("users")
  133. {
  134. users.GET("/info", handler.AuthenticationHandler(types.Blocking), handler.UserInfoHandler)
  135. users.POST("/sign_up", handler.UserSignUpHandler)
  136. users.POST("/sign_in", handler.UserSignInHandler)
  137. users.GET("/sign_out", handler.UserSignOutHandler)
  138. users.POST("/reset_password", handler.UserResetPasswordHandler)
  139. }
  140. portal := apiGroup.Group("portal", handler.AuthenticationHandler(types.Blocking))
  141. {
  142. portal.GET("/events", handler.PortalEventHandler)
  143. portal.POST("/push/membership/:fingerprint", handler.PortalPushMembershipHandler)
  144. }
  145. patterns := apiGroup.Group("patterns", handler.AuthenticationHandler(types.Blocking))
  146. {
  147. patterns.GET("/pattern/:id", handler.PatternByIDHandler)
  148. patterns.GET("/categories", handler.PatternCategoryHandler)
  149. patterns.POST("/categories/category/:id", handler.PatternChangeCategoryHandler)
  150. }
  151. staticDir, err := ioutil.TempDir("", "fengg-")
  152. if err != nil {
  153. logger.Fatal().Err(err).Msg("cannot create temporary directory")
  154. }
  155. router.Use(static.Serve("/", static.LocalFile(staticDir, true)))
  156. // register all workers and start executing them
  157. go initWorkers(staticDir)
  158. logger.Info().Msgf("Listening on %s ..", config.App.ListenAddr)
  159. logger.Fatal().Err(router.Run(config.App.ListenAddr)).Msg("cannot bind listening interface")
  160. }