[Ruse] How to scan player IPs (Proxy & VPN Detection)

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 SimpleJSON ← 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

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!

public static void checkIP(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("https://ipqualityscore.com/api/json/ip/YOUR API KEY/" + 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
				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());

				//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 + "\nVPN: " + VPN + "\nTor: " + tor + "\nProxy: " + proxy + "\nBot Status: " + bot_status + "\nFraud Score: " + fraudScore + "\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();
		}
	}

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("checkipscore")) {
			try {
				Player target = World.getPlayerByName(wholeCommand.substring(command[0].length() + 1));
				assert target != null;
				IPVerification.checkIP(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

If you’d like more information, join our Discord or PM me :slight_smile:

the end GIF

For the curious among you, you can see what the full response looks like by manually pasting the link followed by an IP address.

Here is an example:

{"success":true,"message":"Success","fraud_score":100,"country_code":"US","region":"N\/A","city":"N\/A","ISP":"Loopback","ASN":0,"organization":"Internet Assigned Numbers Authority","is_crawler":false,"timezone":"N\/A","mobile":false,"host":"localhost","proxy":true,"vpn":true,"tor":false,"active_vpn":false,"active_tor":false,"recent_abuse":true,"bot_status":true,"connection_type":"Premium required.","abuse_velocity":"Premium required.","zip_code":"N\/A","latitude":21.29,"longitude":-157.72,"request_id":"4DtCsFZhSgZFS11"}

You can select any data from the response by editing or adding to the class!

<3