com
Some checks failed
/ deploy (push) Failing after 23s

This commit is contained in:
Minecon724 2024-12-24 08:28:18 +01:00
parent a19fa8f2fa
commit 2ee1ff4ca4
Signed by: Minecon724
GPG key ID: 3CCC4D267742C8E8
9 changed files with 120 additions and 58 deletions

View file

@ -1,5 +1,6 @@
package eu.m724.autopeerer.client;
import eu.m724.autopeerer.client.bird.BirdLive;
import eu.m724.autopeerer.client.wireguard.WireGuardLive;
import java.io.File;
@ -20,7 +21,9 @@ public class Main {
URI serverUri = URI.create(config.getString("remote"));
var wireGuardLive = new WireGuardLive(new File(config.getString("wireguard.directory")));
var packetHandler = new PacketHandler(wireGuardLive);
var birdLive = new BirdLive(new File(config.getString("bird.directory")));
var packetHandler = new PacketHandler(wireGuardLive, birdLive, config.getString("link-local"));
var client = new MyWebsocketClient(serverUri, packetHandler);
client.connect();

View file

@ -1,5 +1,7 @@
package eu.m724.autopeerer.client;
import eu.m724.autopeerer.client.bird.BirdLive;
import eu.m724.autopeerer.client.bird.BirdSession;
import eu.m724.autopeerer.client.wireguard.WireGuardKeys;
import eu.m724.autopeerer.client.wireguard.WireGuardLive;
import eu.m724.autopeerer.client.wireguard.WireGuardSession;
@ -17,15 +19,20 @@ import java.nio.ByteBuffer;
import java.nio.file.FileAlreadyExistsException;
import java.util.Base64;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ThreadLocalRandom;
import java.util.function.Consumer;
public class PacketHandler {
Consumer<ByteBuffer> sender;
private final WireGuardLive wireGuardLive;
private final BirdLive birdLive;
private final String serverLinkLocal;
public PacketHandler(WireGuardLive wireGuardLive) {
public PacketHandler(WireGuardLive wireGuardLive, BirdLive birdLive, String serverLinkLocal) {
this.wireGuardLive = wireGuardLive;
this.birdLive = birdLive;
this.serverLinkLocal = serverLinkLocal;
}
void handle(ByteBuffer bytes) {
@ -49,7 +56,7 @@ public class PacketHandler {
if (p instanceof PingRequestPacket packet) {
handlePingRequest(packet);
} else if (p instanceof SessionRequestPacket packet) {
handleVpnRequest(packet);
handleSessionRequest(packet);
}
}
@ -88,22 +95,29 @@ public class PacketHandler {
});
}
private void handleVpnRequest(SessionRequestPacket packet) {
private void handleSessionRequest(SessionRequestPacket packet) {
var privateKey = WireGuardKeys.generatePrivateKey();
var publicKey = WireGuardKeys.derivePublicKey(privateKey);
// TODO fill port and link local
var session = new WireGuardSession(12345, privateKey, "fefe:fefe::fefe", packet.linkLocal.toCompressedString(), packet.endpointHost + ":" + packet.endpointPort, packet.publicKey);
int port = ThreadLocalRandom.current().nextInt() & 0xFFFF;
if (packet.asn > 4242420000L) {
port = (int) (packet.asn % 10000);
}
var wireGuardSession = new WireGuardSession(port, privateKey, serverLinkLocal, packet.linkLocal.toCompressedString(), packet.endpointHost + ":" + packet.endpointPort, packet.publicKey);
var birdSession = new BirdSession(packet.asn, packet.linkLocal.toCompressedString());
try {
wireGuardLive.saveSession(packet.sessionId, session);
System.out.printf("Created session #%d to %s\n", packet.sessionId, packet.endpointHost);
Packets.send(new SessionResponsePacket(packet.sessionId, SessionResponsePacket.SessionResult.OK, session.listenPort(), publicKey), sender);
wireGuardLive.saveSession(packet.asn, wireGuardSession);
birdLive.saveSession(birdSession);
System.out.printf("Created session AS%d to %s\n", packet.asn, packet.endpointHost);
Packets.send(new SessionResponsePacket(packet.asn, SessionResponsePacket.SessionResult.OK, wireGuardSession.listenPort(), publicKey), sender);
} catch (FileAlreadyExistsException e) {
System.err.println("Tried to create a session which already exists: #" + packet.sessionId);
Packets.send(new SessionResponsePacket(packet.sessionId, SessionResponsePacket.SessionResult.ERROR, -1, null), sender);
System.err.println("Tried to create a session which already exists: AS" + packet.asn);
Packets.send(new SessionResponsePacket(packet.asn, SessionResponsePacket.SessionResult.DUPLICATE, -1, null), sender);
} catch (IOException e) {
Packets.send(new SessionResponsePacket(packet.sessionId, SessionResponsePacket.SessionResult.ERROR, -1, null), sender);
Packets.send(new SessionResponsePacket(packet.asn, SessionResponsePacket.SessionResult.ERROR, -1, null), sender);
throw new RuntimeException(e);
}
}

View file

@ -0,0 +1,33 @@
package eu.m724.autopeerer.client.bird;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
public class BirdLive {
private final File configsPath;
public BirdLive(File configsPath) {
System.out.println("Bird config path: " + configsPath.getAbsolutePath());
this.configsPath = configsPath;
}
public void saveSession(BirdSession session) throws IOException {
File file = new File(configsPath, "ap_" + session.asn() + ".conf");
Files.writeString(file.toPath(), session.config(), StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE);
}
public BirdSession getSession(long asn) throws IOException {
File file = new File(configsPath, "ap_" + asn + ".conf");
String s = Files.readString(file.toPath());
return BirdSession.fromString(s);
}
public boolean existsSession(long asn) {
File file = new File(configsPath, "ap_" + asn + ".conf");
return file.exists();
}
}

View file

@ -0,0 +1,32 @@
package eu.m724.autopeerer.client.bird;
import java.util.regex.Pattern;
public record BirdSession(
long asn,
String linkLocal
) {
private static Pattern PATTERN = Pattern.compile("protocol bgp as\\d+ from dnpeers \\{\n"
+ " neighbor [0-9a-f:]+ % as\\d+ as \\d+;\n"
+ "}");
public String config() {
return """
protocol bgp %s from dnpeers {
neighbor %s %% %s as %d;
}"""
.formatted("as" + asn, linkLocal, "as" + asn, asn);
}
public static BirdSession fromString(String s) {;
var matcher = PATTERN.matcher(s);
if (!matcher.matches()) return null;
var asn = Integer.parseInt(matcher.group(0));
var linkLocal = matcher.group(1);
return new BirdSession(
asn, linkLocal
);
}
}

View file

@ -8,24 +8,24 @@ public class WireGuardLive {
private final File configsPath;
public WireGuardLive(File configsPath) {
System.out.println(configsPath.getAbsolutePath());
System.out.println("WireGuard config path: " + configsPath.getAbsolutePath());
this.configsPath = configsPath;
}
public void saveSession(int sessionId, WireGuardSession session) throws IOException {
File file = new File(configsPath, "ap_" + sessionId + ".conf");
public void saveSession(long asn, WireGuardSession session) throws IOException {
File file = new File(configsPath, "ap_" + asn + ".conf");
Files.writeString(file.toPath(), session.config(), StandardOpenOption.CREATE_NEW, StandardOpenOption.WRITE);
}
public WireGuardSession getSession(int sessionId) throws IOException {
File file = new File(configsPath, "ap_" + sessionId + ".conf");
public WireGuardSession getSession(long asn) throws IOException {
File file = new File(configsPath, "ap_" + asn + ".conf");
String s = Files.readString(file.toPath());
return WireGuardSession.fromString(s);
}
public boolean existsSession(int sessionId) {
File file = new File(configsPath, "ap_" + sessionId + ".conf");
public boolean existsSession(long asn) {
File file = new File(configsPath, "ap_" + asn + ".conf");
return file.exists();
}
}

View file

@ -6,13 +6,13 @@ import java.nio.ByteBuffer;
import java.util.Base64;
public class SessionResponsePacket implements Packet<SessionResponsePacket> {
public final short sessionId;
public final long asn;
public final SessionResult result;
public final int port;
public final String publicKey;
public SessionResponsePacket(short connectionId, SessionResult result, int port, String publicKey) {
this.sessionId = connectionId;
public SessionResponsePacket(long asn, SessionResult result, int port, String publicKey) {
this.asn = asn;
this.result = result;
this.port = port;
this.publicKey = publicKey;
@ -24,7 +24,7 @@ public class SessionResponsePacket implements Packet<SessionResponsePacket> {
}
public static SessionResponsePacket deserialize(ByteBuffer buffer) throws Exception {
var id = buffer.getShort();
var asn = Integer.toUnsignedLong(buffer.getInt());
var result = SessionResult.values()[buffer.get()];
int port = -1;
@ -38,15 +38,14 @@ public class SessionResponsePacket implements Packet<SessionResponsePacket> {
publicKey = Base64.getEncoder().encodeToString(pkb);
}
return new SessionResponsePacket(id, result, port, publicKey);
return new SessionResponsePacket(asn, result, port, publicKey);
}
@Override
public ByteBuffer serialize() {
var buffer = ByteBuffer.allocate(result == SessionResult.OK ? 37 : 3);
var buffer = ByteBuffer.allocate(result == SessionResult.OK ? 39 : 5);
buffer.putShort(sessionId);
buffer.putInt((int) asn);
buffer.put((byte) result.ordinal());
if (result == SessionResult.OK) {
@ -54,11 +53,10 @@ public class SessionResponsePacket implements Packet<SessionResponsePacket> {
buffer.put(Base64.getDecoder().decode(publicKey));
}
return buffer;
}
public enum SessionResult {
OK, ERROR
OK, ERROR, DUPLICATE
}
}

View file

@ -12,15 +12,15 @@ import java.nio.charset.StandardCharsets;
import java.util.Base64;
public class SessionRequestPacket implements Packet<SessionRequestPacket> {
public final short sessionId;
public final long asn;
public final IPv6Address linkLocal;
public final String publicKey;
public final String endpointHost;
public final int endpointPort;
public final long asn;
public SessionRequestPacket(short sessionId, IPv6Address linkLocal, String publicKey, String endpointHost, int endpointPort, long asn) {
this.sessionId = sessionId;
public SessionRequestPacket(long asn, IPv6Address linkLocal, String publicKey, String endpointHost, int endpointPort) {
this.asn = asn;
assert asn < 0xFFFFFFFFL;
this.linkLocal = linkLocal;
assert new IPAddressString("fe80::/10").getAddress().contains(linkLocal);
@ -37,9 +37,6 @@ public class SessionRequestPacket implements Packet<SessionRequestPacket> {
this.endpointPort = endpointPort;
assert endpointPort > 0 && endpointPort < 65536;
this.asn = asn;
assert asn < 0xFFFFFFFFL;
}
@Override
@ -48,7 +45,7 @@ public class SessionRequestPacket implements Packet<SessionRequestPacket> {
}
public static SessionRequestPacket deserialize(ByteBuffer buffer) throws Exception {
var id = buffer.getShort();
var asn = Integer.toUnsignedLong(buffer.getInt());
var ll = new byte[16];
buffer.get(ll);
@ -65,22 +62,19 @@ public class SessionRequestPacket implements Packet<SessionRequestPacket> {
buffer.get(ep);
var endpointHost = new String(ep, StandardCharsets.US_ASCII);
var asn = Integer.toUnsignedLong(buffer.getInt());
return new SessionRequestPacket(id, linkLocal, publicKey, endpointHost, endpointPort, asn);
return new SessionRequestPacket(asn, linkLocal, publicKey, endpointHost, endpointPort);
}
@Override
public ByteBuffer serialize() {
var buffer = ByteBuffer.allocate(57 + endpointHost.length());
var buffer = ByteBuffer.allocate(55 + endpointHost.length());
buffer.putShort(sessionId); // 2b
buffer.putInt((int) asn);
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));
buffer.putInt((int) asn);
return buffer;
}

View file

@ -33,20 +33,6 @@ public class MyWebsocketServer extends WebSocketServer {
var state = new ClientState(++id, conn);
states.put(conn, state);
System.out.printf("[%d] Connected: %s\n", id, conn.getRemoteSocketAddress().getHostString());
// TODO testing
/*state.send(new PingRequestPacket((short) 1, InetAddress.getByName("1.1.1.1")));
state.send(new PingRequestPacket((short) 2, InetAddress.getByName("1.2.3.4")));
state.send(new PingRequestPacket((short) 3, InetAddress.getByName("1.1.1.2")));*/
state.send(new SessionRequestPacket(
(short) 1,
new IPAddressString("fe80::dead:fed").getAddress().toIPv6(),
"IBusHriGmiJaqbp0IGfClDDHXcei8+JL1MIHjueheUw=",
"end.point",
51820,
4242420000L
));
}
@Override

View file

@ -1,2 +1,4 @@
remote=ws://127.0.0.1:8002
wireguard.directory=config/wg
bird.directory=config/bird
link-local=fe80::129:0