Jump to content

Featured Replies

Posted
comment_63123

Hey guys!

I'm here with a little tutorial! 

The RSPS Scene has some notoriously shady characters. It's almost impossible to perm ban people these days because there's always a way to circumvent the standard IP / Mac bans.

Well, today you'll learn how to scan a users IP address and retrieve quality metrics such as;

  • If they're using a VPN
  • If they're on the TOR network
  • If they're using a Proxy
  • A 'Fraud Score' (Based on location, previous suspicious behaviour across the internet etc)
  • And plenty more such as their estimated location, ISP and timezone. 

So, let's get started!

First of all, you're going to need an amazing Java Library called Simple JSON <- Download here!

Once you've added the Jar to your project libraries, you're ready to start!

First of all, let's create a new java class dedicated to our new IP scanner.

All changes in this tutorial are done server sided, however it could easily be converted to a client side tool if you wanted to change logon behaviour based on the responses from the scanner.

In my example, I created IPVerification.java

An ideal location would be: 'src/com/ruse/net/login/'

The next step is to head over to IPQualityScore.com and select 'Get a free API key'

image

After you've signed up, find your API key.

Example: 'FnT1NcQRfDrhqDn43lb3srxnjOmZj2CC'

Now, back to IPVerification.java..

Go ahead and paste in the example from below. I have tried my best to annotate everything!

package com.platinum.net.login;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Scanner;

import com.platinum.GameSettings;
import com.platinum.world.content.discord.DiscordMessenger;
import com.platinum.world.entity.impl.player.Player;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
import org.json.simple.parser.ParseException;

public final class IPVerification {

	private final static String API_KEY = "key here";
	private final static String baseURL = "https://ipqualityscore.com/api/json/ip/" + API_KEY + "/";
	
	public static void manualIPCheck(Player initiator, Player suspect) {
		try {
			//Getting the target IP Address as a string to use in the URL
			String IP = suspect.getHostAddress();
			//The URl that will show the required information.
			URL url = new URL(baseURL + IP);

			HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //Connecting to the URL
			conn.setRequestMethod("GET"); //Sending a 'GET' Request to the URL. This is the same thing that happens when you open a webpage on your PC
			conn.connect(); //Connecting to the session

			//Getting Response Code
			int responseCode = conn.getResponseCode();

			//Response code 200 means a webpage responded to our GET request successfully.
			if (responseCode != 200) {
				throw new RuntimeException("HttpResponseCode: " + responseCode);
			} else {
				Scanner sc = new Scanner(url.openStream()); //Scanner is a class which reads the results from a website response
				StringBuilder inline = new StringBuilder(); //Setting a blank string. We will add the responses to the string to build up our results
				while(sc.hasNext()) //While there are still responses, we add them to the blank string 'inline'
				{
					inline.append(sc.nextLine()); //Adding the response to nextline blank string
				}
				//System.out.println(inline); //If you want to see the full result in the console, uncomment this line (Good for debugging)
				sc.close(); //Closes the connection to prevent mem leaks!

				JSONParser parse = new JSONParser(); //Starting a new JSONParses session
				JSONObject obj = (JSONObject) parse.parse(inline.toString()); //Creating a new JSONObject and setting it equal to everything inside 'inline'

				//Using data from JSON
				String ip = obj.get("host").toString();
				boolean VPN = obj.get("vpn").toString().equals("true");
				boolean tor = obj.get("tor").toString().equals("true");
				boolean proxy = obj.get("proxy").toString().equals("true");
				boolean bot_status = obj.get("bot_status").toString().equals("true");
				int fraudScore = Integer.parseInt(obj.get("fraud_score").toString());
				String country = obj.get("country_code").toString();
				String region = obj.get("region").toString();
				String city = obj.get("city").toString();
				String isp = obj.get("ISP").toString();

				//Adding asterisks either side to make them bold in Discord
				String susUser = "**" + suspect.getUsername() + "**";
				String initUser = "**" + initiator.getUsername() + "**";

				//Formatting the results. \n is an expression that creates a new line. Purely for formatting because I have aids level OCD
				String results = "IP Scan on " + susUser + "\nIP: " + ip + "\nVPN: " + VPN + "\nTor: " + tor + "\nProxy: " + proxy + "\nBot Status: " + bot_status + "\nFraud Score: " + fraudScore + "\nCountry: " + country + "\nRegion: " + region + "\nCity: " + city + "\nISP: " + isp + "\nScan Requested by: " + initUser;
				System.out.println(results);
				DiscordMessenger.sendStaffMessage(results); //This is the location that I sent the results to, this should be changed to whatever is most relevant for you!
			}
		} catch (IOException | ParseException e) {
			e.printStackTrace();
		}
	}

