Skip to content

ServerOverflow/matscan

 
 

Repository files navigation

matscan

this is a fork of matscan to fit more within ServerOverflow's infrastructure.
matscan is heavily inspired by masscan, and like masscan contains its own tcp stack for maximum speed.

Changes

  • Store exclusions in MongoDB instead of a configuration file and reload them each run
  • Small changes to the BSON format data is stored as (so it's less confusing)
  • Minor fixes here and there (e.g. only pre-1.13 forge SLP is detected)
  • Ability to set a custom TCP signature to troll honeypot admins
  • Make the output of matscan less bloated with debug information
  • Other miscellaneous changes I can't be bothered to document

Features

  • Adaptive scanning (scans more than just the default port)
  • Works well even on relatively low scan rates and with lots of packet drops (running in production at ~70kpps and ~20% loss)
  • Can be run in a distributed fashion
  • Customizable rescanning (rescan servers with players online more often, etc.)
  • Customizable target host, target port, protocol version
  • Send to a Discord webhook when a player joins/leaves a server
  • Detection of duplicate servers that have the same server on every port
  • Protocol implementation fingerprinting (can identify vanilla, paper, fabric, forge, bungeecord, velocity, node-minecraft-protocol)
  • Prometheus statistics support
  • Historical player tracking
  • Offline-mode detection
  • Written in R*st 🚀🚀🚀

Note

I highly encourage you to make your own server scanner instead of relying on someone else's code, I promise you'll have a lot more fun that way. Can't really blame you though, as this fork exists only because I didn't want to deep dive into networking... at least for now. Also, if you do intend on using any of the code here, please read the license that the original author wrote.

Usage

It is assumed that you know the basics of server scanning. Otherwise, I recommend reading the masscan readme and documentation. Also be aware that matscan only supports Linux, but you probably shouldn't be running it at home anyway.

  1. Rename example-config.toml to config.toml and refer to config.rs for the format.
  2. Create a MongoDB database with all necessary collections and indexes:
use server-overflow
db.createCollection("servers", {
  validator: {
    $jsonSchema: {
      bsonType: "object",
      required: ["minecraft"],
      properties: {
        minecraft: {
          bsonType: "object",
          properties: {
            forgeData: {
              bsonType: ["object", "null"],
              properties: {
                fmlNetworkVersion: { bsonType: ["null", "int", "long"] },
                mods: {
                  bsonType: "array",
                  items: {
                    bsonType: "object",
                    properties: {
                      modId: { bsonType: ["null", "string"] },
                      modmarker: { bsonType: ["null", "string"] },
                    }
                  }
                }
              }
            },
            modinfo: {
              bsonType: ["object", "null"],
              properties: {
                modList: {
                  bsonType: ["array", "null"],
                  items: {
                    bsonType: "object",
                    properties: {
                      modid: { bsonType: ["null", "string"] },
                      version: { bsonType: ["null", "string"] },
                    }
                  }
                }
              }
            },
            version: {
              bsonType: ["object", "null"],
              properties: {
                name: { bsonType: ["null", "string"] },
                protocol: { bsonType: ["null", "int", "long"] },
              }
            },
            players: {
              bsonType: ["object", "null"],
              properties: {
                online: { bsonType: ["null", "int", "long"] },
                max: { bsonType: ["null", "int", "long"] },
                sample: {
                  bsonType: ["array", "null"],
                  items: {
                    bsonType: "object",
                    properties: {
                      name: { bsonType: ["null", "string"] },
                      id: { bsonType: ["null", "string"] },
                    }
                  }
                }
              }
            },
            description: { bsonType: ["null", "string"] },
            favicon: { bsonType: ["null", "string"] },
            enforcesSecureChat: { bsonType: ["bool", "null"] }
          }
        }
      }
    }
  }
})
db.createCollection("bad_servers")
db.createCollection("exclusions")
db.servers.createIndex({ ip: 1, port: 1 }, { unique: true })
db.servers.createIndex({ timestamp: 1 })
  1. Populate the exclusions collection from the included exclude.conf:
const exclude = fs.readFileSync("exclude.conf", 'utf8');
const lines = exclude.split("\n");
let readComment = false;
let readRanges = false;
let ranges = [];
let comment = [];

for (const line of lines) {
  const trimmed = line.trim();
  if (trimmed.startsWith("#")) {
    if (readComment && readRanges) {
      db.exclusions.insertOne({
        ranges: ranges,
        comment: comment.join("\n").trim()
      });

      readComment = false;
      readRanges = false;
      ranges = [];
      comment = [];
    }
    
    comment.push(trimmed.slice(1).trim());
    readComment = true;
  } else if (trimmed) {
    ranges.push(trimmed);
    readRanges = true;
  }
}
  1. Setup iptables, build and start matscan:
# Firewall port 61000 so your OS doesn't close the connections
# Note: You probably want to use something like iptables-persistent to save this across reboots
iptables -A INPUT -p tcp --dport 61000 -j DROP

# Run in release mode
cargo b -r && sudo ./target/release/matscan

About

silly minecraft server scanner (serveroverflow edition)

Resources

License

Stars

Watchers

Forks

Sponsor this project

Languages

  • Rust 100.0%