commit 70fd95f2423c2871dd564e0e79b6717a59b4ef0b Author: Liam Date: Sat Apr 27 04:41:08 2024 +0100 initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..60b96d7 --- /dev/null +++ b/.gitignore @@ -0,0 +1,29 @@ +### ME template +*.class +*.log +*.ctxt +.mtj.tmp/ +*.jar +*.war +*.nar +*.ear +*.zip +*.tar.gz +*.rar +hs_err_pid* +replay_pid* +.idea +cmake-build-*/ +.idea/**/mongoSettings.xml +*.iws +out/ +build/ +work/ +.idea_modules/ +atlassian-ide-plugin.xml +com_crashlytics_export_strings.xml +crashlytics.properties +crashlytics-build.properties +fabric.properties +git.properties +pom.xml.versionsBackup diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..26d3352 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,3 @@ +# Default ignored files +/shelf/ +/workspace.xml diff --git a/.idea/encodings.xml b/.idea/encodings.xml new file mode 100644 index 0000000..aa00ffa --- /dev/null +++ b/.idea/encodings.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..010b430 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..94a25f7 --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..058fb54 --- /dev/null +++ b/pom.xml @@ -0,0 +1,40 @@ + + + 4.0.0 + + cc.fascinated.piaservers + PIA-Servers + 1.0-SNAPSHOT + + + 17 + 17 + UTF-8 + + + + + + org.projectlombok + lombok + 1.18.32 + provided + + + com.google.code.gson + gson + 2.9.1 + compile + + + + + org.codehaus.plexus + plexus-archiver + 4.9.2 + + + + \ No newline at end of file diff --git a/src/main/java/cc/fascinated/piaservers/Main.java b/src/main/java/cc/fascinated/piaservers/Main.java new file mode 100644 index 0000000..4965dda --- /dev/null +++ b/src/main/java/cc/fascinated/piaservers/Main.java @@ -0,0 +1,127 @@ +package cc.fascinated.piaservers; + +import cc.fascinated.piaservers.pia.PiaServer; +import cc.fascinated.piaservers.pia.PiaServerToken; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.JsonObject; +import com.google.gson.reflect.TypeToken; +import org.codehaus.plexus.archiver.zip.ZipUnArchiver; +import lombok.SneakyThrows; + +import java.io.File; +import java.net.InetAddress; +import java.net.URI; +import java.net.http.HttpClient; +import java.net.http.HttpRequest; +import java.net.http.HttpResponse; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Date; +import java.util.List; +import java.util.concurrent.TimeUnit; + +public class Main { + private static final Gson GSON = new GsonBuilder() + .setPrettyPrinting() + .create(); + private static final HttpClient HTTP_CLIENT = HttpClient.newHttpClient(); + private static final String PIA_OPENVPN_CONFIGS_URL = "https://www.privateinternetaccess.com/openvpn/openvpn.zip"; + private static final long REMOVAL_THRESHOLD = TimeUnit.DAYS.toMicros(14); // 2 weeks + + @SneakyThrows + public static void main(String[] args) { + File serversFile = new File("servers.json"); + if (!serversFile.exists()) { + System.out.println("serversFile.json does not exist, creating..."); + serversFile.createNewFile(); + } + + List serverDomains = getServerDomains(); + System.out.println("Found " + serverDomains.size() + " server domains"); + + // Load the serversFile from the file + List servers = GSON.fromJson(Files.readString(serversFile.toPath()), new TypeToken() {}.getType()); + if (servers == null) { + servers = new ArrayList<>(); + } + List toRemove = new ArrayList<>(); + + System.out.println("Removing old servers..."); + // Get the servers that need to be removed + for (PiaServer server : servers) { + if (server.getLastSeen().getTime() < System.currentTimeMillis() - REMOVAL_THRESHOLD) { + toRemove.add(server); + } + } + servers.removeAll(toRemove); // Remove the servers + System.out.printf("Removed %s old servers\n", toRemove.size()); + + // Add the new servers to the list + for (PiaServerToken serverToken : serverDomains) { + InetAddress address = InetAddress.getByName(serverToken.getHostname()); + + // Add the server to the list + servers.add(new PiaServer(address.getHostAddress(), serverToken.getRegion(), new Date())); + } + + // Save the servers to the file + Files.writeString(serversFile.toPath(), GSON.toJson(servers)); + System.out.printf("Wrote %s servers to the file\n", servers.size()); + } + + @SneakyThrows + private static List getServerDomains() { + HttpRequest request = HttpRequest.newBuilder() + .uri(URI.create(PIA_OPENVPN_CONFIGS_URL)) + .GET() + .build(); + // Send the request and get the response + HttpResponse response = HTTP_CLIENT.send(request, HttpResponse.BodyHandlers.ofFile(Files.createTempFile("openvpn", ".zip"))); + if (response.statusCode() != 200) { + System.out.println("Failed to get the PIA OpenVPN configs, status code: " + response.statusCode()); + System.exit(1); + } + Path downloadedFile = response.body(); + File tempDir = Files.createTempDirectory("openvpn").toFile(); + ZipUnArchiver unArchiver = new ZipUnArchiver(); + + // Extract the downloaded file + unArchiver.setSourceFile(downloadedFile.toFile()); + unArchiver.setDestDirectory(tempDir); + unArchiver.extract(); + + // Get the extracted files + File[] files = tempDir.listFiles(); + if (files == null || files.length == 0) { + System.out.println("Failed to extract the OpenVPN configs"); + System.exit(1); + } + + // Search for the server domains + List domains = new ArrayList<>(); + for (File file : files) { + if (file.isDirectory()) { + continue; + } + if (!file.getName().endsWith(".ovpn")) { + continue; + } + // Read the file and get the server domain + List lines = Files.readAllLines(file.toPath()); + for (String line : lines) { + if (line.startsWith("remote ")) { + String[] parts = line.split(" "); + String domain = parts[1]; + String region = file.getName().split("\\.")[0]; + + domains.add(new PiaServerToken(domain, region)); + break; + } + } + } + + return domains; + } +} \ No newline at end of file diff --git a/src/main/java/cc/fascinated/piaservers/pia/PiaServer.java b/src/main/java/cc/fascinated/piaservers/pia/PiaServer.java new file mode 100644 index 0000000..1632f58 --- /dev/null +++ b/src/main/java/cc/fascinated/piaservers/pia/PiaServer.java @@ -0,0 +1,24 @@ +package cc.fascinated.piaservers.pia; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Date; + +@AllArgsConstructor @Getter +public class PiaServer { + /** + * The IP of this server. + */ + private final String ip; + + /** + * The region this server is in. + */ + private final String region; + + /** + * The last time this IP was seen. + */ + private Date lastSeen; +} diff --git a/src/main/java/cc/fascinated/piaservers/pia/PiaServerToken.java b/src/main/java/cc/fascinated/piaservers/pia/PiaServerToken.java new file mode 100644 index 0000000..5979c1b --- /dev/null +++ b/src/main/java/cc/fascinated/piaservers/pia/PiaServerToken.java @@ -0,0 +1,17 @@ +package cc.fascinated.piaservers.pia; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +@AllArgsConstructor @Getter +public class PiaServerToken { + /** + * The hostname for this server. + */ + private final String hostname; + + /** + * The region this server is in. + */ + private final String region; +}