-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 359c883
Showing
12 changed files
with
1,417 additions
and
0 deletions.
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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
105
src/main/java/me/hockey/capatchafy/CapatchafyCommand.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | ||
} | ||
} |
Oops, something went wrong.