	public static boolean autoIPCheck(Player suspect, String IP) {
		boolean shouldBlock = false;

		try {
			//The URl that will show the required information.
			URL url = new URL(baseURL + IP);

			HttpURLConnection conn = (HttpURLConnection) url.openConnection(); //Connecting to the URL
			conn.setRequestMethod("GET"); //Sending a 'GET' Request to the URL. This is the same thing that happens when you open a webpage on your PC
			conn.connect(); //Connecting to the session

			//Getting Response Code
			int responseCode = conn.getResponseCode();

			//Response code 200 means a webpage responded to our GET request successfully.
			if (responseCode != 200) {
				throw new RuntimeException("HttpResponseCode: " + responseCode);
			} else {
				Scanner sc = new Scanner(url.openStream()); //Scanner is a class which reads the results from a website response
				StringBuilder inline = new StringBuilder(); //Setting a blank string. We will add the responses to the string to build up our results
				while(sc.hasNext()) {//While there are still responses, we add them to the blank string 'inline'
					inline.append(sc.nextLine()); //Adding the response to nextline blank string
				}
				//System.out.println(inline); //If you want to see the full result in the console, uncomment this line (Good for debugging)
				sc.close(); //Closes the connection to prevent mem leaks!

				JSONParser parse = new JSONParser(); //Starting a new JSONParses session
				JSONObject obj = (JSONObject) parse.parse(inline.toString()); //Creating a new JSONObject and setting it equal to everything inside 'inline'

				//Using data from JSON
				String ip = obj.get("host").toString();
				boolean VPN = obj.get("vpn").toString().equals("true");
				boolean tor = obj.get("tor").toString().equals("true");
				boolean proxy = obj.get("proxy").toString().equals("true");
				boolean bot_status = obj.get("bot_status").toString().equals("true");
				int fraudScore = Integer.parseInt(obj.get("fraud_score").toString());
				String country = obj.get("country_code").toString();
				String region = obj.get("region").toString();
				String city = obj.get("city").toString();
				String isp = obj.get("ISP").toString();
				//Adding asterisks either side to make them bold in Discord
				String susUser = "**" + suspect.getUsername() + "**";
				//Formatting the results. \n is an expression that creates a new line. Purely for formatting because I have aids level OCD
				String results = "LOGON BLOCKED FOR " + susUser + "\nIP: " + ip +"\nVPN: " + VPN + "\nTor: " + tor + "\nProxy: " + proxy + "\nBot Status: " + bot_status + "\nFraud Score: " + fraudScore + "\nCountry: " + country + "\nRegion: " + region + "\nCity: " + city + "\nISP: " + isp;

				if ((VPN || tor || (proxy && fraudScore > 90) || bot_status)
						&& !GameSettings.DEVELOPERSERVER
						&& !suspect.getRights().isSeniorStaff() //Excluding senior staff
						&& !suspect.getRights().isMember()) { //Only sending the info to staff if these prereqs are met
					DiscordMessenger.sendStaffMessage(results); //This is the location that I sent the results to, this should be changed to whatever is most relevant for you!
					shouldBlock = true;
				}
			}
		} catch (IOException | ParseException e) {
			e.printStackTrace();
		}
		return shouldBlock;
	}
}

Be sure that the JSONParser and JSONObject methods are imported from the SimpleJson lib 'org.json.simple.*'

An example command where you'd use the method..

if (command[0].equals("checkip")) {
            try {
                Player target = World.getPlayerByName(wholeCommand.substring(command[0].length() + 1));
                assert target != null;
                IPVerification.manualIPCheck(player, target);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

Of course you can use this anywhere, including in your login responses if you wanted to block access to anyone using a VPN!

Here's the final result send into Discord.

image

Now, blocking VPN Logins..

Under ConnectionHandler.java you'll find the 'getResponse' method.

Add in: 

if (IPVerification.autoIPCheck(player, host) && !GameSettings.DEVELOPERSERVER){
			PlayerPunishment.addBannedIP(host); //Also ban the IP once flagged
			return LoginResponses.LOGIN_REJECT_VPN;
		}
//Remove the !GameSettings.DEVELOPERSERVER if you don't have that.
//The autocheck method ignores local IP addresses anyway.

Next, you'll want to repurpose an unused LoginResponse found in 'LoginResponses.java'

I used response code 10.

Refactor it to match the 'LOGIN_REJECT_VPN' response name featured above! (Ctrl + F6 whilst the old name is highlighted)

OBwo6SV.png

 

Finally, in Client.java, search for loginCode == (The number you chose)

Then update the message :)

if (loginCode == 10) { //VPN Block
				loginMessages = new String[] { "VPN or Proxy Dedected!", "You cannot login using either!" };
				return;
			}

 

 

  • 3 months later...
  • 4 weeks later...
  • 3 months later...
  • 1 year later...

Create an account or sign in to comment