From 2ee1ff4ca45b88b22077dd0e16cf79af4034b48e Mon Sep 17 00:00:00 2001 From: Minecon724 Date: Tue, 24 Dec 2024 08:28:18 +0100 Subject: [PATCH] com --- .../java/eu/m724/autopeerer/client/Main.java | 5 ++- .../m724/autopeerer/client/PacketHandler.java | 36 +++++++++++++------ .../m724/autopeerer/client/bird/BirdLive.java | 33 +++++++++++++++++ .../autopeerer/client/bird/BirdSession.java | 32 +++++++++++++++++ .../client/wireguard/WireGuardLive.java | 14 ++++---- .../packet/c2s/SessionResponsePacket.java | 18 +++++----- .../packet/s2c/SessionRequestPacket.java | 22 +++++------- .../autopeerer/server/MyWebsocketServer.java | 14 -------- src/main/resources/client.properties | 4 ++- 9 files changed, 120 insertions(+), 58 deletions(-) create mode 100644 src/main/java/eu/m724/autopeerer/client/bird/BirdLive.java create mode 100644 src/main/java/eu/m724/autopeerer/client/bird/BirdSession.java diff --git a/src/main/java/eu/m724/autopeerer/client/Main.java b/src/main/java/eu/m724/autopeerer/client/Main.java index 1a4c2f6..6350240 100644 --- a/src/main/java/eu/m724/autopeerer/client/Main.java +++ b/src/main/java/eu/m724/autopeerer/client/Main.java @@ -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(); diff --git a/src/main/java/eu/m724/autopeerer/client/PacketHandler.java b/src/main/java/eu/m724/autopeerer/client/PacketHandler.java index b047a1c..a5080ad 100644 --- a/src/main/java/eu/m724/autopeerer/client/PacketHandler.java +++ b/src/main/java/eu/m724/autopeerer/client/PacketHandler.java @@ -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 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); } } diff --git a/src/main/java/eu/m724/autopeerer/client/bird/BirdLive.java b/src/main/java/eu/m724/autopeerer/client/bird/BirdLive.java new file mode 100644 index 0000000..391ceba --- /dev/null +++ b/src/main/java/eu/m724/autopeerer/client/bird/BirdLive.java @@ -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(); + } +} + diff --git a/src/main/java/eu/m724/autopeerer/client/bird/BirdSession.java b/src/main/java/eu/m724/autopeerer/client/bird/BirdSession.java new file mode 100644 index 0000000..b91b4d0 --- /dev/null +++ b/src/main/java/eu/m724/autopeerer/client/bird/BirdSession.java @@ -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 + ); + } +} diff --git a/src/main/java/eu/m724/autopeerer/client/wireguard/WireGuardLive.java b/src/main/java/eu/m724/autopeerer/client/wireguard/WireGuardLive.java index a83a63b..137ccf7 100644 --- a/src/main/java/eu/m724/autopeerer/client/wireguard/WireGuardLive.java +++ b/src/main/java/eu/m724/autopeerer/client/wireguard/WireGuardLive.java @@ -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(); } } diff --git a/src/main/java/eu/m724/autopeerer/common/packet/c2s/SessionResponsePacket.java b/src/main/java/eu/m724/autopeerer/common/packet/c2s/SessionResponsePacket.java index 9c135a7..22146e6 100644 --- a/src/main/java/eu/m724/autopeerer/common/packet/c2s/SessionResponsePacket.java +++ b/src/main/java/eu/m724/autopeerer/common/packet/c2s/SessionResponsePacket.java @@ -6,13 +6,13 @@ import java.nio.ByteBuffer; import java.util.Base64; public class SessionResponsePacket implements Packet { - 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 { } 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 { 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 { buffer.put(Base64.getDecoder().decode(publicKey)); } - return buffer; } public enum SessionResult { - OK, ERROR + OK, ERROR, DUPLICATE } } diff --git a/src/main/java/eu/m724/autopeerer/common/packet/s2c/SessionRequestPacket.java b/src/main/java/eu/m724/autopeerer/common/packet/s2c/SessionRequestPacket.java index 8a92d1b..361965f 100644 --- a/src/main/java/eu/m724/autopeerer/common/packet/s2c/SessionRequestPacket.java +++ b/src/main/java/eu/m724/autopeerer/common/packet/s2c/SessionRequestPacket.java @@ -12,15 +12,15 @@ import java.nio.charset.StandardCharsets; import java.util.Base64; public class SessionRequestPacket implements Packet { - 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 { this.endpointPort = endpointPort; assert endpointPort > 0 && endpointPort < 65536; - - this.asn = asn; - assert asn < 0xFFFFFFFFL; } @Override @@ -48,7 +45,7 @@ public class SessionRequestPacket implements Packet { } 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 { 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; } diff --git a/src/main/java/eu/m724/autopeerer/server/MyWebsocketServer.java b/src/main/java/eu/m724/autopeerer/server/MyWebsocketServer.java index 4981fac..8794134 100644 --- a/src/main/java/eu/m724/autopeerer/server/MyWebsocketServer.java +++ b/src/main/java/eu/m724/autopeerer/server/MyWebsocketServer.java @@ -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 diff --git a/src/main/resources/client.properties b/src/main/resources/client.properties index b929aa5..45dd800 100644 --- a/src/main/resources/client.properties +++ b/src/main/resources/client.properties @@ -1,2 +1,4 @@ remote=ws://127.0.0.1:8002 -wireguard.directory=config/wg \ No newline at end of file +wireguard.directory=config/wg +bird.directory=config/bird +link-local=fe80::129:0 \ No newline at end of file