wip
This commit is contained in:
parent
b4a3793d5d
commit
0f92f5bcbe
12 changed files with 378 additions and 46 deletions
36
pom.xml
36
pom.xml
|
@ -20,5 +20,41 @@
|
|||
<artifactId>Java-WebSocket</artifactId>
|
||||
<version>1.5.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.seancfoley</groupId>
|
||||
<artifactId>ipaddress</artifactId>
|
||||
<version>5.5.1</version>
|
||||
</dependency>
|
||||
</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>
|
|
@ -1,7 +1,10 @@
|
|||
package eu.m724.autopeerer.client;
|
||||
|
||||
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.handshake.ServerHandshake;
|
||||
|
||||
|
@ -32,9 +35,10 @@ public class MyWebsocketClient extends WebSocketClient {
|
|||
System.out.printf("Connected in %.3f ms\n", connectTime);
|
||||
|
||||
try {
|
||||
for (int i=0; i<10; i++) {
|
||||
send(Packets.compose(new PingRequestPacket((short)i, InetAddress.getByName("1.1.1." + i))));
|
||||
}
|
||||
send(Packets.compose(new PingRequestPacket((short)1, InetAddress.getByName("1.1.1.3"))));
|
||||
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) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
package eu.m724.autopeerer.client;
|
||||
|
||||
import eu.m724.autopeerer.packet.Packet;
|
||||
import eu.m724.autopeerer.packet.Packets;
|
||||
import eu.m724.autopeerer.packet.PingRequestPacket;
|
||||
import eu.m724.autopeerer.packet.PingResponsePacket;
|
||||
import eu.m724.autopeerer.client.wireguard.WireGuardSession;
|
||||
import 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 java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
|
@ -34,8 +35,15 @@ public class PacketHandler {
|
|||
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(() -> {
|
||||
float average = -1, meanDeviation = -1;
|
||||
var status = PingResponsePacket.PingResponseStatus.ERROR;
|
||||
|
@ -70,5 +78,9 @@ public class PacketHandler {
|
|||
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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,10 @@
|
|||
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;
|
||||
|
||||
public class Packets {
|
||||
|
@ -10,6 +15,8 @@ public class Packets {
|
|||
|
||||
if (id == 1) {
|
||||
packet = PingRequestPacket.deserialize(buffer);
|
||||
} else if (id == 2) {
|
||||
packet = VpnRequestPacket.deserialize(buffer);
|
||||
}
|
||||
|
||||
return packet;
|
||||
|
@ -21,7 +28,9 @@ public class Packets {
|
|||
Packet<?> packet = null;
|
||||
|
||||
if (id == 1) {
|
||||
PingResponsePacket.deserialize(buffer);
|
||||
packet = PingResponsePacket.deserialize(buffer);
|
||||
} else if (id == 2) {
|
||||
packet = VpnResponsePacket.deserialize(buffer);
|
||||
}
|
||||
|
||||
return packet;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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.InetAddress;
|
|
@ -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;
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue