web.go (34665B)
1 package web 2 3 import ( 4 "context" 5 "dkforest/bindata" 6 "dkforest/pkg/config" 7 "dkforest/pkg/database" 8 "dkforest/pkg/staticbin" 9 tmp "dkforest/pkg/template" 10 "dkforest/pkg/utils" 11 "dkforest/pkg/web/clientFrontends" 12 "dkforest/pkg/web/handlers" 13 v1 "dkforest/pkg/web/handlers/api/v1" 14 "dkforest/pkg/web/middlewares" 15 "fmt" 16 "github.com/labstack/echo" 17 "github.com/nicksnyder/go-i18n/v2/i18n" 18 "github.com/sirupsen/logrus" 19 "github.com/ulule/limiter" 20 "github.com/ulule/limiter/drivers/store/memory" 21 "golang.org/x/text/language" 22 yaml "gopkg.in/yaml.v1" 23 "net" 24 "net/http" 25 "net/http/httputil" 26 "net/url" 27 "os" 28 "os/signal" 29 "regexp" 30 "strconv" 31 "strings" 32 "time" 33 ) 34 35 func getMainServer(db *database.DkfDB, i18nBundle *i18n.Bundle, renderer *tmp.Templates, clientFE clientFrontends.ClientFrontend) echo.HandlerFunc { 36 e := newEcho() 37 38 e.Server.ReadHeaderTimeout = 10 * time.Second 39 e.Server.ReadTimeout = 10 * time.Second 40 e.Server.WriteTimeout = 10 * time.Second 41 42 e.Use(staticbin.Static(bindata.Asset, staticbin.Options{Dir: "/public", SkipLogging: true})) 43 e.Renderer = renderer 44 e.Use(middlewares.SetDatabaseMiddleware(db)) 45 e.Use(middlewares.SetClientFEMiddleware(clientFE)) 46 e.Use(middlewares.FirstUseMiddleware) 47 e.Use(middlewares.DdosMiddleware) 48 e.Use(middlewares.MaintenanceMiddleware) 49 e.Use(middlewares.SecureMiddleware) 50 e.Use(middlewares.SetUserMiddleware) 51 e.Use(middlewares.GzipMiddleware) 52 e.Use(middlewares.CSRFMiddleware()) 53 e.Use(middlewares.I18nMiddleware(i18nBundle, "en")) 54 e.Use(middlewares.BodyLimit) 55 e.Use(middlewares.HellbannedCookieMiddleware) 56 e.Use(middlewares.AprilFoolMiddleware()) 57 e.GET("/", handlers.HomeHandler, middlewares.CircuitRateLimitMiddleware(15*time.Second, 4, true)) 58 e.POST("/", handlers.HomeHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 4, false)) 59 e.GET("/bhcli", handlers.BhcliHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 5, false)) 60 e.GET("/torchess", handlers.TorchessHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 5, false)) 61 e.GET("/captcha-help", handlers.CaptchaHelpHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 5, false)) 62 e.GET("/pow-help", handlers.PowHelpHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 5, false)) 63 e.GET("/werewolf", handlers.WerewolfHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 5, false)) 64 e.GET("/gists/:gistUUID", handlers.GistHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 5, false)) 65 e.POST("/gists/:gistUUID", handlers.GistHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 3, false)) 66 e.GET("/chat/:roomName", handlers.ChatHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 4, false)) 67 e.POST("/chat/:roomName", handlers.ChatHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 2, false)) 68 e.GET("/bhc", handlers.BHCHandler, middlewares.CircuitRateLimitMiddleware(5*time.Second, 4, true)) 69 e.POST("/bhc", handlers.BHCHandler, middlewares.CircuitRateLimitMiddleware(5*time.Second, 4, true)) 70 e.GET("/public/css/:signupToken/signup.css", handlers.SignupCss, middlewares.CircuitRateLimitMiddleware(15*time.Second, 4, false)) 71 e.GET("/public/img/:signupToken/:signal/:data", handlers.SignalCss, middlewares.CircuitRateLimitMiddleware(15*time.Second, 4, false)) 72 noAuthGroup := e.Group("", middlewares.NoAuthMiddleware) 73 noAuthGroup.GET("/login", handlers.LoginHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 4, false)) 74 noAuthGroup.POST("/login", handlers.LoginHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 4, false)) 75 noAuthGroup.GET("/login/:loginToken", handlers.LoginAttackHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 4, false)) 76 noAuthGroup.POST("/login/:loginToken", handlers.LoginAttackHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 2, false)) 77 noAuthGroup.GET("/signup", handlers.SignupHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 5, false)) 78 noAuthGroup.POST("/signup", handlers.SignupHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 4, false)) 79 noAuthGroup.GET("/signup/invitation", handlers.SignupInvitationHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 5, false)) 80 noAuthGroup.GET("/signup/invitation/:invitationToken", handlers.SignupInvitationHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 5, false)) 81 noAuthGroup.POST("/signup/invitation/:invitationToken", handlers.SignupInvitationHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 5, false)) 82 noAuthGroup.GET("/signup/:signupToken", handlers.SignupAttackHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 5, false)) 83 noAuthGroup.POST("/signup/:signupToken", handlers.SignupAttackHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 2, false)) 84 noAuthGroup.GET("/forgot-password", handlers.ForgotPasswordHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 4, false)) 85 noAuthGroup.POST("/forgot-password", handlers.ForgotPasswordHandler, middlewares.CircuitRateLimitMiddleware(1*time.Second, 2, false)) 86 maybeAuthGroup := e.Group("", middlewares.MaybeAuthMiddleware) 87 maybeAuthGroup.GET("/u/:username", handlers.PublicUserProfileHandler, middlewares.GenericRateLimitMiddleware(time.Second, 2)) 88 maybeAuthGroup.GET("/u/:username/pgp", handlers.PublicUserProfilePGPHandler, middlewares.GenericRateLimitMiddleware(time.Second, 2)) 89 maybeAuthGroup.GET("/t/:threadUUID", handlers.ThreadHandler, middlewares.GenericRateLimitMiddleware(time.Second, 2)) 90 authGroup := e.Group("", middlewares.IsAuthMiddleware, middlewares.ForceCaptchaMiddleware) 91 authGroup.GET("/public/css/meta.css", handlers.MetaCss) 92 authGroup.GET("/public/img/signal/:signal/:data", handlers.SignalCss1) 93 authGroup.GET("/captcha-required", handlers.CaptchaRequiredHandler, middlewares.AuthRateLimitMiddleware(time.Second, 1)) 94 authGroup.POST("/captcha-required", handlers.CaptchaRequiredHandler, middlewares.AuthRateLimitMiddleware(time.Second, 1)) 95 authGroup.GET("/odometer", handlers.OdometerHandler, middlewares.AuthRateLimitMiddleware(time.Second, 1)) 96 authGroup.GET("/captcha", handlers.CaptchaHandler, middlewares.AuthRateLimitMiddleware(time.Second, 1)) 97 authGroup.POST("/captcha", handlers.CaptchaHandler, middlewares.AuthRateLimitMiddleware(time.Second, 1)) 98 authGroup.GET("/donate", handlers.DonateHandler) 99 authGroup.GET("/shop", handlers.ShopHandler) 100 authGroup.GET("/poker", handlers.PokerHomeHandler) 101 authGroup.POST("/poker", handlers.PokerHomeHandler, middlewares.AuthRateLimitMiddleware(time.Second, 1)) 102 authGroup.GET("/poker/rake-back", handlers.PokerRakeBackHandler) 103 authGroup.POST("/poker/rake-back", handlers.PokerRakeBackHandler, middlewares.AuthRateLimitMiddleware(time.Second, 1)) 104 authGroup.GET("/poker/:roomID", handlers.PokerTableHandler) 105 authGroup.GET("/poker/:roomID/stream", handlers.PokerStreamHandler) 106 authGroup.GET("/poker/:roomID/logs", handlers.PokerLogsHandler) 107 authGroup.GET("/poker/:roomID/bet", handlers.PokerBetHandler) 108 authGroup.POST("/poker/:roomID/bet", handlers.PokerBetHandler) 109 authGroup.GET("/poker/:roomID/deal", handlers.PokerDealHandler) 110 authGroup.POST("/poker/:roomID/deal", handlers.PokerDealHandler) 111 authGroup.GET("/poker/:roomID/unsit", handlers.PokerUnSitHandler) 112 authGroup.POST("/poker/:roomID/unsit", handlers.PokerUnSitHandler) 113 authGroup.GET("/poker/:roomID/sit/:pos", handlers.PokerSitHandler) 114 authGroup.POST("/poker/:roomID/sit/:pos", handlers.PokerSitHandler) 115 authGroup.GET("/chess", handlers.ChessHandler) 116 authGroup.POST("/chess", handlers.ChessHandler) 117 authGroup.GET("/chess/analyze", handlers.ChessAnalyzeHandler) 118 authGroup.POST("/chess/analyze", handlers.ChessAnalyzeHandler) 119 authGroup.GET("/chess/:key", handlers.ChessGameHandler) 120 authGroup.POST("/chess/:key", handlers.ChessGameHandler) 121 authGroup.GET("/chess/:key/analyze", handlers.ChessGameAnalyzeHandler) 122 authGroup.POST("/chess/:key/analyze", handlers.ChessGameAnalyzeHandler) 123 authGroup.GET("/chess/:key/form", handlers.ChessGameFormHandler) 124 authGroup.POST("/chess/:key/form", handlers.ChessGameFormHandler) 125 authGroup.GET("/chess/:key/stats", handlers.ChessGameStatsHandler) 126 authGroup.POST("/chess/:key/stats", handlers.ChessGameStatsHandler) 127 authGroup.GET("/settings/chat", handlers.SettingsChatHandler) 128 authGroup.POST("/settings/chat", handlers.SettingsChatHandler, middlewares.AuthRateLimitMiddleware(2*time.Second, 1)) 129 authGroup.GET("/settings/chat/pm", handlers.SettingsChatPMHandler) 130 authGroup.POST("/settings/chat/pm", handlers.SettingsChatPMHandler, middlewares.AuthRateLimitMiddleware(2*time.Second, 5)) 131 authGroup.GET("/settings/chat/ignore", handlers.SettingsChatIgnoreHandler) 132 authGroup.POST("/settings/chat/ignore", handlers.SettingsChatIgnoreHandler, middlewares.AuthRateLimitMiddleware(2*time.Second, 5)) 133 authGroup.GET("/settings/chat/snippets", handlers.SettingsChatSnippetsHandler) 134 authGroup.POST("/settings/chat/snippets", handlers.SettingsChatSnippetsHandler, middlewares.AuthRateLimitMiddleware(2*time.Second, 5)) 135 authGroup.GET("/settings/public-notes", handlers.SettingsPublicNotesHandler) 136 authGroup.POST("/settings/public-notes", handlers.SettingsPublicNotesHandler) 137 authGroup.GET("/settings/private-notes", handlers.SettingsPrivateNotesHandler) 138 authGroup.POST("/settings/private-notes", handlers.SettingsPrivateNotesHandler) 139 authGroup.GET("/settings/sessions", handlers.SettingsSessionsHandler) 140 authGroup.POST("/settings/sessions", handlers.SettingsSessionsHandler) 141 authGroup.GET("/settings/api", handlers.SettingsAPIHandler) 142 authGroup.POST("/settings/api", handlers.SettingsAPIHandler) 143 authGroup.GET("/settings/security", handlers.SettingsSecurityHandler) 144 authGroup.GET("/settings/account", handlers.SettingsAccountHandler) 145 authGroup.POST("/settings/account", handlers.SettingsAccountHandler, middlewares.AuthRateLimitMiddleware(2*time.Second, 1)) 146 authGroup.GET("/settings/password", handlers.SettingsPasswordHandler) 147 authGroup.POST("/settings/password", handlers.SettingsPasswordHandler, middlewares.AuthRateLimitMiddleware(2*time.Second, 1)) 148 authGroup.GET("/settings/uploads", handlers.SettingsUploadsHandler) 149 authGroup.POST("/settings/uploads", handlers.SettingsUploadsHandler, middlewares.AuthRateLimitMiddleware(2*time.Second, 5)) 150 authGroup.GET("/settings/inbox", handlers.SettingsInboxHandler) 151 authGroup.POST("/settings/inbox", handlers.SettingsInboxHandler, middlewares.AuthRateLimitMiddleware(2*time.Second, 1)) 152 authGroup.GET("/settings/inbox/sent", handlers.SettingsInboxSentHandler) 153 authGroup.POST("/settings/inbox/sent", handlers.SettingsInboxSentHandler, middlewares.AuthRateLimitMiddleware(2*time.Second, 1)) 154 authGroup.GET("/settings/pgp/add", handlers.AddPGPHandler) 155 authGroup.POST("/settings/pgp/add", handlers.AddPGPHandler) 156 authGroup.GET("/settings/pgp", handlers.SettingsPGPHandler) 157 authGroup.GET("/settings/age", handlers.SettingsAgeHandler) 158 authGroup.GET("/settings/age/add", handlers.AddAgeHandler) 159 authGroup.POST("/settings/age/add", handlers.AddAgeHandler) 160 authGroup.GET("/gpg-two-factor-authentication/toggle", handlers.GpgTwoFactorAuthenticationToggleHandler) 161 authGroup.POST("/gpg-two-factor-authentication/toggle", handlers.GpgTwoFactorAuthenticationToggleHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 4)) 162 authGroup.GET("/two-factor-authentication/verify", handlers.TwoFactorAuthenticationVerifyHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 4)) 163 authGroup.POST("/two-factor-authentication/verify", handlers.TwoFactorAuthenticationVerifyHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 164 authGroup.GET("/two-factor-authentication/disable", handlers.TwoFactorAuthenticationDisableHandler) 165 authGroup.POST("/two-factor-authentication/disable", handlers.TwoFactorAuthenticationDisableHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 166 authGroup.GET("/api/v1/captcha-svc", v1.GetCaptchaHandler) 167 authGroup.POST("/api/v1/chat/:roomName/notifier", v1.RoomNotifierHandler) 168 authGroup.POST("/api/v1/battleship", v1.BattleshipHandler) 169 authGroup.POST("/api/v1/werewolf", v1.WerewolfHandler) 170 authGroup.POST("/api/v1/captcha/solver", v1.CaptchaSolverHandler) 171 authGroup.GET("/api/v1/chat/controls/:roomName/:isStream", v1.ChatControlsHandler) 172 authGroup.POST("/api/v1/chat/controls/:roomName/:isStream", v1.ChatControlsHandler) 173 authGroup.GET("/api/v1/chat/top-bar/:roomName", v1.ChatTopBarHandler) 174 authGroup.POST("/api/v1/chat/top-bar/:roomName", v1.ChatTopBarHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 3)) 175 authGroup.GET("/api/v1/chat/messages/:roomName", v1.ChatMessagesHandler) 176 authGroup.GET("/api/v1/chat/messages/:roomName/refresh", v1.ChatStreamMessagesRefreshHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 4)) 177 authGroup.GET("/api/v1/chat/messages/:roomName/stream", v1.ChatStreamMessagesHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 4)) 178 authGroup.GET("/api/v1/chat/messages/:roomName/stream/menu", v1.ChatStreamMenuHandler) 179 authGroup.POST("/api/v1/notifications/delete/:notificationID", v1.DeleteNotificationHandler) 180 authGroup.POST("/api/v1/session-notifications/delete/:sessionNotificationID", v1.DeleteSessionNotificationHandler) 181 authGroup.POST("/api/v1/inbox/delete/:messageID", v1.ChatInboxDeleteMessageHandler) 182 authGroup.POST("/api/v1/inbox/delete-all", v1.ChatInboxDeleteAllMessageHandler) 183 authGroup.GET("/api/v1/chat/messages/delete/:messageUUID", v1.ChatDeleteMessageHandler) 184 authGroup.POST("/api/v1/chat/messages/delete/:messageUUID", v1.ChatDeleteMessageHandler) 185 authGroup.POST("/api/v1/chat/messages/reactions", v1.ChatMessageReactionHandler) 186 authGroup.POST("/api/v1/rooms/:roomName/subscribe", v1.SubscribeHandler) 187 authGroup.POST("/api/v1/rooms/:roomName/unsubscribe", v1.UnsubscribeHandler) 188 authGroup.POST("/api/v1/threads/:threadUUID/subscribe", v1.ThreadSubscribeHandler) 189 authGroup.POST("/api/v1/threads/:threadUUID/unsubscribe", v1.ThreadUnsubscribeHandler) 190 authGroup.POST("/logout", handlers.LogoutHandler) 191 authGroup.GET("/uploads/:filename", handlers.UploadsDownloadHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 192 authGroup.POST("/uploads/:filename", handlers.UploadsDownloadHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 193 authGroup.GET("/torchess/downloads", handlers.TorchessDownloadsHandler) 194 authGroup.GET("/torchess/downloads/:filename", handlers.TorChessDownloadFileHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2), middlewares.CaptchaMiddleware()) 195 authGroup.POST("/torchess/downloads/:filename", handlers.TorChessDownloadFileHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2), middlewares.CaptchaMiddleware()) 196 authGroup.GET("/bhcli/downloads", handlers.BhcliDownloadsHandler) 197 authGroup.GET("/bhcli/downloads/:filename", handlers.BhcliDownloadFileHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2), middlewares.CaptchaMiddleware()) 198 authGroup.POST("/bhcli/downloads/:filename", handlers.BhcliDownloadFileHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2), middlewares.CaptchaMiddleware()) 199 authGroup.GET("/memes/:slug", handlers.MemeHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 200 authGroup.GET("/news", handlers.NewsHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 201 authGroup.GET("/links", handlers.LinksHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 202 authGroup.GET("/links/download", handlers.LinksDownloadHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 203 authGroup.POST("/links/download", handlers.LinksDownloadHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 204 authGroup.GET("/l/:shorthand", handlers.LinkHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 205 authGroup.GET("/links/claim-instructions", handlers.LinksClaimInstructionsHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 206 authGroup.GET("/links/:linkUUID", handlers.LinkHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 207 authGroup.POST("/links/:linkUUID/restore", handlers.RestoreLinkHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 208 authGroup.GET("/links/:linkUUID/claim", handlers.ClaimLinkHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 209 authGroup.POST("/links/:linkUUID/claim", handlers.ClaimLinkHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 210 authGroup.POST("/links/:linkUUID/claim/download-certificate", handlers.ClaimDownloadCertificateLinkHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 211 authGroup.GET("/links/:linkUUID/claim-certificate", handlers.ClaimCertificateLinkHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 212 authGroup.GET("/links/:linkUUID/edit", handlers.EditLinkHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 213 authGroup.POST("/links/:linkUUID/edit", handlers.EditLinkHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 214 authGroup.GET("/links/:linkUUID/delete", handlers.LinkDeleteHandler) 215 authGroup.POST("/links/:linkUUID/delete", handlers.LinkDeleteHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 216 authGroup.POST("/api/v1/pgp/:linkPgpID/download", handlers.LinkPgpDownloadHandler) 217 authGroup.GET("/links/pgp/:linkPgpID/delete", handlers.LinkPgpDeleteHandler) 218 authGroup.POST("/links/pgp/:linkPgpID/delete", handlers.LinkPgpDeleteHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 219 authGroup.GET("/links/mirrors/:linkMirrorID/delete", handlers.LinkMirrorDeleteHandler) 220 authGroup.POST("/links/mirrors/:linkMirrorID/delete", handlers.LinkMirrorDeleteHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 221 authGroup.GET("/links/upload", handlers.LinksUploadHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 222 authGroup.POST("/links/upload", handlers.LinksUploadHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 223 authGroup.GET("/new-link", handlers.NewLinkHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 224 authGroup.POST("/new-link", handlers.NewLinkHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 225 authGroup.GET("/forum", handlers.ForumHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 226 authGroup.GET("/forum/c/:categorySlug", handlers.ForumCategoryHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 227 authGroup.GET("/forum/search", handlers.ForumSearchHandler, middlewares.AuthRateLimitMiddleware(time.Second, 2)) 228 authGroup.GET("/t/:threadUUID/edit", handlers.ThreadEditHandler) 229 authGroup.POST("/t/:threadUUID/edit", handlers.ThreadEditHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 230 authGroup.GET("/t/:threadUUID/delete", handlers.ThreadDeleteHandler) 231 authGroup.POST("/t/:threadUUID/delete", handlers.ThreadDeleteHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 232 authGroup.GET("/t/:threadUUID/reply", handlers.ThreadReplyHandler) 233 authGroup.POST("/t/:threadUUID/reply", handlers.ThreadReplyHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 234 authGroup.GET("/t/:threadUUID/messages/:messageUUID/raw", handlers.ThreadRawMessageHandler) 235 authGroup.GET("/t/:threadUUID/messages/:messageUUID/edit", handlers.ThreadEditMessageHandler) 236 authGroup.POST("/t/:threadUUID/messages/:messageUUID/edit", handlers.ThreadEditMessageHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 237 authGroup.GET("/t/:threadUUID/messages/:messageUUID/delete", handlers.ThreadDeleteMessageHandler) 238 authGroup.POST("/t/:threadUUID/messages/:messageUUID/delete", handlers.ThreadDeleteMessageHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 239 authGroup.GET("/new-thread", handlers.NewThreadHandler) 240 authGroup.POST("/new-thread", handlers.NewThreadHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 241 authGroup.GET("/red-room", handlers.RedRoomHandler) 242 authGroup.GET("/rooms", handlers.RoomsHandler) 243 authGroup.GET("/chat", handlers.ChatHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 4)) 244 authGroup.POST("/chat", handlers.ChatHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 245 authGroup.GET("/chat/help", handlers.ChatHelpHandler) 246 authGroup.GET("/chat-code/:messageUUID/:idx", handlers.ChatCodeHandler) 247 authGroup.GET("/chat/create-room", handlers.ChatCreateRoomHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 248 authGroup.POST("/chat/create-room", handlers.ChatCreateRoomHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 249 authGroup.GET("/chat/:roomName/stream", handlers.ChatStreamHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 4)) 250 authGroup.GET("/chat/:roomName/archive", handlers.ChatArchiveHandler) 251 authGroup.GET("/chat/:roomName/delete", handlers.ChatDeleteHandler) 252 authGroup.POST("/chat/:roomName/delete", handlers.ChatDeleteHandler) 253 authGroup.GET("/chat/:roomName/settings", handlers.RoomChatSettingsHandler) 254 authGroup.POST("/chat/:roomName/settings", handlers.RoomChatSettingsHandler) 255 authGroup.GET("/external-link/:original", handlers.ExternalLink1Handler) 256 authGroup.GET("/external-link/:service/:original", handlers.ExternalLinkHandler) 257 moderatorGroup := e.Group("", middlewares.IsModeratorMiddleware) 258 moderatorGroup.POST("/api/v1/users/:userID/hellban", v1.UserHellbanHandler) 259 moderatorGroup.POST("/api/v1/users/:userID/unhellban", v1.UserUnHellbanHandler) 260 moderatorGroup.POST("/api/v1/users/:userID/kick", v1.KickHandler) 261 moderatorGroup.POST("/links/reindex", handlers.LinksReindexHandler) 262 moderatorGroup.GET("/forum/reindex", handlers.ForumReindexHandler) 263 moderatorGroup.GET("/settings/website", handlers.SettingsWebsiteHandler) 264 moderatorGroup.POST("/settings/website", handlers.SettingsWebsiteHandler) 265 moderatorGroup.GET("/settings/invitations", handlers.SettingsInvitationsHandler) 266 moderatorGroup.POST("/settings/invitations", handlers.SettingsInvitationsHandler) 267 adminGroup := e.Group("", middlewares.IsAdminMiddleware) 268 adminGroup.GET("/debug/*", echo.WrapHandler(http.DefaultServeMux)) 269 adminGroup.GET("/admin", handlers.AdminHandler) 270 adminGroup.POST("/admin", handlers.AdminHandler) 271 adminGroup.GET("/admin/ignored", handlers.IgnoredHandler) 272 adminGroup.POST("/admin/ignored/delete", handlers.IgnoredDeleteHandler) 273 adminGroup.GET("/admin/sessions", handlers.SessionsHandler) 274 adminGroup.GET("/admin/backup", handlers.BackupHandler) 275 adminGroup.POST("/admin/backup", handlers.BackupHandler) 276 adminGroup.GET("/admin/poker-transactions", handlers.AdminPokerTransactionsHandler) 277 adminGroup.GET("/admin/poker-addresses", handlers.AdminPokerAddressesHandler) 278 adminGroup.GET("/admin/spam-filters", handlers.AdminSpamFiltersHandler) 279 adminGroup.POST("/admin/spam-filters", handlers.AdminSpamFiltersHandler) 280 adminGroup.GET("/admin/ddos", handlers.DdosHandler) 281 adminGroup.POST("/admin/ddos", handlers.DdosHandler) 282 adminGroup.GET("/admin/audits", handlers.AdminAuditsHandler) 283 adminGroup.POST("/admin/users/:userID/delete", handlers.AdminDeleteUserHandler) 284 adminGroup.GET("/admin/users/:userID/security-logs", handlers.AdminUserSecurityLogsHandler) 285 adminGroup.GET("/admin/users/:userID/edit", handlers.AdminEditUserHandler) 286 adminGroup.POST("/admin/users/:userID/edit", handlers.AdminEditUserHandler) 287 adminGroup.GET("/admin/captcha", handlers.AdminCaptchaHandler) 288 adminGroup.GET("/admin/rooms", handlers.AdminRoomsHandler) 289 adminGroup.GET("/admin/rooms/:roomID/edit", handlers.AdminEditRoomHandler) 290 adminGroup.POST("/admin/rooms/:roomID/edit", handlers.AdminEditRoomHandler) 291 adminGroup.POST("/admin/rooms/:roomID/delete", handlers.AdminDeleteRoomHandler) 292 adminGroup.GET("/admin/settings", handlers.AdminSettingsHandler) 293 adminGroup.POST("/admin/settings", handlers.AdminSettingsHandler) 294 adminGroup.GET("/admin/uploads", handlers.AdminUploadsHandler) 295 adminGroup.POST("/admin/uploads", handlers.AdminUploadsHandler) 296 adminGroup.GET("/admin/filedrops", handlers.AdminFiledropsHandler) 297 adminGroup.POST("/admin/filedrops", handlers.AdminFiledropsHandler) 298 adminGroup.GET("/admin/file-drop/:filename", handlers.FiledropDownloadHandler) 299 adminGroup.GET("/admin/downloads", handlers.AdminDownloadsHandler) 300 adminGroup.POST("/admin/downloads/:downloadID/delete", handlers.AdminDeleteDownloadHandler) 301 adminGroup.GET("/admin/gists", handlers.AdminGistsHandler) 302 adminGroup.GET("/admin/gists/new", handlers.AdminNewGistHandler) 303 adminGroup.POST("/admin/gists/new", handlers.AdminNewGistHandler) 304 adminGroup.GET("/admin/gists/:gistUUID/edit", handlers.AdminEditGistHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 305 adminGroup.POST("/admin/gists/:gistUUID/edit", handlers.AdminEditGistHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 306 adminGroup.GET("/admin/stream-users", handlers.StreamUsersHandler) 307 clubGroup := authGroup.Group("", middlewares.ClubMiddleware) 308 clubGroup.GET("/club", handlers.ClubHandler) 309 clubGroup.GET("/club/threads/:threadID", handlers.ClubThreadHandler) 310 clubGroup.GET("/club/threads/:threadID/reply", handlers.ClubThreadReplyHandler) 311 clubGroup.POST("/club/threads/:threadID/reply", handlers.ClubThreadReplyHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 312 clubGroup.GET("/club/threads/:threadID/messages/:messageID/edit", handlers.ClubThreadEditMessageHandler) 313 clubGroup.POST("/club/threads/:threadID/messages/:messageID/edit", handlers.ClubThreadEditMessageHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 314 clubGroup.POST("/api/v1/club/messages/:messageID/delete", v1.ClubDeleteMessageHandler) 315 clubGroup.GET("/club/new-thread", handlers.ClubNewThreadHandler) 316 clubGroup.POST("/club/new-thread", handlers.ClubNewThreadHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2)) 317 clubGroup.GET("/club/members", handlers.ClubMembersHandler) 318 vipGroup := authGroup.Group("", middlewares.VipMiddleware) 319 vipGroup.GET("/vip", handlers.VipHandler) 320 vipGroup.GET("/vip/challenges/stego1", handlers.Stego1ChallengeHandler) 321 vipGroup.POST("/vip/challenges/stego1", handlers.Stego1ChallengeHandler) 322 vipGroup.GET("/vip/challenges/forgot-password-bypass", handlers.ForgotPasswordBypassChallengeHandler) 323 vipGroup.GET("/vip/challenges/byte-road", handlers.ByteRoadChallengeHandler, middlewares.AuthRateLimitMiddleware(1*time.Minute, 500)) 324 vipGroup.POST("/vip/challenges/byte-road", handlers.ByteRoadChallengeHandler, middlewares.AuthRateLimitMiddleware(1*time.Minute, 500)) 325 vipGroup.GET("/vip/challenges/re-1", handlers.VipDownloadsHandler) 326 vipGroup.POST("/vip/challenges/re-1", handlers.VipDownloadsHandler) 327 vipGroup.GET("/vip/challenges/re-1/:filename", handlers.VipDownloadFileHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2), middlewares.CaptchaMiddleware()) 328 vipGroup.POST("/vip/challenges/re-1/:filename", handlers.VipDownloadFileHandler, middlewares.AuthRateLimitMiddleware(1*time.Second, 2), middlewares.CaptchaMiddleware()) 329 vipGroup.GET("/vip/projects", handlers.VipProjectsHandler) 330 vipGroup.GET("/vip/projects/ip-grabber", handlers.VipProjectsIPGrabberHandler) 331 vipGroup.GET("/vip/projects/malware-dropper", handlers.VipProjectsMalwareDropperHandler) 332 vipGroup.GET("/vip/projects/rust-ransomware", handlers.VipProjectsRustRansomwareHandler) 333 334 return func(c echo.Context) error { 335 e.ServeHTTP(c.Response(), c.Request()) 336 return nil 337 } 338 } 339 340 func getBaseServer(db *database.DkfDB, clientFE clientFrontends.ClientFrontend) *echo.Echo { 341 e := newEcho() 342 renderer := tmp.GetRenderer(e) 343 i18nBundle := getI18nBundle() 344 e.Renderer = renderer 345 e.Use(middlewares.SetUselessHeadersMiddleware) 346 e.GET("/file-drop/:uuid", handlers.FileDropHandler, middlewares.SetDatabaseMiddleware(db), middlewares.I18nMiddleware(i18nBundle, "en")) 347 e.POST("/file-drop/:uuid", handlers.FileDropHandler, middlewares.SetDatabaseMiddleware(db), middlewares.I18nMiddleware(i18nBundle, "en")) 348 e.POST("/file-drop/:uuid/dkfupload", handlers.FileDropDkfUploadHandler, middlewares.SetDatabaseMiddleware(db), middlewares.I18nMiddleware(i18nBundle, "en")) 349 e.POST("/api/v1/file-drop/:uuid/dkfdownload", handlers.FileDropDkfDownloadHandler, middlewares.SetDatabaseMiddleware(db), middlewares.I18nMiddleware(i18nBundle, "en"), middlewares.SetUserMiddleware, middlewares.IsAuthMiddleware) 350 e.GET("/downloads/:fileName", handlers.FileDropDownloadHandler, middlewares.SetDatabaseMiddleware(db), middlewares.I18nMiddleware(i18nBundle, "en"), middlewares.SetUserMiddleware) 351 e.POST("/downloads/:fileName", handlers.FileDropDownloadHandler, middlewares.SetDatabaseMiddleware(db), middlewares.I18nMiddleware(i18nBundle, "en"), middlewares.SetUserMiddleware) 352 e.Any("*", getMainServer(db, i18nBundle, renderer, clientFE)) 353 return e 354 } 355 356 func getSubdomainServer(db *database.DkfDB, clientFE clientFrontends.ClientFrontend) *echo.Echo { 357 rp := getReverseProxy(config.GogsURL) 358 be := getBaseServer(db, clientFE) 359 e := newEcho() 360 e.Any("*", func(c echo.Context) error { 361 res := c.Response() 362 req := c.Request() 363 host := req.Host 364 hostParts := strings.SplitN(host, ".", 2) 365 if hostParts[0] == "git" { 366 rp.ServeHTTP(res, req) 367 return nil 368 } 369 be.ServeHTTP(res, req) 370 return nil 371 }) 372 return e 373 } 374 375 func getI2pServer(db *database.DkfDB) *echo.Echo { 376 if config.Development.IsTrue() { 377 return nil 378 } 379 return getSubdomainServer(db, clientFrontends.I2PClientFE) 380 } 381 382 func getTorServer(db *database.DkfDB) *echo.Echo { 383 e := getSubdomainServer(db, clientFrontends.TorClientFE) 384 configTorProdServer(e) 385 return e 386 } 387 388 // Start ... 389 func Start(db *database.DkfDB, host string, port int) { 390 // Server for Tor/dev 391 e1 := getTorServer(db) 392 // Start server for I2P 393 e2 := getI2pServer(db) 394 395 serverError1 := make(chan struct{}) 396 serverError2 := make(chan struct{}) 397 398 utils.SGo(func() { 399 address := host + ":" + strconv.Itoa(port) 400 logrus.Info("start tor server on " + address) 401 if err := e1.Start(address); err != nil { 402 if err != http.ErrServerClosed { 403 logrus.Error(err) 404 } 405 close(serverError1) 406 } 407 }) 408 409 utils.SGo(func() { 410 if e2 != nil { 411 address := host + ":" + strconv.Itoa(port+1) 412 logrus.Info("start i2p server on " + address) 413 if err := e2.Start(address); err != nil { 414 if err != http.ErrServerClosed { 415 logrus.Error(err) 416 } 417 close(serverError2) 418 } 419 } 420 }) 421 422 // Wait for interrupt signal to gracefully shutdown the server with 423 // a timeout of 10 seconds. 424 quit := make(chan os.Signal) 425 signal.Notify(quit, os.Interrupt) 426 select { 427 case <-quit: 428 case <-serverError1: 429 case <-serverError2: 430 } 431 432 logrus.Info("graceful shutdown") 433 ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second) 434 defer cancel() 435 if err := e1.Shutdown(ctx); err != nil { 436 logrus.Errorf("tor graceful shutdown failed: %s", err.Error()) 437 } 438 439 if e2 != nil { 440 ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second) 441 defer cancel() 442 if err := e2.Shutdown(ctx); err != nil { 443 logrus.Errorf("i2p graceful shutdown failed: %s", err.Error()) 444 } 445 } 446 447 logrus.Info("Bye!") 448 } 449 450 func extractGlobalCircuitIdentifier(m string) int64 { 451 // You can compute the global circuit identifier using the following formula given the IPv6 address "fc00:dead:beef:4dad::AABB:CCDD": 452 // global_circuit_id = (0xAA << 24) + (0xBB << 16) + (0xCC << 8) + 0xDD; 453 s1 := strings.Split(m, "::")[1] 454 s2 := strings.Split(s1, ":") 455 aabb := fmt.Sprintf("%04s", s2[0]) 456 ccdd := fmt.Sprintf("%04s", s2[1]) 457 aa, _ := strconv.ParseInt(aabb[0:2], 16, 64) 458 bb, _ := strconv.ParseInt(aabb[2:4], 16, 64) 459 cc, _ := strconv.ParseInt(ccdd[0:2], 16, 64) 460 dd, _ := strconv.ParseInt(ccdd[2:4], 16, 64) 461 globalCircuitID := (aa << 24) + (bb << 16) + (cc << 8) + dd 462 return globalCircuitID 463 } 464 465 func getReverseProxy(u string) *httputil.ReverseProxy { 466 remote, err := url.Parse(u) 467 if err != nil { 468 panic(err) 469 } 470 reverseProxy := httputil.NewSingleHostReverseProxy(remote) 471 reverseProxy.FlushInterval = 1000 * time.Millisecond 472 reverseProxy.ErrorHandler = func(w http.ResponseWriter, req *http.Request, e error) { 473 if e.Error() != "context canceled" { 474 logrus.Error(e.Error()) 475 } 476 w.WriteHeader(http.StatusBadGateway) 477 } 478 return reverseProxy 479 } 480 481 func newEcho() *echo.Echo { 482 e := echo.New() 483 e.HideBanner = true 484 e.HidePort = true 485 e.Debug = true 486 return e 487 } 488 489 func configTorProdServer(e *echo.Echo) { 490 if config.Development.IsTrue() { 491 return 492 } 493 rate := limiter.Rate{Period: 5 * time.Second, Limit: 25} 494 store := memory.NewStore() 495 limiterInstance := limiter.New(store, rate) 496 497 var haproxyRgx = regexp.MustCompile(`PROXY TCP6 (\S+)`) 498 e.Server.ConnState = func(conn net.Conn, state http.ConnState) { 499 if state == http.StateNew { 500 buf := make([]byte, 1024) 501 _, err := conn.Read(buf) 502 if err != nil { 503 return 504 } 505 m := haproxyRgx.FindStringSubmatch(string(buf)) 506 if len(m) == 2 { 507 globalCircuitID := extractGlobalCircuitIdentifier(m[1]) 508 config.ConnMap.Set(conn, globalCircuitID) 509 510 limiterCtx, _ := limiterInstance.Get(context.Background(), utils.FormatInt64(globalCircuitID)) 511 if limiterCtx.Reached { 512 config.ConnMap.CloseCircuit(globalCircuitID) 513 } 514 } 515 } else if state == http.StateClosed { 516 config.ConnMap.Delete(conn) 517 } 518 } 519 e.Server.ConnContext = func(ctx context.Context, c net.Conn) context.Context { 520 return context.WithValue(ctx, "conn", c) 521 } 522 523 // Open a tcp connection to each of tor process & authenticate 524 servers := []string{"127.0.0.1:6668"} 525 conns := make([]net.Conn, 0) 526 for _, server := range servers { 527 conn1, err := net.Dial("tcp", server) 528 if err != nil { 529 logrus.Errorf("failed to connect to tor port %s : %v", server, err) 530 } 531 _, _ = conn1.Write([]byte("AUTHENTICATE \"\"\n")) 532 buf := make([]byte, 1024) 533 n, _ := conn1.Read(buf) 534 fmt.Println("AUTHENTICATE", strings.TrimSpace(string(buf[0:n]))) 535 conns = append(conns, conn1) 536 } 537 // Listen for circuit to close 538 go func() { 539 for circuitID := range config.ConnMap.CircuitIDCh { 540 res := "" 541 for _, conn := range conns { 542 _, _ = fmt.Fprintf(conn, "CLOSECIRCUIT %d\n", circuitID) 543 buf1 := make([]byte, 1024) 544 n1, _ := conn.Read(buf1) 545 res += " : " + strings.TrimSpace(string(buf1[0:n1])) 546 } 547 logrus.Warnf("CLOSECIRCUIT %d -> %s", circuitID, res) 548 } 549 }() 550 } 551 552 func getI18nBundle() *i18n.Bundle { 553 bundle := i18n.NewBundle(language.English) 554 bundle.RegisterUnmarshalFunc("yaml", yaml.Unmarshal) 555 dir, _ := config.LocalsFs.ReadDir(".") 556 fileNames := make([]string, 0) 557 for _, d := range dir { 558 fileNames = append(fileNames, d.Name()) 559 } 560 for _, fileName := range fileNames { 561 if strings.HasSuffix(fileName, ".yaml") && !strings.HasSuffix(fileName, "sample.yaml") { 562 if _, err := bundle.ParseMessageFileBytes(utils.Must(config.LocalsFs.ReadFile(fileName)), fileName); err != nil { 563 logrus.Errorf("failed to parse %s : %s", fileName, err.Error()) 564 } 565 } 566 } 567 568 if err := utils.LoadLocals(bundle); err != nil { 569 logrus.Fatal(err) 570 } 571 return bundle 572 }