gdlemonitor

command module
v0.0.0-...-91ea87c Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 16, 2023 License: BSD-2-Clause Imports: 15 Imported by: 0

README

Huh?

GDLEMonitor is a Windows Service-based server monitor for GDLE. It provides a few basic services, to facilitate running a server.

It is currently under development, in the Proof of Concept phase abandoned.

Default Config

Default config is now handled via an embedded file; and should be sufficient to get self signed tls certs, and console login working; to access the gui settings page.

API-TLS

Serves a rather generic minstyle.io website, under www. Provides account registration facilities. Pages are stored in a pre-compiled, compressed, memory archive. The archive is re-built any time a file in the www subdirectory changes. Do not store large files here. it will end badly. This is not intended to host static content. Files is this folder are heavily mutated before being served.

  • all files in the www folder are embedded into the compiled executable. Most files can be hot-reloaded by simply placing the files alongside the executable, for rapid development

  • .html files: template feeders; First line in the file is the Title, remainder is Content. templated against conf struct, so any conf variable is available, IE {{.DomainName}}, {{.API.Origin}}

  • base.html: base html template. must contain entries for {{.Title}}, {{.Content}} also templated against conf struct, so any conf variable is available, IE {{.DomainName}}, {{.API.Origin}}

  • schema/gdlemonitor.json - JSON Schema for the GDLEMonitor.json config file

  • schema/server.json - JSON Schema for a mock gdlenhanced config

  • ac.svg - Drawn by Maethor on Discord

  • server.html - GDLE server.cfg editor

  • user_management.html - administrative user management page, for setting passwords, adjusting bans, adjusting permissions; and viewing security questions/creation info/etc

  • favicon.ico - render of gdlemonitor.svg, for favicon

  • gdlemonitor.png - render of gdlemonitor.svg for og tags

  • gdlemonitor.svg - gdlemonitor logo

  • index.html - default page

  • local.css - just a little bit of layout fun

  • local.js - most of the universal jwt/pagination type stuff

  • minstyle.io.css - moderately modified from dist

  • privacy.html - semi-generic privacy page

  • register.html - mostly working account creation page- captcha is haunted.

  • account.html - user change password/email/security questions page

  • gdlemonitor.html - Editor for GDLEMonitor config .json

  • server.html - Editor for GDLE server.cfg file

  • on init, gdlemonitor iterates the www subfolder, and on each file:

    • minimizes if extension is html, js, css, json
    • gzip
    • if compression ratio is lower than 50%, discard gzip, and use raw file (fixes pointlessly gziping images/icons)
    • stores the resulting "string" in memory, for service.
  • adds a filesystem watcher on the www subfolder, and reloads/discards files as needed. (hot reload, for development)

    • TODO: changes to API config do not update the static cache; or the api_conf header; yet.

minstyle.io

The embedded site uses minstyle.io.

icon

Below are the files, and the command, to embed the exe icon.

  • main.rc
  • main.manifest
  • main-res.syso
windres -o main-res.syso main.rc

API Global Rate Limit

  • initialized in persistance.go, ratelimit.NewBucketWithQuantum(20*time.Millisecond, 15, 1)
  • implemented in api.go, aids.P.GlobalLimiter.WaitMaxDuration(1, 5*time.Second)
  • Simple quantum bucket, with 15 tickets; 20ms refill time.
  • handles the first 15 requests concurrently
  • handles the 16th request after 20ms
  • handles the 17th request after 40ms
  • ...
  • if the client waits 5000ms, serves 429 error, and drops request.
  • outside of DDoS, should not ever trip.
  • forces server to Sleep during DDoS, instead of pegging cpu/io
  • makes server easily DDoSable; but DDoS results only in inavailability of website.

API User Rate Limit (based on ipv4 address)

  • initialized in aids/userRateLimiter.go, Userlimiter{RateLimiter: ratelimit.NewBucketWithQuantum(275*time.Millisecond, 5, 1), LastSeen: time.Now().UTC().}
  • implemented in api.go, userLimiter.RateLimiter.WaitMaxDuration(1, 10*time.Second)
  • TODO change hash key to longip. currently using a hashed string of the ip.... messy.
  • Simple quantum bucket, with 5 tickets; 275ms refill time.
  • handles the first 5 requests concurrently
  • handles the 6th request after 275ms
  • handles the 7th request after 550ms
  • ...
  • if the client waits 10000ms, serves 429 error, and drops request.
  • normal page loads do hit this limiter, by design.
  • intended to make DDoS from a single IP completely ineffective.
  • TODO: make this true. need to count connections, and drop them, instead of ending up with 50000 Sleeping goroutines.
  • pushes DDoS requirement to trip global limiter, to roughly 60 unique ip addresses. Not hard, but makes it more irritating to accomplish.

