diff --git a/README.md b/README.md index 06c30715..74705ed7 100644 --- a/README.md +++ b/README.md @@ -36,12 +36,6 @@ to be compatible. 1. `make` to build and run a test server 2. Navigate to `localhost:8081` (or whatever port is printed in the console) -### HTTPS - -If you build the server in `--release` mode, it will force HTTPS using a self-signed certificate. - -Optionally, specify `--certificate-path` and `--private-key-path` to use a trusted CA certificate (e.g. acquired via [Let's Encrypt](https://letsencrypt.org/)). The server will periodically check for and load renewed certificates. - ## Developing If you follow the *Building* steps, you have a fully functioning game (could be used to host a private server). If your goal @@ -68,7 +62,7 @@ One notable feature of the engine is an (optional) admin interface. To build it: 1. Enter `/engine/js` 2. `make` 3. Deploy the server to host the admin interface -4. Go to `localhost:8080/admin` +4. Go to `localhost:8081/admin/` 5. Paste the contents of `engine/game_server/src/auth.txt`, generated randomly by a build script, into the alert dialog ### Macros @@ -82,3 +76,7 @@ and game engine macros can be found in the `engine/engine_macros` directory. A f ## Contributing See [Contributing](https://github.com/SoftbearStudios/mk48/wiki/Contributing) Wiki page. + +## Trademark + +Mk48.io is a trademark of Softbear, Inc. diff --git a/engine/game_terraform/core.tf b/engine/game_terraform/core.tf deleted file mode 100644 index bb31f2c7..00000000 --- a/engine/game_terraform/core.tf +++ /dev/null @@ -1,11 +0,0 @@ -data "terraform_remote_state" "core" { - backend = "s3" - - config = { - profile = "terraform" - bucket = "softbear-terraform" - key = "core.tfstate" - dynamodb_table = "core_terraform" // For locking. - region = "us-east-1" - } -} \ No newline at end of file diff --git a/engine/game_terraform/dns.tf b/engine/game_terraform/dns.tf deleted file mode 100644 index e9365b43..00000000 --- a/engine/game_terraform/dns.tf +++ /dev/null @@ -1,38 +0,0 @@ -resource "linode_domain" "main" { - type = "master" - domain = var.domain - refresh_sec = 300 - retry_sec = 30 - expire_sec = 604800 - soa_email = "finnbearone@gmail.com" - tags = [var.name] -} - -// This is accomplished at runtime by the servutil watchdog. -/* -resource "linode_domain_record" "home_ipv4" { - count = var.servers - domain_id = linode_domain.main.id - name = "" - record_type = "A" - target = element(linode_instance.servers.*.ip_address, count.index) - ttl_sec = 30 -} -*/ - -resource "linode_domain_record" "servers_ipv4" { - for_each = var.servers - domain_id = linode_domain.main.id - name = each.key - record_type = "A" - target = linode_instance.servers[each.key].ip_address - ttl_sec = 120 -} - -resource "linode_domain_record" "www" { - domain_id = linode_domain.main.id - name = "www" - record_type = "CNAME" - target = var.domain - ttl_sec = 120 -} \ No newline at end of file diff --git a/engine/game_terraform/linode.tf b/engine/game_terraform/linode.tf deleted file mode 100644 index ba52d23b..00000000 --- a/engine/game_terraform/linode.tf +++ /dev/null @@ -1,59 +0,0 @@ -resource "linode_instance" "servers" { - depends_on = [linode_domain.main] - for_each = var.servers - label = "${var.name}_${each.key}" - image = "linode/debian11" - region = each.value - type = "g6-nanode-1" - authorized_keys = [ - "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC+TE0LBTlPK2g4ULX48WfBJZKk/8vs3/faGaEkr+Q8j6ZB3nl0qBVk7NI8ETxbqZ0WRXf21ExZUO6m+ecUB5JmkU19pw9zLwDB+TT8DVsjRDuMEW09afeMGux2eXOV+0w+G1qqqwH2V8zFGpRj91kNwvR2tZ5yc+r1NTC+T3gr5HeGXGb7Q82l7knUErSvCB52T0BR31lXT6FiNSdRt+uYAkAoe3gtdnlvKV3GkiWejgY3L6sXz63llnGDefxhXSATo6yj41UNbAXHxCHPmFNFktpYT+H2OkdRRdSSIcs+1/JtwEm3QKBkDsjKFrBP3ujuvlVOi1sStEesKyNAUOyX finnb@epyc", - chomp(file("../.ssh/id_rsa.pub")) - ] - tags = [var.name] - swap_size = 128 - private_ip = true - backups_enabled = false - - connection { - type = "ssh" - user = "root" - host = self.ip_address - } - - provisioner "file" { - source = "../server/target/release/server" - destination = "/root/server" - } - - provisioner "file" { - source = "../engine/game_terraform/server_init.sh" - destination = "/root/server_init.sh" - } - provisioner "remote-exec" { - inline = [ - "chmod u+x /root/server", - "chmod u+x /root/server_init.sh", - "echo \"SERVER_ID=\\\"${each.key}\\\"\" >> /etc/environment", - "echo \"IP_ADDRESS=\\\"${self.ip_address}\\\"\" >> /etc/environment", - "echo \"DOMAIN=\\\"${var.domain}\\\"\" >> /etc/environment", - "echo \"AWS_ACCESS_KEY_ID=\\\"${data.terraform_remote_state.core.outputs.aws_access_key_id}\\\"\" >> /etc/environment", - "echo \"AWS_SECRET_ACCESS_KEY=\\\"${data.terraform_remote_state.core.outputs.aws_secret_access_key}\\\"\" >> /etc/environment", - "echo \"PRIVATE_S3_BUCKET=\\\"${data.terraform_remote_state.core.outputs.private_s3_bucket}\\\"\" >> /etc/environment", - "echo \"DISCORD_CLIENT_SECRET=\\\"${var.discord_client_secret}\\\"\" >> /etc/environment", - "echo \"DISCORD_BOT_TOKEN=\\\"${var.discord_bot_token}\\\"\" >> /etc/environment", - "echo \"LINODE_TOKEN=\\\"${var.linode_token}\\\"\" >> /etc/environment" - ] - } - - provisioner "remote-exec" { - inline = [ - "/root/server_init.sh" - ] - } -} - -resource "linode_firewall_device" "servers" { - for_each = var.servers - firewall_id = data.terraform_remote_state.core.outputs.game_server_firewall_id - entity_id = linode_instance.servers[each.key].id -} \ No newline at end of file diff --git a/engine/game_terraform/provider.tf b/engine/game_terraform/provider.tf deleted file mode 100644 index 592c2122..00000000 --- a/engine/game_terraform/provider.tf +++ /dev/null @@ -1,8 +0,0 @@ -terraform { - required_providers { - linode = { - source = "linode/linode" - # version = "1.20.2" - } - } -} \ No newline at end of file diff --git a/engine/game_terraform/server_init.sh b/engine/game_terraform/server_init.sh deleted file mode 100644 index 1b289f0a..00000000 --- a/engine/game_terraform/server_init.sh +++ /dev/null @@ -1,207 +0,0 @@ -#!/bin/bash - -echo "Security measures" - -sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config && service ssh restart - -< /etc/sysctl.conf -# Enable Spoof protection (reverse-path filter) -# Turn on Source Address Verification in all interfaces to -# prevent some spoofing attacks -net.ipv4.conf.default.rp_filter=1 -net.ipv4.conf.all.rp_filter=1 - -# Enable TCP/IP SYN cookies -# See http://lwn.net/Articles/277146/ -# Note: This may impact IPv6 TCP sessions too -net.ipv4.tcp_syncookies=1 - -# Do not accept ICMP redirects (prevent MITM attacks) -net.ipv4.conf.all.accept_redirects = 0 -net.ipv6.conf.all.accept_redirects = 0 - -# Do not send ICMP redirects (we are not a router) -net.ipv4.conf.all.send_redirects = 0 - -# Do not accept IP source route packets (we are not a router) -net.ipv4.conf.all.accept_source_route = 0 -net.ipv6.conf.all.accept_source_route = 0 -EOF -comment - -cat < /etc/nftables.conf -#!/usr/sbin/nft -f - -flush ruleset - -table inet filter { - # Garbage collected - set ipv4 { - type ipv4_addr - size 16384 - flags dynamic - } - - # Expiry based - set ipv4_timeout { - type ipv4_addr - size 16384 - flags dynamic, timeout - } - - # Garbage collected - set ipv6 { - type ipv6_addr; - size 16384 - flags dynamic - } - - # Expiry based - set ipv6_timeout { - type ipv6_addr; - size 16384 - flags dynamic, timeout - } - - chain inbound_ipv4 { - # Allow ICMP pings (with a global limit) - icmp type echo-request limit rate 5/second accept - - # Limit connections per source IP - ct state new add @ipv4 { ip saddr ct count over 64 } counter reject - - # Limit connection rate per source IP - # ct state new add @ipv4_timeout { ip saddr timeout 30s limit rate over 12/second burst 128 packets } counter drop - - # Limit packet rate per source IP - # ct state { established, related } add @ipv4_timeout { ip saddr timeout 30s limit rate over 2048/second burst 4096 packets } counter drop - } - - chain inbound_ipv6 { - icmpv6 type { nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert } accept - - # Allow ICMP pings (with a global limit) - icmpv6 type echo-request limit rate 5/second accept - - # Limit connections per source IP - ct state new add @ipv6 { ip6 saddr ct count over 64 } counter reject - - # Limit connection rate per source IP - ct state new add @ipv6_timeout { ip6 saddr timeout 30s limit rate over 12/second burst 128 packets } counter drop - - # Limit packet rate per source IP - ct state { established, related } add @ipv6_timeout { ip6 saddr timeout 30s limit rate over 2048/second burst 4096 packets } counter drop - } - - chain inbound { - # What follows this is a whitelist - type filter hook input priority 0; policy drop; - - # Protocol-specific rules - meta protocol vmap { ip : jump inbound_ipv4, ip6 : jump inbound_ipv6 } - - # Allow existing connections to continue, drop invalid packets - ct state vmap { established : accept, related : accept, invalid : drop } - - # Allow loopback - iifname lo accept - - # Allow SSH (with a global limit) - tcp dport ssh ct count 32 accept - - # Allow HTTP (without a global limit) - tcp dport { http, https } accept - } - - chain forward { - # We are not a router. - type filter hook forward priority 0; policy drop; - } -} -EOF - -nft -f /etc/nftables.conf - -echo "Updating" - -apt update - -echo "Installing snap" - -apt install -y snapd -snap install core; -snap refresh core; - -echo "Installing linode token" - -printf "dns_linode_key = $LINODE_TOKEN\ndns_linode_version = 4\n" > /root/linode.ini -chmod 600 /root/linode.ini - -echo "Installing certbot" - -snap install --classic certbot -ln -s /snap/bin/certbot /usr/bin/certbot -snap set certbot trust-plugin-with-root=ok -snap install certbot-dns-linode - -printf "certbot certonly --agree-tos --non-interactive --dns-linode --dns-linode-credentials /root/linode.ini --dns-linode-propagation-seconds 180 --no-eff-email --no-redirect --email finnbearone@gmail.com -d $DOMAIN -d www.$DOMAIN -d $SERVER_ID.$DOMAIN" > get_ssl_cert.sh -chmod u+x /root/get_ssl_cert.sh -./get_ssl_cert.sh - -#echo "Creating server download script..." -#printf "aws s3 cp s3://${aws_s3_bucket.static.bucket}/server /root/game-server\n\nchmod u+x /root/server" > /root/download-game-server.sh -#chmod u+x /root/download-game-server.sh - -#echo "Downloading server..." -#/root/download-game-server.sh - -echo "Installing service..." -cat < /etc/systemd/system/game-server.service -[Unit] -Description=Game Server - -[Service] -Type=simple -User=root -Group=root -Restart=always -RestartSec=3 -EnvironmentFile=/etc/environment -WorkingDirectory=~ -ExecStart=/root/server \ - --server-id $SERVER_ID \ - --ip-address $IP_ADDRESS \ - --domain $DOMAIN \ - --chat-log /root/chat.log \ - --trace-log /root/trace.log \ - --admin-config-file /root/admin.toml \ - --discord-client-secret $DISCORD_CLIENT_SECRET \ - --discord-bot-token $DISCORD_BOT_TOKEN \ - --linode-personal-access-token $LINODE_TOKEN \ - --certificate-path /etc/letsencrypt/live/$DOMAIN/fullchain.pem \ - --private-key-path /etc/letsencrypt/live/$DOMAIN/privkey.pem - -[Install] -WantedBy=multi-user.target -EOF - -echo "Enabling service..." -sudo systemctl daemon-reload -sudo systemctl start game-server -sudo systemctl enable game-server - -echo "Installing util scripts..." -printf "journalctl -a -f -o cat -u game-server" > /root/view-game-server-logs.sh -chmod u+x /root/view-game-server-logs.sh - -printf "sudo systemctl restart game-server" > /root/restart-game-server.sh -chmod u+x /root/restart-game-server.sh - -#printf "/root/download-game-server.sh\n/root/restart-game-server.sh\n/root/view-game-server-logs.sh" > /root/update-game-server.sh -#chmod u+x /root/update-game-server.sh - -printf "journalctl -a --no-pager -o cat -u game-server | grep -i \$1" > /root/grep-game-server-logs.sh -chmod u+x /root/grep-game-server-logs.sh - -echo "Init done." \ No newline at end of file diff --git a/engine/game_terraform/variable.tf b/engine/game_terraform/variable.tf deleted file mode 100644 index 7045e8a9..00000000 --- a/engine/game_terraform/variable.tf +++ /dev/null @@ -1,34 +0,0 @@ -variable "name" { - type = string -} - -variable "domain" { - type = string -} - -variable "servers" { - type = map - default = { - 1 = "us-east" - 2 = "us-east" - } -} - -variable "aws_region" { - type = string -} - -variable "discord_client_secret" { - type = string - sensitive = true -} - -variable "discord_bot_token" { - type = string - sensitive = true -} - -variable "linode_token" { - type = string - sensitive = true -} \ No newline at end of file diff --git a/engine/terraform/.gitignore b/engine/terraform/.gitignore deleted file mode 100644 index 88eff74f..00000000 --- a/engine/terraform/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -.terraform/ -*.hcl diff --git a/engine/terraform/dynamodb.tf b/engine/terraform/dynamodb.tf deleted file mode 100644 index 11b5ed6f..00000000 --- a/engine/terraform/dynamodb.tf +++ /dev/null @@ -1,125 +0,0 @@ -resource "aws_dynamodb_table" "sessions" { - name = "core_sessions" - billing_mode = "PAY_PER_REQUEST" - hash_key = "arena_id" - range_key = "session_id" - - attribute { - name = "arena_id" - type = "N" - } - - attribute { - name = "session_id" - type = "N" - } - - ttl { - attribute_name = "ttl" - enabled = true - } - - point_in_time_recovery { - enabled = true - } -} - -resource "aws_dynamodb_table" "scores" { - name = "core_scores" - billing_mode = "PAY_PER_REQUEST" - hash_key = "game_id_score_type" - range_key = "alias" - - attribute { - name = "game_id_score_type" - type = "S" - } - - attribute { - name = "alias" - type = "S" - } - - ttl { - attribute_name = "ttl" - enabled = true - } - - point_in_time_recovery { - enabled = true - } -} - -resource "aws_dynamodb_table" "metrics" { - name = "core_metrics" - billing_mode = "PAY_PER_REQUEST" - hash_key = "game_id" - range_key = "timestamp" - - attribute { - name = "game_id" - type = "S" - } - - attribute { - name = "timestamp" - type = "N" - } - - point_in_time_recovery { - enabled = true - } -} - -resource "aws_dynamodb_table" "users" { - name = "core_users" - billing_mode = "PAY_PER_REQUEST" - hash_key = "user_id" - - attribute { - name = "user_id" - type = "N" - } - - stream_enabled = true - stream_view_type = "NEW_IMAGE" - - point_in_time_recovery { - enabled = true - } -} - -resource "aws_dynamodb_table" "logins" { - name = "core_logins" - billing_mode = "PAY_PER_REQUEST" - hash_key = "login_type" - range_key = "id" - - attribute { - name = "login_type" - type = "S" - } - - attribute { - name = "id" - type = "S" - } - - attribute { - name = "user_id" - type = "N" - } - - global_secondary_index { - hash_key = "user_id" - name = "user_id" - projection_type = "ALL" - } - - stream_enabled = true - stream_view_type = "NEW_IMAGE" - - point_in_time_recovery { - enabled = true - } -} diff --git a/engine/terraform/firewall.tf b/engine/terraform/firewall.tf deleted file mode 100644 index 8a5a55e9..00000000 --- a/engine/terraform/firewall.tf +++ /dev/null @@ -1,28 +0,0 @@ -resource "linode_firewall" "game_server" { - label = "game_server" - tags = [] - - inbound { - label = "HTTP_SSH" - action = "ACCEPT" - protocol = "TCP" - ports = "443,80,22" - ipv4 = ["0.0.0.0/0"] - ipv6 = ["::/0"] - } - - inbound { - label = "ICMP" - action = "ACCEPT" - protocol = "ICMP" - ipv4 = ["0.0.0.0/0"] - ipv6 = ["::/0"] - } - - inbound_policy = "DROP" - outbound_policy = "ACCEPT" -} - -output "game_server_firewall_id" { - value = linode_firewall.game_server.id -} \ No newline at end of file diff --git a/engine/terraform/iam.tf b/engine/terraform/iam.tf deleted file mode 100644 index 4b470ece..00000000 --- a/engine/terraform/iam.tf +++ /dev/null @@ -1,55 +0,0 @@ -resource "aws_iam_access_key" "servers" { - user = aws_iam_user.servers.name -} - -resource "aws_iam_user" "servers" { - name = "${var.name}_servers" - path = "/system/" -} - -resource "aws_iam_user_policy" "servers" { - name = "${var.name}_servers" - user = aws_iam_user.servers.name - - policy = <