mirror of
https://github.com/funkemunky/AntiVPN.git
synced 2026-05-31 09:31:54 +00:00
Fixed CIDR notations and the ability for mongo to properly grab CIDRs
This commit is contained in:
@@ -78,6 +78,8 @@ public class AllowlistCommand extends Command {
|
||||
String safeSearch = search != null ? search.replace("&", "") : null;
|
||||
boolean databaseEnabled = AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled();
|
||||
|
||||
AntiVPN.getInstance().getExecutor().log("Is Database Enabled: %s", databaseEnabled ? "yes" : "no");
|
||||
|
||||
List<UUID> uuids = databaseEnabled
|
||||
? AntiVPN.getInstance().getDatabase().getAllWhitelisted()
|
||||
: new ArrayList<>(AntiVPN.getInstance().getExecutor().getWhitelisted());
|
||||
|
||||
@@ -207,7 +207,7 @@ public class H2VPN implements VPNDatabase {
|
||||
return;
|
||||
|
||||
try(var statement = Query.prepare("insert into `whitelisted-ranges` (`cidr_string`, `ip_start`, `ip_end`) values (?, ?, ?)")
|
||||
.append(cidr.toString()).append(cidr.getStartIpInt()).append(cidr.getEndIpInt())) {
|
||||
.append(cidr.getCidr()).append(cidr.getStartIpInt()).append(cidr.getEndIpInt())) {
|
||||
statement.execute();
|
||||
|
||||
} catch (SQLException e) {
|
||||
@@ -220,7 +220,7 @@ public class H2VPN implements VPNDatabase {
|
||||
if (!AntiVPN.getInstance().getVpnConfig().isDatabaseEnabled() || MySQL.isClosed())
|
||||
return;
|
||||
|
||||
try(var statement = Query.prepare("delete from `whitelisted-ranges` where `cidr_string` = ?").append(cidr.toString())) {
|
||||
try(var statement = Query.prepare("delete from `whitelisted-ranges` where `cidr_string` = ?").append(cidr.getCidr())) {
|
||||
statement.execute();
|
||||
|
||||
} catch (SQLException e) {
|
||||
@@ -253,7 +253,11 @@ public class H2VPN implements VPNDatabase {
|
||||
try(var statement = Query.prepare("select `cidr_string`, `ip_start`, `ip_end` from `whitelisted-ranges`")) {
|
||||
statement.execute(set -> {
|
||||
try {
|
||||
ips.add(new CIDRUtils(set.getString("cidr_string")));
|
||||
String cidrString = set.getString("cidr_string");
|
||||
|
||||
AntiVPN.getInstance().getExecutor().log("CIDR String: %s", cidrString);
|
||||
ips.add(new CIDRUtils(cidrString));
|
||||
|
||||
} catch (UnknownHostException e) {
|
||||
AntiVPN.getInstance().getExecutor()
|
||||
.logException("Could not format ip "
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* Copyright 2026 Dawson Hessler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dev.brighten.antivpn.database.local.version;
|
||||
|
||||
import dev.brighten.antivpn.AntiVPN;
|
||||
import dev.brighten.antivpn.database.DatabaseException;
|
||||
import dev.brighten.antivpn.database.VPNDatabase;
|
||||
import dev.brighten.antivpn.database.sql.utils.Query;
|
||||
import dev.brighten.antivpn.database.version.Version;
|
||||
import dev.brighten.antivpn.utils.CIDRUtils;
|
||||
import dev.brighten.antivpn.utils.MiscUtils;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.net.UnknownHostException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class Third implements Version<VPNDatabase> {
|
||||
@Override
|
||||
public void update(VPNDatabase database) throws DatabaseException {
|
||||
List<CIDRUtils> ipRanges = new ArrayList<>();
|
||||
List<CIDRUtils> rangesToInsert = new ArrayList<>();
|
||||
List<BigInteger[]> rangesToRemove = new ArrayList<>();
|
||||
try (var preparedQuery = Query.prepare("select ip_start, ip_end from `whitelist-ranges`")) {
|
||||
preparedQuery.execute(set -> {
|
||||
BigInteger start = set.getBigDecimal("ip_start").toBigInteger();
|
||||
BigInteger end = set.getBigDecimal("ip_end").toBigInteger();
|
||||
|
||||
try {
|
||||
var range = MiscUtils.rangeToCidrs(start, end);
|
||||
|
||||
if(range.size() > 1) {
|
||||
rangesToRemove.add(new BigInteger[]{start, end});
|
||||
rangesToInsert.addAll(range);
|
||||
AntiVPN.getInstance().getExecutor().log(Level.WARNING, "Found multiple CIDR ranges for whitelist range for %s, %s!", start, end);
|
||||
} else ipRanges.addAll(range);
|
||||
} catch (UnknownHostException e) {
|
||||
AntiVPN.getInstance().getExecutor().logException(
|
||||
String.format("Could not convert ip range to CIDR! %s, %s", start, end), e);
|
||||
}
|
||||
});
|
||||
} catch (SQLException e) {
|
||||
AntiVPN.getInstance().getExecutor().logException("Could not get all whitelisted ranges due to SQL error.", e);
|
||||
}
|
||||
|
||||
AntiVPN.getInstance().getExecutor().log("Inserting %s new ranges into database...", rangesToInsert.size());
|
||||
|
||||
for (CIDRUtils cidr : rangesToInsert) {
|
||||
try(var statement = Query.prepare("insert into `whitelisted-ranges` (`cidr_string`, `ip_start`, `ip_end`) values (?, ?, ?)")
|
||||
.append(cidr.getCidr()).append(cidr.getStartIpInt()).append(cidr.getEndIpInt())) {
|
||||
statement.execute();
|
||||
} catch (SQLException e) {
|
||||
AntiVPN.getInstance().getExecutor().logException("Could not add cidr '" + cidr + "' to whitelist due to SQL error.", e);
|
||||
}
|
||||
}
|
||||
|
||||
AntiVPN.getInstance().getExecutor().log("Removing %s old ranges from database...", rangesToRemove.size());
|
||||
|
||||
for (BigInteger[] range : rangesToRemove) {
|
||||
try(var statement = Query.prepare("delete from `whitelisted-ranges` where `ip_start` = ? and `ip_end` = ?")) {
|
||||
statement.append(range[0]).append(range[1]).execute();
|
||||
} catch (SQLException e) {
|
||||
AntiVPN.getInstance().getExecutor().logException("Could not remove cidr range '" + range[0] + ", " + range[1] + "' from whitelist due to SQL error.", e);
|
||||
}
|
||||
}
|
||||
|
||||
AntiVPN.getInstance().getExecutor().log("Updating %s ranges to proper CIDR notation with the database", ipRanges.size());
|
||||
|
||||
for (CIDRUtils cidr : ipRanges) {
|
||||
try(var statement = Query.prepare("update `whitelisted-ranges` set `cidr_string` = ? where `ip_start` = ? and `ip_end` = ?")) {
|
||||
statement.append(cidr.getCidr()).append(cidr.getStartIpInt()).append(cidr.getEndIpInt()).execute();
|
||||
} catch (SQLException e) {
|
||||
AntiVPN.getInstance().getExecutor().logException("Could not update cidr '" + cidr + "' to proper CIDR notation in whitelist due to SQL error.", e);
|
||||
}
|
||||
}
|
||||
|
||||
try (var preparedStatement = Query.prepare("INSERT INTO `database_version` (`version`) VALUES (?)").append(versionNumber())) {
|
||||
preparedStatement.execute();
|
||||
} catch (SQLException e) {
|
||||
AntiVPN.getInstance().getExecutor().logException("Could not update database version to 2 due to SQL error.", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int versionNumber() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsUpdate(VPNDatabase database) {
|
||||
try (var statement = Query.prepare("select * from `database_version` where version = 2")) {
|
||||
try(var set = statement.executeQuery()) {
|
||||
return set.getFetchSize() == 0;
|
||||
}
|
||||
} catch (SQLException e) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -183,7 +183,7 @@ public class MongoVPN implements VPNDatabase {
|
||||
Document doc = new Document("setting", "whitelist");
|
||||
doc.append("ip_start", new Decimal128(new BigDecimal(cidr.getStartIpInt())));
|
||||
doc.append("ip_end", new Decimal128(new BigDecimal(cidr.getEndIpInt())));
|
||||
doc.append("cidr_string", cidr.toString());
|
||||
doc.append("cidr_string", cidr.getCidr());
|
||||
|
||||
settingsDocument.insertOne(doc);
|
||||
}
|
||||
@@ -210,7 +210,7 @@ public class MongoVPN implements VPNDatabase {
|
||||
public List<CIDRUtils> getAllWhitelistedIps() {
|
||||
List<CIDRUtils> ips = new ArrayList<>();
|
||||
settingsDocument.find(Filters.and(Filters.eq("setting", "whitelist"),
|
||||
Filters.exists("ip"))).forEach((Consumer<? super Document>) doc -> {
|
||||
Filters.exists("cidr_string"))).forEach((Consumer<? super Document>) doc -> {
|
||||
try {
|
||||
var cidr = new CIDRUtils(doc.getString("cidr_string"));
|
||||
ips.add(cidr);
|
||||
|
||||
+108
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* Copyright 2026 Dawson Hessler
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package dev.brighten.antivpn.database.mongo.version;
|
||||
|
||||
import com.mongodb.client.model.Filters;
|
||||
import dev.brighten.antivpn.AntiVPN;
|
||||
import dev.brighten.antivpn.database.DatabaseException;
|
||||
import dev.brighten.antivpn.database.mongo.MongoVPN;
|
||||
import dev.brighten.antivpn.database.version.Version;
|
||||
import dev.brighten.antivpn.utils.CIDRUtils;
|
||||
import dev.brighten.antivpn.utils.MiscUtils;
|
||||
import org.bson.Document;
|
||||
import org.bson.types.Decimal128;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.logging.Level;
|
||||
|
||||
public class MongoThird implements Version<MongoVPN> {
|
||||
@Override
|
||||
public void update(MongoVPN database) throws DatabaseException {
|
||||
List<CIDRUtils> ipRanges = new ArrayList<>();
|
||||
List<CIDRUtils> rangesToInsert = new ArrayList<>();
|
||||
List<BigInteger[]> rangesToRemove = new ArrayList<>();
|
||||
database.settingsDocument.find(Filters.and(Filters.eq("setting", "whitelist"), Filters.exists("cidr_string")))
|
||||
.forEach((Consumer<? super Document>) doc -> {
|
||||
BigInteger start = doc.get("ip_start", Decimal128.class).bigDecimalValue().toBigInteger();
|
||||
BigInteger end = doc.get("ip_end", Decimal128.class).bigDecimalValue().toBigInteger();
|
||||
|
||||
try {
|
||||
var range = MiscUtils.rangeToCidrs(start, end);
|
||||
|
||||
if(range.size() > 1) {
|
||||
rangesToRemove.add(new BigInteger[]{start, end});
|
||||
rangesToInsert.addAll(range);
|
||||
AntiVPN.getInstance().getExecutor().log(Level.WARNING, "Found multiple CIDR ranges for whitelist range for %s, %s!", start, end);
|
||||
} else ipRanges.addAll(range);
|
||||
} catch (UnknownHostException e) {
|
||||
AntiVPN.getInstance().getExecutor().logException(
|
||||
String.format("Could not convert ip range to CIDR! %s, %s", start, end), e);
|
||||
}
|
||||
});
|
||||
|
||||
if(!rangesToInsert.isEmpty()) {
|
||||
AntiVPN.getInstance().getExecutor().log("Inserting %s new ranges into database...", rangesToInsert.size());
|
||||
var documentsToInsert = rangesToInsert.stream().map(cidr -> {
|
||||
Document doc = new Document("setting", "whitelist");
|
||||
doc.append("ip_start", new Decimal128(new BigDecimal(cidr.getStartIpInt())));
|
||||
doc.append("ip_end", new Decimal128(new BigDecimal(cidr.getEndIpInt())));
|
||||
doc.append("cidr_string", cidr.getCidr());
|
||||
|
||||
return doc;
|
||||
}).toList();
|
||||
|
||||
database.settingsDocument.insertMany(documentsToInsert);
|
||||
}
|
||||
if(!rangesToRemove.isEmpty()) {
|
||||
AntiVPN.getInstance().getExecutor().log("Removing %s old ranges from database...", rangesToRemove.size());
|
||||
rangesToRemove.forEach(range -> database.settingsDocument
|
||||
.deleteMany(Filters.and(
|
||||
Filters.gte("ip_start", new Decimal128(new BigDecimal(range[0]))),
|
||||
Filters.lte("ip_end", new Decimal128(new BigDecimal(range[1]))))));
|
||||
}
|
||||
|
||||
if(!ipRanges.isEmpty()) {
|
||||
AntiVPN.getInstance().getExecutor().log("Updating %s CIDRs in database with proper notation...", ipRanges.size());
|
||||
|
||||
ipRanges.forEach(cidr -> database.settingsDocument
|
||||
.updateMany(Filters.and(Filters.eq("setting", "whitelist"),
|
||||
Filters.eq("ip_start", new Decimal128(new BigDecimal(cidr.getStartIpInt()))),
|
||||
Filters.eq("ip_end", new Decimal128(new BigDecimal(cidr.getEndIpInt())))),
|
||||
new Document("$set", new Document("cidr_string", cidr.getCidr()))));
|
||||
}
|
||||
|
||||
var versionCollect = database.antivpnDatabase.getCollection("version");
|
||||
versionCollect.insertOne(new Document("version", versionNumber()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int versionNumber() {
|
||||
return 2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean needsUpdate(MongoVPN database) {
|
||||
var versionCollect = database.antivpnDatabase.getCollection("version");
|
||||
|
||||
return versionCollect.find(Filters.eq("version", versionNumber())).first() == null;
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,11 @@ import dev.brighten.antivpn.database.DatabaseException;
|
||||
import dev.brighten.antivpn.database.local.H2VPN;
|
||||
import dev.brighten.antivpn.database.local.version.First;
|
||||
import dev.brighten.antivpn.database.local.version.Second;
|
||||
import dev.brighten.antivpn.database.local.version.Third;
|
||||
import dev.brighten.antivpn.database.mongo.MongoVPN;
|
||||
import dev.brighten.antivpn.database.mongo.version.MongoFirst;
|
||||
import dev.brighten.antivpn.database.mongo.version.MongoSecond;
|
||||
import dev.brighten.antivpn.database.mongo.version.MongoThird;
|
||||
import dev.brighten.antivpn.database.sql.MySqlVPN;
|
||||
import dev.brighten.antivpn.database.sql.version.MySQLFirst;
|
||||
|
||||
@@ -32,7 +34,7 @@ public interface Version<DB> {
|
||||
int versionNumber();
|
||||
boolean needsUpdate(DB database);
|
||||
|
||||
Version<MongoVPN>[] mongoDbVersions = new Version[] {new MongoFirst(), new MongoSecond()};
|
||||
Version<MySqlVPN>[] mysqlVersions = new Version[] {new MySQLFirst(), new Second()};
|
||||
Version<H2VPN>[] h2Versions = new Version[] {new First(), new Second()};
|
||||
Version<MongoVPN>[] mongoDbVersions = new Version[] {new MongoFirst(), new MongoSecond(), new MongoThird()};
|
||||
Version<MySqlVPN>[] mysqlVersions = new Version[] {new MySQLFirst(), new Second(), new Third()};
|
||||
Version<H2VPN>[] h2Versions = new Version[] {new First(), new Second(), new Third()};
|
||||
}
|
||||
@@ -22,6 +22,11 @@ import dev.brighten.antivpn.utils.json.JSONObject;
|
||||
import dev.brighten.antivpn.utils.json.JsonReader;
|
||||
|
||||
import java.io.*;
|
||||
import java.math.BigInteger;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -72,6 +77,43 @@ public class MiscUtils {
|
||||
};
|
||||
}
|
||||
|
||||
public static List<CIDRUtils> rangeToCidrs(BigInteger start, BigInteger end) throws UnknownHostException {
|
||||
List<CIDRUtils> cidrs = new ArrayList<>();
|
||||
|
||||
while (start.compareTo(end) <= 0) {
|
||||
// Find the number of trailing zero bits — this determines max block size alignment
|
||||
int trailingZeros = start.equals(BigInteger.ZERO)
|
||||
? 128 // handle the edge case
|
||||
: start.getLowestSetBit();
|
||||
|
||||
// Find the largest block that fits
|
||||
BigInteger remaining = end.subtract(start).add(BigInteger.ONE);
|
||||
int maxBits = remaining.bitLength() - 1;
|
||||
|
||||
int blockBits = Math.min(trailingZeros, maxBits);
|
||||
int prefixLen = 32 - blockBits; // use 128 for IPv6
|
||||
|
||||
// Build the CIDR string
|
||||
byte[] addrBytes = toFixedLengthBytes(start, 4); // use 16 for IPv6
|
||||
String cidr = InetAddress.getByAddress(addrBytes).getHostAddress() + "/" + prefixLen;
|
||||
cidrs.add(new CIDRUtils(cidr));
|
||||
|
||||
// Advance past this block
|
||||
start = start.add(BigInteger.ONE.shiftLeft(blockBits));
|
||||
}
|
||||
|
||||
return cidrs;
|
||||
}
|
||||
|
||||
private static byte[] toFixedLengthBytes(BigInteger value, int length) {
|
||||
byte[] raw = value.toByteArray();
|
||||
byte[] result = new byte[length];
|
||||
int srcPos = Math.max(0, raw.length - length);
|
||||
int destPos = Math.max(0, length - raw.length);
|
||||
System.arraycopy(raw, srcPos, result, destPos, Math.min(raw.length, length));
|
||||
return result;
|
||||
}
|
||||
|
||||
public static UUID lookupUUID(String playername) {
|
||||
try {
|
||||
JSONObject object = JsonReader
|
||||
|
||||
Reference in New Issue
Block a user