This commit is contained in:
Minecon724 2024-12-10 16:07:45 +01:00
parent b4a3793d5d
commit 0f92f5bcbe
Signed by: Minecon724
GPG key ID: 3CCC4D267742C8E8
12 changed files with 378 additions and 46 deletions

36
pom.xml
View file

@ -20,5 +20,41 @@
<artifactId>Java-WebSocket</artifactId> <artifactId>Java-WebSocket</artifactId>
<version>1.5.7</version> <version>1.5.7</version>
</dependency> </dependency>
<dependency>
<groupId>com.github.seancfoley</groupId>
<artifactId>ipaddress</artifactId>
<version>5.5.1</version>
</dependency>
</dependencies> </dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.6.0</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<createDependencyReducedPom>false</createDependencyReducedPom>
<minimizeJar>true</minimizeJar>
<filters>
<filter>
<artifact>**</artifact>
<excludes>
<exclude>module-info.class</exclude>
<exclude>META-INF/</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project> </project>

View file

@ -1,7 +1,10 @@
package eu.m724.autopeerer.client; package eu.m724.autopeerer.client;
import eu.m724.autopeerer.packet.Packets; import eu.m724.autopeerer.packet.Packets;
import eu.m724.autopeerer.packet.PingRequestPacket; import eu.m724.autopeerer.packet.client.PingRequestPacket;
import eu.m724.autopeerer.packet.client.VpnRequestPacket;
import inet.ipaddr.IPAddressString;
import inet.ipaddr.ipv6.IPv6Address;
import org.java_websocket.client.WebSocketClient; import org.java_websocket.client.WebSocketClient;
import org.java_websocket.handshake.ServerHandshake; import org.java_websocket.handshake.ServerHandshake;
@ -32,9 +35,10 @@ public class MyWebsocketClient extends WebSocketClient {
System.out.printf("Connected in %.3f ms\n", connectTime); System.out.printf("Connected in %.3f ms\n", connectTime);
try { try {
for (int i=0; i<10; i++) { send(Packets.compose(new PingRequestPacket((short)1, InetAddress.getByName("1.1.1.3"))));
send(Packets.compose(new PingRequestPacket((short)i, InetAddress.getByName("1.1.1." + i)))); send(Packets.compose(new PingRequestPacket((short)2, InetAddress.getByName("1.1.1.1"))));
}
send(Packets.compose(new VpnRequestPacket((short)1, (IPv6Address) new IPAddressString("fefe::fefe").getAddress(), "sAt8JSXW4leihcAAdsghsfgFWkO5stBZJm87PGLZFXY=", "example.com", 6823)));
} catch (UnknownHostException e) { } catch (UnknownHostException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

View file

@ -1,9 +1,10 @@
package eu.m724.autopeerer.client; package eu.m724.autopeerer.client;
import eu.m724.autopeerer.packet.Packet; import eu.m724.autopeerer.client.wireguard.WireGuardSession;
import eu.m724.autopeerer.packet.Packets; import eu.m724.autopeerer.packet.*;
import eu.m724.autopeerer.packet.PingRequestPacket; import eu.m724.autopeerer.packet.client.PingRequestPacket;
import eu.m724.autopeerer.packet.PingResponsePacket; import eu.m724.autopeerer.packet.client.VpnRequestPacket;
import eu.m724.autopeerer.packet.server.PingResponsePacket;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.IOException; import java.io.IOException;
@ -34,8 +35,15 @@ public class PacketHandler {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
if (p instanceof PingRequestPacket packet) {System.out.printf("Ping request #%d to %s\n", packet.requestId, packet.target.getHostAddress()); if (p instanceof PingRequestPacket packet) {
handlePingRequest(packet);
} else if (p instanceof VpnRequestPacket packet) {
handleVpnRequest(packet);
}
}
private void handlePingRequest(PingRequestPacket packet) {
System.out.printf("Ping request #%d to %s\n", packet.requestId, packet.target.getHostAddress());
CompletableFuture.runAsync(() -> { CompletableFuture.runAsync(() -> {
float average = -1, meanDeviation = -1; float average = -1, meanDeviation = -1;
var status = PingResponsePacket.PingResponseStatus.ERROR; var status = PingResponsePacket.PingResponseStatus.ERROR;
@ -70,5 +78,9 @@ public class PacketHandler {
sender.accept(new PingResponsePacket(packet.requestId, status, average, meanDeviation).serialize()); sender.accept(new PingResponsePacket(packet.requestId, status, average, meanDeviation).serialize());
}); });
} }
private void handleVpnRequest(VpnRequestPacket packet) {
var session = new WireGuardSession(12345, "serverpoecjteta", "fefe:fefe::fefe", packet.linkLocal.toCompressedString(), packet.endpointHost + ":" + packet.endpointPort, packet.publicKey);
System.err.println(session.config());
} }
} }

View file

@ -0,0 +1,34 @@
package eu.m724.autopeerer.client.wireguard;
import java.io.IOException;
public class WireGuardKeys {
public static String generatePrivateKey() {
try {
Process process = Runtime.getRuntime().exec("wg genkey");
process.waitFor();
return process.inputReader().readLine();
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
}
/**
* Derive a WireGuard public key from a private key
* @param privateKey base64 encoded private key
* @return base64 encoded public key or null if invalid private key
*/
public static String derivePublicKey(String privateKey) {
try {
Process process = Runtime.getRuntime().exec("wg genkey");
process.outputWriter().write(privateKey);
int code = process.waitFor();
if (code != 0) return null;
return process.inputReader().readLine();
} catch (IOException | InterruptedException e) {
throw new RuntimeException(e);
}
}
}

View file

@ -0,0 +1,25 @@
package eu.m724.autopeerer.client.wireguard;
public record WireGuardSession(
int listenPort,
String serverPrivateKey,
String localLinkLocal,
String clientLinkLocal,
String endpoint,
String clientPublicKey
) {
public String config() {
return """
[Interface]
ListenPort = %d
PrivateKey = %s
PostUp = /sbin/ip addr add dev %%i %s peer %s
Table = off
[Peer]
Endpoint = %s
PublicKey = %s
AllowedIPs = ::/0"""
.formatted(listenPort, serverPrivateKey, localLinkLocal, clientLinkLocal, endpoint, clientPublicKey);
}
}

View file

@ -1,5 +1,10 @@
package eu.m724.autopeerer.packet; package eu.m724.autopeerer.packet;
import eu.m724.autopeerer.packet.client.PingRequestPacket;
import eu.m724.autopeerer.packet.client.VpnRequestPacket;
import eu.m724.autopeerer.packet.server.PingResponsePacket;
import eu.m724.autopeerer.packet.server.VpnResponsePacket;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
public class Packets { public class Packets {
@ -10,6 +15,8 @@ public class Packets {
if (id == 1) { if (id == 1) {
packet = PingRequestPacket.deserialize(buffer); packet = PingRequestPacket.deserialize(buffer);
} else if (id == 2) {
packet = VpnRequestPacket.deserialize(buffer);
} }
return packet; return packet;
@ -21,7 +28,9 @@ public class Packets {
Packet<?> packet = null; Packet<?> packet = null;
if (id == 1) { if (id == 1) {
PingResponsePacket.deserialize(buffer); packet = PingResponsePacket.deserialize(buffer);
} else if (id == 2) {
packet = VpnResponsePacket.deserialize(buffer);
} }
return packet; return packet;

View file

@ -0,0 +1,43 @@
package eu.m724.autopeerer.packet.client;
import eu.m724.autopeerer.packet.Packet;
import inet.ipaddr.ipv6.IPv6Address;
import java.nio.ByteBuffer;
public class BgpRequestPacket implements Packet<BgpRequestPacket> {
public final short id;
public final long asn;
public final IPv6Address linkLocal;
public BgpRequestPacket(short id, long asn, IPv6Address linkLocal) {
this.id = id;
this.asn = asn;
this.linkLocal = linkLocal;
}
@Override
public byte getId() {
return 3;
}
@Override
public ByteBuffer serialize() {
ByteBuffer buffer = ByteBuffer.allocate(22);
buffer.putShort(id);
buffer.putInt((int) (asn & 0xFFFFFFFFL));
buffer.put(linkLocal.getBytes());
return buffer;
}
public static BgpRequestPacket deserialize(ByteBuffer buffer) {
var id = buffer.getShort();
var asn = Integer.toUnsignedLong(buffer.getInt());
var ip = new byte[16];
buffer.get(ip);
var linkLocal = new IPv6Address(ip);
return new BgpRequestPacket(id, asn, linkLocal);
}
}

View file

@ -1,4 +1,6 @@
package eu.m724.autopeerer.packet; package eu.m724.autopeerer.packet.client;
import eu.m724.autopeerer.packet.Packet;
import java.net.Inet6Address; import java.net.Inet6Address;
import java.net.InetAddress; import java.net.InetAddress;

View file

@ -0,0 +1,80 @@
package eu.m724.autopeerer.packet.client;
import eu.m724.autopeerer.packet.Packet;
import inet.ipaddr.HostName;
import inet.ipaddr.HostNameException;
import inet.ipaddr.IPAddressString;
import inet.ipaddr.ipv6.IPv6Address;
import java.net.IDN;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class VpnRequestPacket implements Packet<VpnRequestPacket> {
public final short connectionId;
public final IPv6Address linkLocal;
public final String publicKey;
public final String endpointHost;
public final int endpointPort;
public VpnRequestPacket(short connectionId, IPv6Address linkLocal, String publicKey, String endpointHost, int endpointPort) {
this.connectionId = connectionId;
this.linkLocal = linkLocal;
assert new IPAddressString("fe80::/10").getAddress().contains(linkLocal);
this.publicKey = publicKey;
assert Base64.getDecoder().decode(publicKey).length == 32;
this.endpointHost = IDN.toASCII(endpointHost, IDN.ALLOW_UNASSIGNED);
try {
new HostName(endpointHost).validate();
} catch (HostNameException e) {
throw new RuntimeException(e);
}
this.endpointPort = endpointPort;
assert endpointPort > 0 && endpointPort < 65536;
}
@Override
public byte getId() {
return 2;
}
public static VpnRequestPacket deserialize(ByteBuffer buffer) throws Exception {
var id = buffer.getShort();
var ll = new byte[16];
buffer.get(ll);
var linkLocal = new IPv6Address(ll);
var pk = new byte[32];
buffer.get(pk);
var publicKey = Base64.getEncoder().encodeToString(pk);
var endpointPort = buffer.getShort();
var epl = buffer.get() & 0xFF;
var ep = new byte[epl];
buffer.get(ep);
var endpointHost = new String(ep, StandardCharsets.US_ASCII);
return new VpnRequestPacket(id, linkLocal, publicKey, endpointHost, endpointPort);
}
@Override
public ByteBuffer serialize() {
var buffer = ByteBuffer.allocate(53 + endpointHost.length());
buffer.putShort(connectionId); // 2b
buffer.put(linkLocal.getBytes()); // 16b
buffer.put(Base64.getDecoder().decode(publicKey)); // 32b
buffer.putShort((short)endpointPort); // 2b
buffer.put((byte) endpointHost.length()); // 1b
buffer.put(endpointHost.getBytes(StandardCharsets.US_ASCII));
return buffer;
}
}

View file

@ -0,0 +1,37 @@
package eu.m724.autopeerer.packet.server;
import eu.m724.autopeerer.packet.Packet;
import java.nio.ByteBuffer;
public class BgpResponsePacket implements Packet<BgpResponsePacket> {
public final short id;
public final boolean success;
public BgpResponsePacket(short id, boolean success) {
this.id = id;
this.success = success;
}
@Override
public byte getId() {
return 3;
}
@Override
public ByteBuffer serialize() {
ByteBuffer buffer = ByteBuffer.allocate(3);
buffer.putShort(id);
buffer.put((byte) (success ? 1 : 0));
return buffer;
}
public static BgpResponsePacket deserialize(ByteBuffer buffer) {
var id = buffer.getShort();
var success = buffer.get() == 1;
return new BgpResponsePacket(id, success);
}
}

View file

@ -1,4 +1,6 @@
package eu.m724.autopeerer.packet; package eu.m724.autopeerer.packet.server;
import eu.m724.autopeerer.packet.Packet;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;

View file

@ -0,0 +1,48 @@
package eu.m724.autopeerer.packet.server;
import eu.m724.autopeerer.packet.Packet;
import java.nio.ByteBuffer;
import java.util.Base64;
public class VpnResponsePacket implements Packet<VpnResponsePacket> {
public final short connectionId;
public final boolean success;
public final int port;
public final String publicKey;
public VpnResponsePacket(short connectionId, boolean success, int port, String publicKey) {
this.connectionId = connectionId;
this.success = success;
this.port = port;
this.publicKey = publicKey;
}
@Override
public byte getId() {
return 2;
}
public static VpnResponsePacket deserialize(ByteBuffer buffer) throws Exception {
var id = buffer.getShort();
var port = buffer.getShort() & 0xFFFF;
var success = port != 0;
var pkb = new byte[32];
buffer.get(pkb);
var publicKey = Base64.getEncoder().encodeToString(pkb);
return new VpnResponsePacket(id, success, port, publicKey);
}
@Override
public ByteBuffer serialize() {
var buffer = ByteBuffer.allocate(35);
buffer.putShort(connectionId); // 2b
buffer.put((byte) (success ? 1 : 0));
buffer.put(Base64.getDecoder().decode(publicKey));
return buffer;
}
}