Skip to content

Commit

Permalink
Initial Commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Hockeyfan360 committed Mar 12, 2017
0 parents commit 359c883
Show file tree
Hide file tree
Showing 12 changed files with 1,417 additions and 0 deletions.
621 changes: 621 additions & 0 deletions License.txt

Large diffs are not rendered by default.

44 changes: 44 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# Capatchafy - The only spambot solution you'll ever need.

### What is Capatchafy?
Capatchafy is a Spigot plugin/extension for Minecraft servers. Its sole purpose is to protect against spambot attacks. When a server is under attack, Capatchafy directs players to solve a capatcha before joining. This prevents spambots from flooding and crashing a server. Attacks are automatically detected by Capatchafy, so you can kick back and let Capatchafy do the work.

### How does Capatchafy work?
From a user's standpoint, during an attack, they will be kicked and ask to solve a capatcha at example.com:port/capatcha/. Once the capatcha is solved, their ip is added to a list of authorized IPs and they are allowed to join.

Capatchafy runs on a lightweight, embedded Grizzly container for Jersey. This allows us to make full use of the jax-rs API. When a player accesses the capatcha URL in their browser, they send an HTTP/GET request to the server, which is processed by Capatchafy. Capatchafy serves the user the capatcha. The player solves the capatcha. Their capatcha data is POSTed back to the server, and is then sent off to Google to be verified. Once Google gives the okay, the player's IP is added to the list of authorized IPs.

### Features
- Capatcha-based Spam-bot Prevention.
- IP Whitelisting
- Automatic Attack Detection
- Multiple Security Modes
- Check the Issues tab for more.

### How do I use Capatchafy?
Capatchafy comes with one simple command: /capatchafy.

Usage: /capatchafy <on:off> <friendly:moderate:strict> or /capatchafy <on:off> <1:2:3>
The on/off parameter will turn on/turn off Capatcha based verification. The second parameter is the security level.

Security levels:
1/Friendly - Players will only have to solve a capatcha once. Their IPs will be saved in a config for future logins.
2/Moderate - Players will have to solve one capatcha every time the server reloads. (Recommended)
3/Strict - Players will have to solve a capatcha every time they join.

Capatchafy will auto-enable/disable when the server is attacked. You can force Capatchafy to stay off by using the command /capatchafy off -f. Capatchafy will not auto-disable if you enable it using the command.

You will need to assign the permission 'capatchafy.command' to anyone who needs to use /capatchafy. It is assigned to OPs by default.

You can also whitelist IPs in the config. These IPs will never have to solve a capatcha.

### How do I install Capatchafy?
Installation is fairly straight-forward. Drag Capatchafy to your plugins folder like any other add-on, and start your server. This will allow Capatchafy to generate the necessary config files. Then, edit the config as you please. You will need to obtain a reCapatcha key from Google. You can do that here: https://www.google.com/recaptcha/. Place the keys in the config file, and you're ready to go!

---

### Compiling
Capatchafy makes use of Maven, so it should compile automatically. You shouldn't need to add any dependencies or make edits to the POM. However, you MUST use the jar labeled Capatchafy-jar-with-dependencies. If you don't, you will get NoClassDefFound errors. If you have any problems, open an issue.

### License
Capatchafy is licensed under the GNU General Public License v3.0. You can find a copy of it in the License.txt file.
97 changes: 97 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,97 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>me.hockey</groupId>
<artifactId>Capatchafy</artifactId>
<version>1.0</version>
<packaging>jar</packaging>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<jersey.version>${project.version}</jersey.version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>

<repositories>
<repository>
<id>spigot-repo</id>
<url>https://hub.spigotmc.org/nexus/content/repositories/snapshots/</url>
</repository>
</repositories>

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.glassfish.jersey</groupId>
<artifactId>jersey-bom</artifactId>
<version>LATEST</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>

<dependencies>
<dependency>
<groupId>org.glassfish.jersey.containers</groupId>
<artifactId>jersey-container-grizzly2-http</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax.json</groupId>
<artifactId>javax.json-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.glassfish</groupId>
<artifactId>javax.json</artifactId>
<version>LATEST</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.5</version>
</dependency>
<dependency>
<groupId>org.spigotmc</groupId>
<artifactId>spigot-api</artifactId>
<version>1.11.2-R0.1-SNAPSHOT</version>
<scope>provided</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<inherited>true</inherited>
<configuration>
<source>1.7</source>
<target>1.7</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
<configuration>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
</plugin>
</plugins>
</build>
</project>
95 changes: 95 additions & 0 deletions src/main/java/me/hockey/capatchafy/Capatchafy.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
/*
Copyright (C) 2017 James Depp
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package me.hockey.capatchafy;

import me.hockey.capatchafy.httpd.HttpdServer;
import org.bukkit.Bukkit;
import org.bukkit.plugin.java.JavaPlugin;
import org.glassfish.grizzly.http.server.HttpServer;

import java.io.IOException;

public class Capatchafy extends JavaPlugin
{
public static Capatchafy plugin;
public static Listeners listeners;

public static Configuration configs;
public static boolean enabled = false;
public static boolean forced = false; //Disallows auto-enabling/disabling of capatchafy.
public static int securityLevel;
public HttpServer server;

public static boolean error = false;

@Override
public void onEnable()
{
plugin = this;
configs = new Configuration();
listeners = new Listeners();
Bukkit.getPluginManager().registerEvents(listeners, this);
getCommand("capatchafy").setExecutor(new CapatchafyCommand());
try
{
configs = new Configuration();
configs.startup();
if (configs.isIncomplete())
{
Bukkit.getLogger().severe("[Capatchafy] There is information missing in the config. Please make the appropriate changes. " +
"This is normal on the first run. Reload the server once you have made the correct edits.");
Capatchafy.error = true;
Bukkit.getPluginManager().disablePlugin(Capatchafy.plugin);
return;
}
}
catch (IOException e)
{
e.printStackTrace();
}
securityLevel = configs.config.getInt("security-level");
if (securityLevel > 3 || securityLevel < 1)
{
securityLevel = 2;
Bukkit.getLogger().severe("[Capatchafy] The 'security-level' config field was not between 1 and 3. Setting security level to 2.");
}
enabled = configs.config.getBoolean("always-on");
server = HttpdServer.startServer();
Bukkit.getLogger().info("[Capatchafy] Running in security level " + securityLevel + ".");
}

@Override
public void onDisable()
{
if (error)
{
return; //Prevents errors on the first startup.
}

try
{
configs.saveNames(true);
configs.saveConfig();
}
catch (IOException e)
{
e.printStackTrace();
}
server.stop();
configs.ipList.clear(); //TODO See if removing this line affects functionality.
}
}
105 changes: 105 additions & 0 deletions src/main/java/me/hockey/capatchafy/CapatchafyCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
/*
Copyright (C) 2017 James Depp
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package me.hockey.capatchafy;

import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
import org.bukkit.command.CommandSender;

public class CapatchafyCommand implements CommandExecutor
{
//Friendly - One time verification.
//Moderate - One time verification for each time the server starts.
//Strict - Needs verification each time you join/leave.
@Override
public boolean onCommand(CommandSender sender, Command cmd, String cL, String[] args)
{
//TODO Implement command permissions with TFM and bukkit permissions.

if (!sender.hasPermission("capatchafy.command"))
{
sender.sendMessage(ChatColor.RED + "You do not have permission to use this command.");
return true;
}

if (Capatchafy.configs.config.getBoolean("always-on"))
{
sender.sendMessage(ChatColor.RED + "The server owner has Capatchafy enabled at all times. You are not allowed to turn it off or change the security level.");
return true;
}

//TODO Fix arguments problem, it will throw errors if the parameters aren't filled out properly. Also, make it show usage when the security level arg is spelled wrong.
if (args.length < 1)
{
sender.sendMessage("Usage: /capatchafy <on:off> <friendly:moderate:strict>");
return true;
}

if (args[0].equalsIgnoreCase("on"))
{
Capatchafy.enabled = true;
Bukkit.broadcastMessage(ChatColor.DARK_RED + "Capatcha-based verification has been enabled.");

//TODO Add time based disabling of capatchafy. E.g. when admin that turns capatchafy on leaves, turn capatchafy off.
//If it does not match any of these, we just keep the security level as is.
//Remember, the security level only changes when we tell it to with this command.

Capatchafy.forced = true;
Capatchafy.listeners.numberOfAttacks = 0;
if (args.length < 2)
{
sender.sendMessage("Capatchafy will run in security level " + Capatchafy.securityLevel + ". It will not be auto-disabled.");
return true;
}

if (args[1].equalsIgnoreCase("friendly") || args[1].equalsIgnoreCase("1"))
{
Capatchafy.securityLevel = 1;
}
else if (args[1].equalsIgnoreCase("moderate") || args[1].equalsIgnoreCase("2"))
{
Capatchafy.securityLevel = 2;
}
else if (args[1].equalsIgnoreCase("strict") || args[1].equalsIgnoreCase("3"))
{
Capatchafy.securityLevel = 3;
}
else
{
sender.sendMessage("Usage: /capatchafy <on:off> <friendly:moderate:strict>");
}
sender.sendMessage("Capatchafy will run in security level " + Capatchafy.securityLevel + ". It will not be auto-disabled.");
}
else if (args[0].equalsIgnoreCase("off"))
{
Capatchafy.enabled = false;
Capatchafy.forced = false;
Capatchafy.listeners.numberOfAttacks = 0;
Bukkit.broadcastMessage(ChatColor.GREEN + "Capatcha-based verification has been disabled.");
if (args.length < 2)
return true;
if (args[1].equalsIgnoreCase("-f"))
{
Capatchafy.forced = true;
sender.sendMessage(ChatColor.YELLOW + "Capatchafy " + ChatColor.RED + "will not" + ChatColor.YELLOW + " automatically enable if the server detects an attack.");
}
}
return false;
}
}
Loading

0 comments on commit 359c883

Please sign in to comment.