STS

  • Locks down the TLS domain pretty tightly... Make sure your brown pants are on before enabling this.
  • STS "poisens" browsers, forcing them to only talk to your domain, over validated TLS certificates. It is VERY annoying to remove this, without changing domain.
  • Recommended to only enable this on free domains that can be easily replaced (https://www.freenom.com/en/index.html?lang=en)
		if useSimpleCert && strings.ToLower(r.Host) == authHost {
			w.Header().Add("Strict-Transport-Security", "max-age=63072000; includeSubDomains")
		}

Console Password

  • Generated in api.go, console_password = aids.RandString(64, aids.SQLpasswordBytes)
  • router.HandleFunc("/console", handle_console).Methods("GET")
  • if r.URL.RawQuery == console_password Issues a signed, validated JWT; Authenticating the client that loaded the page with aids.IssueJWT(&aids.Gdle_account{Username: "Server Owner", Access: 6}, w)
  • Generated password has 64^62 (64 of a set of 62) possible combinations (or thereabouts, I'm not a math-ologist); based on a PRNG seeded with start time. Can be brute forced (see user rate limiter :cough:), but results in less than a 1% chance of success before the heat-death of the universe. Deemed "safe enough"™ - Yonneh
  • on startup, and re-generation, password is linked in EventLog and Discord.
  • Password is one time use. it re-generates once used.
  • Provides a method to login when SQL is unavailable, like initial setup

Authentication

  • all auth endpoints are defined in api_auth.go

    • router.HandleFunc("/login", handle_login).Methods("POST")

    • router.HandleFunc("/logout", handle_logout).Methods("GET")

    • router.HandleFunc("/keepalive", handle_keepalive).Methods("GET")

    • router.HandleFunc("/console", handle_console).Methods("GET")

    • gdle.go, func verifyGDLEAccount(username string, password string) (*aids.Gdle_account, int) *moved to gdle/db.go

      • validates against GDLE DB
      • returns http.StatusInternalServerError on database error
      • returns http.StatusOK on success
      • returns http.StatusUnauthorized on password failure
      • returns http.StatusNotFound on no account
      • returns http.StatusForbidden on banned
    • if 200, issue signed JWT: aids.IssueJWT(gdle_acct, w)

    • aids/jwt.go, func IssueJWT(acct *Gdle_account, w http.ResponseWriter)

      • Lots of little details here.. but issues a bearer token, inside of a signed JWT; signed with a randomly generated key, rotated in the Persistance Database. 100000x more complex than it needs to be
  • Authentication is handled via a Bearer token, wrapped inside of a JWT, signed with cyclicly generated key.

  • gdle_account is also exposed inside of the JWT, giving convenient access to username/etc in javascript. This information is never read back, by the server. only the Id (aka jti- used as a bearer token), RandString(32, SQLpasswordBytes), is ever read back from the client.

  • Bearer tokens (and their containing JWT) expire after 30 minutes.

  • They can be infinitely renewed, any time GetJWTClaims() is called, and the token is over 120 seconds old.

  • TODO: add background javascript setTimeout/clearTimeout logic to poll /keepalive

  • Auth is only validated when needed. Mostly only in "write" endpoints, and sensitive "get" endpoints.

    • aids/jwt.go func VerifyAccess(reqLevel int, w http.ResponseWriter, r *http.Request) *Claims
  • Both the JWT Keys and Bearer tokens are backed up, and read from gdlemonitor-persistance.json, to support logins persisting between runs, for development. This should probably be simplified for production.

Permissions

Permissions are arranged in a simple tier. Each level can also access the permissions of any level under it. Most permissions are validated with greater than operators. While technically not valid; access levels 0, 2, 5, and 6+ should still be handled appropriately; but may lead to some display issues (un named access level, etc)

  • None (0)
    • Currently technically unused- new users are created at 1.
    • Can update email address/password/security questions on /account
  • User (1)
  • Advocate (3)
    • Can VIEW user account details, minus password, on /user_management, of ANY user
    • Can access /ip/:{ip} (GET) - ip-api relay (displays geolocation/proxy info on /user_management)
  • Sentinel (4)
    • Can VIEW user account details, on /user_management, of ANY user
    • Can WRITE user Password/Banned/Access level (up to Advocate), on /user_management, of Advocates/Users/Nones
  • Admin (6)
    • Can WRITE user Password/Banned/Access level, on /user_management, of ANY user
    • Can read/write GDLEMonitor Config, at /gdlemonitor
    • Can read/write GDLE server.cfg at /server.cfg

SQL

Below are the current required modifications from the GDLE 1.38 release database format. It is planned to have these automatically added in the future.

ALTER TABLE accounts
    ADD `last_update` timestamp NOT NULL DEFAULT current_timestamp() ON UPDATE current_timestamp(),
    ADD `security` longtext CHARACTER SET utf8mb4 COLLATE utf8mb4_bin DEFAULT '{}' CHECK (json_valid(`security`)),
    ADD KEY `email` (`email`) USING BTREE,
    ADD KEY `created_ip_address` (`created_ip_address`) USING BTREE,
    ADD KEY `last_update` (`last_update`) USING BTREE;

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL