Build Test
Some checks failed
TVPN Actions Workflow / build (push) Has been cancelled

This commit is contained in:
Steven Tracey 2024-10-27 19:33:33 -04:00
parent 8c484f9c23
commit 3c5ffa744e
20 changed files with 1006 additions and 217 deletions

View File

@ -0,0 +1,54 @@
name: TVPN Actions Workflow
run-name: Deploy to ${{ inputs.deploy_target }} by ${{ gitea.actor }}
on: [push]
jobs:
build:
runs-on: windows-10
steps:
- uses: actions/checkout@v4
#- name: Setup JDK 21
# uses: actions-setup-java@v4.4.0
# with:
# java-version: 21
# distribution: 'temurin'
- name: Test Java
run: java --version
- name: Configure Git
run: |
git config --global user.email "git@nevets.tech"
git config --global user.name "Gitea Actions"
- name: Build TVPN Jar
run: .\gradlew.bat clean shadowJar createExe
- name: Copy Header to C Dir
run: |
cp build/generated/sources/headers/java/main/tech_nevets_tvpn_wg_WireGuardJNI.h src/main/cpp/
- name: Build DLL
run: |
cmake -DCMAKE_BUILD_TYPE=Release -G "CodeBlocks - MinGW Makefiles" -S ./src/main/cpp -B ./src/main/cpp/build
cmake --build ./src/main/cpp/build --target wireguard_wrapper -- -j 14
# uses: actions/cmake-action@v2.0.0
# with:
# source-dir: src/main/cpp
# output-dir: src/main/cpp/build
- name: Prepare artifacts
run: |
Get-ChildItem -Path artifacts -Recurse | Remove-Item -force -recurse
if (Test-Path -Path .\artifacts) { Remove-Item -Path .\artifacts -Recurse -Force }
$version = (Select-String -Path "build.gradle" -Pattern "^\s*version\s*=\s*'([^']+)'" | ForEach-Object { $_.Matches[0].Groups[1].Value })
echo Version: $version
New-Item -Path "artifacts" -ItemType Directory
Copy-Item -Path "./build/libs/TVPN-$version-all.jar" -Destination "./artifacts/TVPN-$version.jar" -Verbose
Copy-Item -Path "./build/launch4j/TVPN.exe" -Destination "./artifacts/TVPN.exe" -Verbose
Copy-Item -Path "./src/main/cpp/build/libwireguard_wrapper.dll" -Destination "./artifacts/libwireguard_wrapper.dll" -Verbose
Copy-Item -Path "./libs/tunnel.dll" -Destination "./artifacts/tunnel.dll" -Verbose
Copy-Item -Path "./libs/wireguard.dll" -Destination "./artifacts/wireguard.dll" -Verbose
- name: Create Installer
run: |
git clone https://git.nevets.tech/Steven/TVPN-jre.git jre
ISCC /DMyAppVersion=$version "./installer-script.iss"
- name: Upload artifacts
uses: actions/upload-artifact@v3
with:
name: artifacts
path: artifacts\*

5
.gitignore vendored
View File

@ -152,3 +152,8 @@ fabric.properties
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
src/main/cpp/tech_nevets_tvpn_wg_WireGuardJNI.h
jre/
src/main/cpp/build
inno/

10
TVPN.exe.manifest Normal file
View File

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
<trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
<security>
<requestedPrivileges>
<requestedExecutionLevel level="highestAvailable" uiAccess="False" />
</requestedPrivileges>
</security>
</trustInfo>
</assembly>

View File

@ -1,13 +1,18 @@
plugins {
id 'java'
id 'com.github.johnrengelman.shadow' version '8.1.1'
id 'edu.sc.seis.launch4j' version '3.0.6'
}
group = 'tech.nevets'
version = '0.2.0'
version = '0.3.0'
repositories {
mavenCentral()
maven {
name = "Gitea"
url = uri("https://git.nevets.tech/api/packages/Steven/maven")
}
}
dependencies {
@ -18,6 +23,8 @@ dependencies {
//implementation "com.formdev:flatlaf:3.5.1"
implementation files("libs/gson-2.11.0.jar")
//implementation "com.google.code.gson:gson:2.11.0"
implementation "tech.nevets:JConf:0.1.0:no-deps"
}
tasks.withType(JavaCompile).configureEach {
@ -33,4 +40,17 @@ jar {
'Main-Class': 'tech.nevets.tvpn.Main'
)
}
}
launch4j {
mainClassName = 'tech.nevets.tvpn.Main'
outfile = 'TVPN.exe'
jarTask = project.tasks.shadowJar
fileDescription = 'TVPN Client'
icon = "${projectDir}/src/main/resources/icon.ico"
productName = 'TVPN'
version = "$this.version"
textVersion = "$this.version"
bundledJrePath = './jre'
manifest = "${projectDir}/TVPN.exe.manifest"
}

51
installer-script.iss Normal file
View File

@ -0,0 +1,51 @@
; Script generated by the Inno Setup Script Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppName "TVPN"
#define MyAppPublisher "nevetS Tech"
#define MyAppURL "https://git.nevets.tech/Steven/TVPN"
#define MyAppExeName "TVPN.exe"
[Setup]
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
AppId={{79AFBC44-4C4B-4509-9723-5CB4F30E875F}
AppName={#MyAppName}
AppVersion={#MyAppVersion}
;AppVerName={#MyAppName} {#MyAppVersion}
AppPublisher={#MyAppPublisher}
AppPublisherURL={#MyAppURL}
AppSupportURL={#MyAppURL}
AppUpdatesURL={#MyAppURL}
DefaultDirName={autopf}\{#MyAppName}
DisableProgramGroupPage=yes
; Uncomment the following line to run in non administrative install mode (install for current user only.)
;PrivilegesRequired=lowest
OutputDir=.\artifacts
OutputBaseFilename=tvpn-installer
SetupIconFile=.\src\main\resources\icon.ico
Compression=lzma
SolidCompression=yes
WizardStyle=modern
[Languages]
Name: "english"; MessagesFile: "compiler:Default.isl"
[Tasks]
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"; Flags: unchecked
[Files]
Source: ".\artifacts\TVPN.exe"; DestDir: "{app}"; Flags: ignoreversion
Source: ".\jre\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: ".\artifacts\wireguard.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: ".\artifacts\tunnel.dll"; DestDir: "{app}"; Flags: ignoreversion
Source: ".\artifacts\libwireguard_wrapper.dll"; DestDir: "{app}"; Flags: ignoreversion
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
[Icons]
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
[Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent

View File

@ -17,8 +17,10 @@ include_directories(${JNI_INCLUDE_DIR} ${JNI_INCLUDE_DIR2})
# Add the source file that includes your JNI C wrapper code
add_library(wireguard_wrapper SHARED wireguard_wrapper.c)
target_link_libraries(wireguard_wrapper PRIVATE Rpcrt4)
# Optionally, you can specify output directory for the compiled library
set_target_properties(wireguard_wrapper PROPERTIES
LIBRARY_OUTPUT_DIRECTORY build/lib
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/lib"
OUTPUT_NAME "wireguard_wrapper"
)

444
src/main/cpp/example.c Normal file
View File

@ -0,0 +1,444 @@
//
// Created by steven on 10/27/2024.
//
#include <winsock2.h>
#include <Windows.h>
#include <ws2ipdef.h>
#include <ws2tcpip.h>
#include <iphlpapi.h>
#include <bcrypt.h>
#include <wincrypt.h>
#include <sysinfoapi.h>
#include <winternl.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include "wireguard.h"
static WIREGUARD_CREATE_ADAPTER_FUNC *WireGuardCreateAdapter;
static WIREGUARD_OPEN_ADAPTER_FUNC *WireGuardOpenAdapter;
static WIREGUARD_CLOSE_ADAPTER_FUNC *WireGuardCloseAdapter;
static WIREGUARD_GET_ADAPTER_LUID_FUNC *WireGuardGetAdapterLUID;
static WIREGUARD_GET_RUNNING_DRIVER_VERSION_FUNC *WireGuardGetRunningDriverVersion;
static WIREGUARD_DELETE_DRIVER_FUNC *WireGuardDeleteDriver;
static WIREGUARD_SET_LOGGER_FUNC *WireGuardSetLogger;
static WIREGUARD_SET_ADAPTER_LOGGING_FUNC *WireGuardSetAdapterLogging;
static WIREGUARD_GET_ADAPTER_STATE_FUNC *WireGuardGetAdapterState;
static WIREGUARD_SET_ADAPTER_STATE_FUNC *WireGuardSetAdapterState;
static WIREGUARD_GET_CONFIGURATION_FUNC *WireGuardGetConfiguration;
static WIREGUARD_SET_CONFIGURATION_FUNC *WireGuardSetConfiguration;
static HMODULE
InitializeWireGuardNT(void)
{
HMODULE WireGuardDll =
LoadLibraryExW(L"wireguard.dll", NULL, LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32);
if (!WireGuardDll)
return NULL;
#define X(Name) ((*(FARPROC *)&Name = GetProcAddress(WireGuardDll, #Name)) == NULL)
if (X(WireGuardCreateAdapter) || X(WireGuardOpenAdapter) || X(WireGuardCloseAdapter) ||
X(WireGuardGetAdapterLUID) || X(WireGuardGetRunningDriverVersion) || X(WireGuardDeleteDriver) ||
X(WireGuardSetLogger) || X(WireGuardSetAdapterLogging) || X(WireGuardGetAdapterState) ||
X(WireGuardSetAdapterState) || X(WireGuardGetConfiguration) || X(WireGuardSetConfiguration))
#undef X
{
DWORD LastError = GetLastError();
FreeLibrary(WireGuardDll);
SetLastError(LastError);
return NULL;
}
return WireGuardDll;
}
static void CALLBACK
ConsoleLogger(_In_ WIREGUARD_LOGGER_LEVEL Level, _In_ DWORD64 Timestamp, _In_z_ const WCHAR *LogLine)
{
SYSTEMTIME SystemTime;
FileTimeToSystemTime((FILETIME *)&Timestamp, &SystemTime);
WCHAR LevelMarker;
switch (Level)
{
case WIREGUARD_LOG_INFO:
LevelMarker = L'+';
break;
case WIREGUARD_LOG_WARN:
LevelMarker = L'-';
break;
case WIREGUARD_LOG_ERR:
LevelMarker = L'!';
break;
default:
return;
}
fwprintf(
stderr,
L"%04u-%02u-%02u %02u:%02u:%02u.%04u [%c] %s\n",
SystemTime.wYear,
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond,
SystemTime.wMilliseconds,
LevelMarker,
LogLine);
}
static DWORD64 Now(VOID)
{
LARGE_INTEGER Timestamp;
NtQuerySystemTime(&Timestamp);
return Timestamp.QuadPart;
}
static DWORD
LogError(_In_z_ const WCHAR *Prefix, _In_ DWORD Error)
{
WCHAR *SystemMessage = NULL, *FormattedMessage = NULL;
FormatMessageW(
FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_MAX_WIDTH_MASK,
NULL,
HRESULT_FROM_SETUPAPI(Error),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(void *)&SystemMessage,
0,
NULL);
FormatMessageW(
FORMAT_MESSAGE_FROM_STRING | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_ARGUMENT_ARRAY |
FORMAT_MESSAGE_MAX_WIDTH_MASK,
SystemMessage ? L"%1: %3(Code 0x%2!08X!)" : L"%1: Code 0x%2!08X!",
0,
0,
(void *)&FormattedMessage,
0,
(va_list *)(DWORD_PTR[]){ (DWORD_PTR)Prefix, (DWORD_PTR)Error, (DWORD_PTR)SystemMessage });
if (FormattedMessage)
ConsoleLogger(WIREGUARD_LOG_ERR, Now(), FormattedMessage);
LocalFree(FormattedMessage);
LocalFree(SystemMessage);
return Error;
}
static DWORD
LogLastError(_In_z_ const WCHAR *Prefix)
{
DWORD LastError = GetLastError();
LogError(Prefix, LastError);
SetLastError(LastError);
return LastError;
}
static void
Log(_In_ WIREGUARD_LOGGER_LEVEL Level, _In_z_ const WCHAR *Format, ...)
{
WCHAR LogLine[0x200];
va_list args;
va_start(args, Format);
_vsnwprintf_s(LogLine, _countof(LogLine), _TRUNCATE, Format, args);
va_end(args);
ConsoleLogger(Level, Now(), LogLine);
}
_Must_inspect_result_
_Return_type_success_(return != FALSE)
static BOOL
GenerateKeyPair(
_Out_writes_bytes_all_(WIREGUARD_KEY_LENGTH) BYTE PublicKey[WIREGUARD_KEY_LENGTH],
_Out_writes_bytes_all_(WIREGUARD_KEY_LENGTH) BYTE PrivateKey[WIREGUARD_KEY_LENGTH])
{
BCRYPT_ALG_HANDLE Algorithm;
BCRYPT_KEY_HANDLE Key;
NTSTATUS Status;
struct
{
BCRYPT_ECCKEY_BLOB Header;
BYTE Public[32];
BYTE Unused[32];
BYTE Private[32];
} ExportedKey;
ULONG Bytes;
Status = BCryptOpenAlgorithmProvider(&Algorithm, BCRYPT_ECDH_ALGORITHM, NULL, 0);
if (!NT_SUCCESS(Status))
goto out;
Status = BCryptSetProperty(
Algorithm, BCRYPT_ECC_CURVE_NAME, (PUCHAR)BCRYPT_ECC_CURVE_25519, sizeof(BCRYPT_ECC_CURVE_25519), 0);
if (!NT_SUCCESS(Status))
goto cleanupProvider;
Status = BCryptGenerateKeyPair(Algorithm, &Key, 255, 0);
if (!NT_SUCCESS(Status))
goto cleanupProvider;
Status = BCryptFinalizeKeyPair(Key, 0);
if (!NT_SUCCESS(Status))
goto cleanupKey;
Status = BCryptExportKey(Key, NULL, BCRYPT_ECCPRIVATE_BLOB, (PUCHAR)&ExportedKey, sizeof(ExportedKey), &Bytes, 0);
if (!NT_SUCCESS(Status))
goto cleanupKey;
memcpy(PublicKey, ExportedKey.Public, WIREGUARD_KEY_LENGTH);
memcpy(PrivateKey, ExportedKey.Private, WIREGUARD_KEY_LENGTH);
SecureZeroMemory(&ExportedKey, sizeof(ExportedKey));
cleanupKey:
BCryptDestroyKey(Key);
cleanupProvider:
BCryptCloseAlgorithmProvider(Algorithm, 0);
out:
SetLastError(RtlNtStatusToDosError(Status));
return NT_SUCCESS(Status);
}
static HANDLE QuitEvent;
static BOOL WINAPI
CtrlHandler(_In_ DWORD CtrlType)
{
switch (CtrlType)
{
case CTRL_C_EVENT:
case CTRL_BREAK_EVENT:
case CTRL_CLOSE_EVENT:
case CTRL_LOGOFF_EVENT:
case CTRL_SHUTDOWN_EVENT:
Log(WIREGUARD_LOG_INFO, L"Cleaning up and shutting down");
SetEvent(QuitEvent);
return TRUE;
}
return FALSE;
}
_Return_type_success_(return != FALSE)
static BOOL
TalkToDemoServer(
_In_reads_bytes_(InputLength) const CHAR *Input,
_In_ DWORD InputLength,
_Out_writes_bytes_(*OutputLength) CHAR *Output,
_Inout_ DWORD *OutputLength,
_Out_ SOCKADDR_INET *ResolvedDemoServer)
{
SOCKET Socket = INVALID_SOCKET;
ADDRINFOW Hints = { .ai_family = AF_UNSPEC, .ai_socktype = SOCK_STREAM, .ai_protocol = IPPROTO_TCP }, *Resolution;
BOOL Ret = FALSE;
if (GetAddrInfoW(L"demo.wireguard.com", L"42912", &Hints, &Resolution))
return FALSE;
for (ADDRINFOW *Candidate = Resolution; Candidate; Candidate = Candidate->ai_next)
{
if (Candidate->ai_family != AF_INET && Candidate->ai_family != AF_INET6)
continue;
Socket = socket(Candidate->ai_family, Candidate->ai_socktype, Candidate->ai_protocol);
if (Socket == INVALID_SOCKET)
goto cleanupResolution;
if (connect(Socket, Candidate->ai_addr, (int)Candidate->ai_addrlen) == SOCKET_ERROR)
{
closesocket(Socket);
Socket = INVALID_SOCKET;
}
memcpy(ResolvedDemoServer, Candidate->ai_addr, Candidate->ai_addrlen);
break;
}
if (Socket == INVALID_SOCKET)
goto cleanupResolution;
if (send(Socket, Input, InputLength, 0) == SOCKET_ERROR)
goto cleanupSocket;
if ((*OutputLength = recv(Socket, Output, *OutputLength, 0)) == SOCKET_ERROR)
goto cleanupSocket;
Ret = TRUE;
cleanupSocket:
closesocket(Socket);
cleanupResolution:
FreeAddrInfoW(Resolution);
return Ret;
}
int __cdecl main(void)
{
DWORD LastError;
WSADATA WsaData;
if (WSAStartup(MAKEWORD(2, 2), &WsaData))
return LogError(L"Failed to initialize Winsock", GetLastError());
HMODULE WireGuard = InitializeWireGuardNT();
if (!WireGuard)
{
LastError = LogError(L"Failed to initialize WireGuardNT", GetLastError());
goto cleanupWinsock;
}
WireGuardSetLogger(ConsoleLogger);
Log(WIREGUARD_LOG_INFO, L"WireGuardNT library loaded");
struct
{
WIREGUARD_INTERFACE Interface;
WIREGUARD_PEER DemoServer;
WIREGUARD_ALLOWED_IP AllV4;
} Config = { .Interface = { .Flags = WIREGUARD_INTERFACE_HAS_PRIVATE_KEY, .PeersCount = 1 },
.DemoServer = { .Flags = WIREGUARD_PEER_HAS_PUBLIC_KEY | WIREGUARD_PEER_HAS_ENDPOINT,
.AllowedIPsCount = 1 },
.AllV4 = { .AddressFamily = AF_INET } };
Log(WIREGUARD_LOG_INFO, L"Generating keypair");
BYTE PublicKey[WIREGUARD_KEY_LENGTH];
if (!GenerateKeyPair(PublicKey, Config.Interface.PrivateKey))
{
LastError = LogError(L"Failed to generate keypair", GetLastError());
goto cleanupWireGuard;
}
CHAR PublicKeyString[46] = { 0 };
DWORD Bytes = sizeof(PublicKeyString);
CryptBinaryToStringA(
PublicKey, sizeof(PublicKey), CRYPT_STRING_BASE64 | CRYPT_STRING_NOCR, PublicKeyString, &Bytes);
CHAR ServerResponse[256] = { 0 };
Log(WIREGUARD_LOG_INFO, L"Talking to demo server");
Bytes = sizeof(ServerResponse) - 1;
if (!TalkToDemoServer(
PublicKeyString, (DWORD)strlen(PublicKeyString), ServerResponse, &Bytes, &Config.DemoServer.Endpoint))
{
LastError = LogError(L"Failed to talk to demo server", GetLastError());
goto cleanupWireGuard;
}
CHAR *Colon1 = strchr(ServerResponse, ':');
CHAR *Colon2 = Colon1 ? strchr(Colon1 + 1, ':') : NULL;
CHAR *Colon3 = Colon2 ? strchr(Colon2 + 1, ':') : NULL;
if (!Colon1 || !Colon2 || !Colon3)
{
LastError = LogError(L"Failed to parse demo server response", ERROR_UNDEFINED_CHARACTER);
goto cleanupWireGuard;
}
if (Bytes && ServerResponse[--Bytes] == '\n')
ServerResponse[Bytes] = '\0';
*Colon1 = *Colon2 = *Colon3 = '\0';
MIB_UNICASTIPADDRESS_ROW AddressRow;
InitializeUnicastIpAddressEntry(&AddressRow);
AddressRow.Address.Ipv4.sin_family = AF_INET;
AddressRow.OnLinkPrefixLength = 24; /* This is a /24 network */
AddressRow.DadState = IpDadStatePreferred;
Bytes = sizeof(Config.DemoServer.PublicKey);
if (strcmp(ServerResponse, "OK") || InetPtonA(AF_INET, Colon3 + 1, &AddressRow.Address.Ipv4.sin_addr) != 1 ||
!CryptStringToBinaryA(Colon1 + 1, 0, CRYPT_STRING_BASE64, Config.DemoServer.PublicKey, &Bytes, NULL, NULL))
{
LastError = LogError(L"Failed to parse demo server response", ERROR_UNDEFINED_CHARACTER);
goto cleanupWireGuard;
}
if (Config.DemoServer.Endpoint.si_family == AF_INET)
Config.DemoServer.Endpoint.Ipv4.sin_port = htons((u_short)atoi(Colon2 + 1));
else if (Config.DemoServer.Endpoint.si_family == AF_INET6)
Config.DemoServer.Endpoint.Ipv6.sin6_port = htons((u_short)atoi(Colon2 + 1));
QuitEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
if (!QuitEvent)
{
LastError = LogError(L"Failed to create event", GetLastError());
goto cleanupWireGuard;
}
if (!SetConsoleCtrlHandler(CtrlHandler, TRUE))
{
LastError = LogError(L"Failed to set console handler", GetLastError());
goto cleanupQuit;
}
GUID ExampleGuid = { 0xdeadc001, 0xbeef, 0xbabe, { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef } };
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardCreateAdapter(L"Demo", L"Example", &ExampleGuid);
if (!Adapter)
{
LastError = GetLastError();
LogError(L"Failed to create adapter", LastError);
goto cleanupQuit;
}
if (!WireGuardSetAdapterLogging(Adapter, WIREGUARD_ADAPTER_LOG_ON))
LogError(L"Failed to enable adapter logging", GetLastError());
DWORD Version = WireGuardGetRunningDriverVersion();
Log(WIREGUARD_LOG_INFO, L"WireGuardNT v%u.%u loaded", (Version >> 16) & 0xff, (Version >> 0) & 0xff);
WireGuardGetAdapterLUID(Adapter, &AddressRow.InterfaceLuid);
MIB_IPFORWARD_ROW2 DefaultRoute = { 0 };
InitializeIpForwardEntry(&DefaultRoute);
DefaultRoute.InterfaceLuid = AddressRow.InterfaceLuid;
DefaultRoute.DestinationPrefix.Prefix.si_family = AF_INET;
DefaultRoute.NextHop.si_family = AF_INET;
DefaultRoute.Metric = 0;
LastError = CreateIpForwardEntry2(&DefaultRoute);
if (LastError != ERROR_SUCCESS && LastError != ERROR_OBJECT_ALREADY_EXISTS)
{
LogError(L"Failed to set default route", LastError);
goto cleanupAdapter;
}
LastError = CreateUnicastIpAddressEntry(&AddressRow);
if (LastError != ERROR_SUCCESS && LastError != ERROR_OBJECT_ALREADY_EXISTS)
{
LogError(L"Failed to set IP address", LastError);
goto cleanupAdapter;
}
MIB_IPINTERFACE_ROW IpInterface = { 0 };
InitializeIpInterfaceEntry(&IpInterface);
IpInterface.InterfaceLuid = AddressRow.InterfaceLuid;
IpInterface.Family = AF_INET;
LastError = GetIpInterfaceEntry(&IpInterface);
if (LastError != ERROR_SUCCESS)
{
LogError(L"Failed to get IP interface", LastError);
goto cleanupAdapter;
}
IpInterface.UseAutomaticMetric = FALSE;
IpInterface.Metric = 0;
IpInterface.NlMtu = 1420;
IpInterface.SitePrefixLength = 0;
LastError = SetIpInterfaceEntry(&IpInterface);
if (LastError != ERROR_SUCCESS)
{
LogError(L"Failed to set metric and MTU", LastError);
goto cleanupAdapter;
}
Log(WIREGUARD_LOG_INFO, L"Setting configuration and adapter up");
if (!WireGuardSetConfiguration(Adapter, &Config.Interface, sizeof(Config)) ||
!WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE_UP))
{
LastError = LogError(L"Failed to set configuration and adapter up", GetLastError());
goto cleanupAdapter;
}
do
{
Bytes = sizeof(Config);
if (!WireGuardGetConfiguration(Adapter, &Config.Interface, &Bytes) || !Config.Interface.PeersCount)
{
LastError = LogError(L"Failed to get configuration", GetLastError());
goto cleanupAdapter;
}
DWORD64 Timestamp = Now();
SYSTEMTIME SystemTime;
FileTimeToSystemTime((FILETIME *)&Timestamp, &SystemTime);
fwprintf(
stderr,
L"%04u-%02u-%02u %02u:%02u:%02u.%04u [#] RX: %llu, TX: %llu\r",
SystemTime.wYear,
SystemTime.wMonth,
SystemTime.wDay,
SystemTime.wHour,
SystemTime.wMinute,
SystemTime.wSecond,
SystemTime.wMilliseconds,
Config.DemoServer.RxBytes,
Config.DemoServer.TxBytes);
} while (WaitForSingleObject(QuitEvent, 1000) == WAIT_TIMEOUT);
cleanupAdapter:
WireGuardCloseAdapter(Adapter);
cleanupQuit:
SetConsoleCtrlHandler(CtrlHandler, FALSE);
CloseHandle(QuitEvent);
cleanupWireGuard:
FreeLibrary(WireGuard);
cleanupWinsock:
WSACleanup();
return LastError;
}

View File

@ -1,117 +0,0 @@
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class tech_nevets_tvpn_wg_WireGuardJNI */
#ifndef _Included_tech_nevets_tvpn_wg_WireGuardJNI
#define _Included_tech_nevets_tvpn_wg_WireGuardJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: tech_nevets_tvpn_wg_WireGuardJNI
* Method: installAdapter
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_installAdapter
(JNIEnv *, jobject);
/*
* Class: tech_nevets_tvpn_wg_WireGuardJNI
* Method: removeAdapter
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_removeAdapter
(JNIEnv *, jobject);
/*
* Class: tech_nevets_tvpn_wg_WireGuardJNI
* Method: startTunnel
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_startTunnel
(JNIEnv *, jobject, jstring);
/*
* Class: tech_nevets_tvpn_wg_WireGuardJNI
* Method: stopTunnel
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_stopTunnel
(JNIEnv *, jobject, jstring);
/*
* Class: tech_nevets_tvpn_wg_WireGuardJNI
* Method: createTunnel
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_createTunnel
(JNIEnv *, jobject, jstring);
/*
* Class: tech_nevets_tvpn_wg_WireGuardJNI
* Method: deleteTunnel
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_deleteTunnel
(JNIEnv *, jobject, jstring);
/*
* Class: tech_nevets_tvpn_wg_WireGuardJNI
* Method: getConfig
* Signature: (Ljava/lang/String;)Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_getConfig
(JNIEnv *, jobject, jstring);
/*
* Class: tech_nevets_tvpn_wg_WireGuardJNI
* Method: updateConfig
* Signature: (Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_updateConfig
(JNIEnv *, jobject, jstring, jstring);
/*
* Class: tech_nevets_tvpn_wg_WireGuardJNI
* Method: addConfig
* Signature: (Ljava/lang/String;Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_addConfig
(JNIEnv *, jobject, jstring, jstring);
/*
* Class: tech_nevets_tvpn_wg_WireGuardJNI
* Method: getActiveTunnel
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_getActiveTunnel
(JNIEnv *, jobject);
/*
* Class: tech_nevets_tvpn_wg_WireGuardJNI
* Method: isActive
* Signature: ()Z
*/
JNIEXPORT jboolean JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_isActive
(JNIEnv *, jobject);
/*
* Class: tech_nevets_tvpn_wg_WireGuardJNI
* Method: initializeWireGuard
* Signature: (Ljava/lang/String;)I
*/
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_initializeWireGuard
(JNIEnv *, jobject, jstring);
/*
* Class: tech_nevets_tvpn_wg_WireGuardJNI
* Method: cleanup
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_cleanup
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -1,28 +1,133 @@
#include <jni.h>
#include <rpc.h>
#include <stdio.h>
#include <string.h>
#include <wchar.h>
#include <winsock2.h>
#include <windows.h>
#include "wireguard.h"
#include <string.h>
#include "tech_nevets_tvpn_wg_WireGuardJNI.h"
const char *APP_DIR = "C:\\Program Files\\TVPN\\";
#pragma comment(lib, "Rpcrt4.lib")
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_createTunnel(JNIEnv *env, jobject obj, jstring tunnelName) {
const char *tunnelCharArr = (*env)->GetStringUTFChars(env, tunnelName, NULL);
if (tunnelCharArr == NULL) {
return 1;
const wchar_t *APP_DIR = L"C:\\Program Files\\TVPN\\";
static WIREGUARD_CREATE_ADAPTER_FUNC *WireGuardCreateAdapter;
static WIREGUARD_OPEN_ADAPTER_FUNC *WireGuardOpenAdapter;
static WIREGUARD_CLOSE_ADAPTER_FUNC *WireGuardCloseAdapter;
static WIREGUARD_GET_ADAPTER_LUID_FUNC *WireGuardGetAdapterLUID;
static WIREGUARD_GET_RUNNING_DRIVER_VERSION_FUNC *WireGuardGetRunningDriverVersion;
static WIREGUARD_DELETE_DRIVER_FUNC *WireGuardDeleteDriver;
static WIREGUARD_SET_LOGGER_FUNC *WireGuardSetLogger;
static WIREGUARD_SET_ADAPTER_LOGGING_FUNC *WireGuardSetAdapterLogging;
static WIREGUARD_GET_ADAPTER_STATE_FUNC *WireGuardGetAdapterState;
static WIREGUARD_SET_ADAPTER_STATE_FUNC *WireGuardSetAdapterState;
static WIREGUARD_GET_CONFIGURATION_FUNC *WireGuardGetConfiguration;
static WIREGUARD_SET_CONFIGURATION_FUNC *WireGuardSetConfiguration;
static HMODULE InitializeWireGuardNT(void) {
HMODULE WireGuardDll = LoadLibraryExW(
L"wireguard.dll",
NULL,
LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32
);
if (!WireGuardDll) return NULL;
#define X(Name) ((*(FARPROC *)&Name = GetProcAddress(WireGuardDll, #Name)) == NULL)
if (X(WireGuardCreateAdapter) || X(WireGuardOpenAdapter) || X(WireGuardCloseAdapter) ||
X(WireGuardGetAdapterLUID) || X(WireGuardGetRunningDriverVersion) || X(WireGuardDeleteDriver) ||
X(WireGuardSetLogger) || X(WireGuardSetAdapterLogging) || X(WireGuardGetAdapterState) ||
X(WireGuardSetAdapterState) || X(WireGuardGetConfiguration) || X(WireGuardSetConfiguration))
#undef X
{
DWORD LastError = GetLastError();
FreeLibrary(WireGuardDll);
SetLastError(LastError);
return NULL;
}
return WireGuardDll;
}
GUID generateGUID() {
UUID uuid;
RPC_STATUS status = UuidCreate(&uuid);
// Handle GUID generation error
if (status != RPC_S_OK) {
fprintf(stderr, "[C] Failed to create GUID\n");
exit(1); // Exiting here to indicate a critical error; you may handle differently
}
char *initialServiceName = "WireGuardTunnel$";
char *tnlName = malloc(strlen(initialServiceName) + strlen(tunnelCharArr) + 1);
strcpy(tnlName, initialServiceName);
strcat(tnlName, tunnelCharArr);
// Copy the generated UUID into a GUID struct
GUID guid = { uuid.Data1, uuid.Data2, uuid.Data3 };
for (int i = 0; i < 8; i++) {
guid.Data4[i] = uuid.Data4[i];
}
char *initialDisplayName = "WireGuard Tunnel: ";
char *displayName = malloc(strlen(initialDisplayName) + strlen(tunnelCharArr) + 1);
strcpy(displayName, initialDisplayName);
strcat(displayName, tunnelCharArr);
return guid;
}
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_installAdapter(JNIEnv *env, jobject obj) {
HMODULE WireGuardDLL = InitializeWireGuardNT();
GUID guid = generateGUID();
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardCreateAdapter(L"TVPNet", L"WireGuard", &guid);
struct {
WIREGUARD_INTERFACE Interface;
WIREGUARD_PEER DemoServer;
WIREGUARD_ALLOWED_IP AllV4;
} Config = {
.Interface = {
.Flags = WIREGUARD_INTERFACE_HAS_PRIVATE_KEY,
.PeersCount = 1
},
.DemoServer = {
.Flags = WIREGUARD_PEER_HAS_PUBLIC_KEY | WIREGUARD_PEER_HAS_ENDPOINT,
.AllowedIPsCount = 1
},
.AllV4 = {
.AddressFamily = AF_INET
}
};
WireGuardSetConfiguration(Adapter, &Config.Interface, sizeof(Config));
WireGuardSetAdapterState(Adapter, WIREGUARD_ADAPTER_STATE_UP);
FreeLibrary(WireGuardDLL);
return 0;
}
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_removeAdapter(JNIEnv *env, jobject obj) {
HMODULE WireGuardDLL = InitializeWireGuardNT();
WIREGUARD_ADAPTER_HANDLE Adapter = WireGuardOpenAdapter(L"TVPNet");
printf("[C] Closing Adapter...\n");
WireGuardCloseAdapter(Adapter);
FreeLibrary(WireGuardDLL);
return 0;
}
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_installTunnel(JNIEnv *env, jobject obj, jstring tunnelName, jstring pathToConfig) {
printf("[C] Started installTunnel\n");
const jchar *rawStr = (*env)->GetStringChars(env, tunnelName, 0); //TODO mem cleanup
LPWSTR tnlName = (LPWSTR) rawStr;
wprintf(L"[C] Tunnel Name: %ls", tnlName);
wchar_t *servicePrefix = L"WireGuardTunnel$";
wchar_t *serviceName = malloc(sizeof(wchar_t) * (wcslen(servicePrefix) + wcslen(tnlName) + 1)); //TODO mem cleanup
wcscpy(serviceName, servicePrefix);
wcscat(serviceName, tnlName);
wchar_t *displayNamePrefix = L"WireGuard Tunnel: ";
wchar_t *displayName = malloc(sizeof(wchar_t) * (wcslen(displayNamePrefix) + wcslen(tnlName) + 1)); //TODO mem cleanup
wcscpy(displayName, displayNamePrefix);
wcscat(displayName, tnlName);
printf("[C] Opening Service Manager\n");
SC_HANDLE hSCManager = OpenSCManager(
NULL,
@ -30,21 +135,23 @@ JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_createTunnel(JNIEnv
SC_MANAGER_ALL_ACCESS
);
if (hSCManager == NULL) {
printf("OpenSCManager failed (%lu)\n", GetLastError());
return 2;
printf("[C] OpenSCManager failed (%lu)\n", GetLastError());
return 3;
}
char *params = "TVPN.exe /installtunnelservice ";
char *conf = ".conf";
char *exePath = malloc(strlen(APP_DIR) + strlen(params) + strlen(tunnelCharArr) + strlen(conf) + 1);
strcpy(exePath, APP_DIR);
strcat(exePath, params);
strcat(exePath, tunnelCharArr);
strcat(exePath, conf);
wchar_t *params = L"TVPN.exe /installtunnelservice ";
wchar_t *conf = L".conf";
wchar_t *exePath = malloc(sizeof(wchar_t) * (wcslen(APP_DIR) + wcslen(params) + wcslen(tnlName) + wcslen(conf) + 1)); //TODO mem cleanup
wcscpy(exePath, APP_DIR);
wcscat(exePath, params);
wcscat(exePath, tnlName);
wcscat(exePath, conf);
SC_HANDLE hService = CreateServiceA(
wprintf(L"[C] Creating Service: %ls\n", exePath);
SC_HANDLE hService = CreateServiceW(
hSCManager,
tnlName,
serviceName,
displayName,
SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
@ -53,42 +160,62 @@ JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_createTunnel(JNIEnv
exePath,
NULL,
NULL,
"Nsi\0TcpIp\0\0",
L"Nsi\0TcpIp\0\0",
NULL,
NULL
);
);
DWORD sid_info = SERVICE_SID_TYPE_UNRESTRICTED;
if (!ChangeServiceConfig2A(hService, SERVICE_CONFIG_SERVICE_SID_INFO, &sid_info)) {
printf("ChangeServiceConfig2W failed (%lu)\n", GetLastError());
(*env)->ReleaseStringUTFChars(env, tunnelName, tunnelCharArr);
free(tnlName);
printf("[C] Changing Service Config\n");
if (!ChangeServiceConfig2W(hService, SERVICE_CONFIG_SERVICE_SID_INFO, &sid_info)) {
printf("[C] ChangeServiceConfig2W failed (%lu)\n", GetLastError());
(*env)->ReleaseStringChars(env, tunnelName, rawStr);
free(serviceName);
free(displayName);
free(exePath);
CloseServiceHandle(hSCManager);
CloseServiceHandle(hService);
return 3;
return 4;
}
printf("[C] Cleaning up creation\n");
(*env)->ReleaseStringUTFChars(env, tunnelName, tunnelCharArr);
free(tnlName);
free(displayName);
free(exePath);
CloseServiceHandle(hSCManager);
CloseServiceHandle(hService);
free(serviceName);
free(displayName);
free(exePath);
(*env)->ReleaseStringChars(env, tunnelName, rawStr);
return 0;
printf("[C] Loading tunnel.dll\n");
HMODULE tunnel_lib = LoadLibrary("tunnel.dll");
if (!tunnel_lib) abort();
BOOL (_cdecl *tunnel_proc) (_In_ LPCWSTR conf_file);
*(FARPROC*) &tunnel_proc = GetProcAddress(tunnel_lib, "WireGuardTunnelService");
if (!tunnel_proc) abort();
const jchar *rawString = (*env)->GetStringChars(env, pathToConfig, NULL);
LPCWSTR configPath = (LPCWSTR) rawString;
//TODO figure out how to handle this
//(*env)->ReleaseStringChars(env, tunnelName, rawStr);
wprintf(L"[C] Calling function with arg: %ls\n", configPath);
return tunnel_proc(configPath);
}
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_deleteTunnel(JNIEnv *env, jobject obj, jstring tunnelName) {
const char *nativeString = (*env)->GetStringUTFChars(env, tunnelName, NULL);
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_removeTunnel(JNIEnv *env, jobject obj, jstring tunnelName) {
const jchar *nativeString = (*env)->GetStringChars(env, tunnelName, NULL);
char *initialServiceName = "WireGuardTunnel$";
char *tnlName = malloc(strlen(initialServiceName) + strlen(nativeString) + 1);
strcpy(tnlName, initialServiceName);
strcat(tnlName, nativeString);
wchar_t *initialServiceName = L"WireGuardTunnel$";
wchar_t *tnlName = malloc(sizeof(wchar_t) * (wcslen(initialServiceName) + wcslen(nativeString) + 1));
wcscpy(tnlName, initialServiceName);
wcscat(tnlName, nativeString);
SC_HANDLE hSCManager = OpenSCManager(
NULL,
@ -100,7 +227,7 @@ JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_deleteTunnel(JNIEnv
return 1;
}
SC_HANDLE hService = OpenServiceA(hSCManager, tnlName, DELETE);
SC_HANDLE hService = OpenServiceW(hSCManager, tnlName, DELETE);
if (hService != NULL) {
if (!DeleteService(hService)) {
// Handle error
@ -113,49 +240,8 @@ JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_deleteTunnel(JNIEnv
}
CloseServiceHandle(hSCManager);
(*env)->ReleaseStringUTFChars(env, tunnelName, nativeString);
(*env)->ReleaseStringChars(env, tunnelName, nativeString);
free(tnlName);
return 0;
}
JNIEXPORT jint JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_initializeWireGuard(JNIEnv *env, jobject obj, jstring configFilePath) {
const char *nativeString = (*env)->GetStringUTFChars(env, configFilePath, 0);
int confLength = strlen(nativeString);
(*env)->ReleaseStringUTFChars(env, configFilePath, nativeString);
return confLength;
// const char *nativeConfigFilePath = (*env)->GetStringUTFChars(env, configFilePath, 0);
// Load the WireGuard DLL dynamically
// hInstLibrary = LoadLibrary("tunnel.dll"); // Adjust with the actual DLL name
// if (hInstLibrary) {
// Example: Load the WireGuard function from DLL
// wg_func_t wg_init_func = (wg_func_t) GetProcAddress(hInstLibrary, "WireGuardInitFunction"); // Adjust based on the WireGuard API
// if (wg_init_func) {
// wg_init_func(nativeConfigFilePath);
// (*env)->ReleaseStringUTFChars(env, configFilePath, nativeConfigFilePath);
// return 0; // Success
// } else {
// printf("Failed to get function from WireGuard DLL\n");
// return -2; // Failed to get function
// }
// } else {
// printf("Failed to load WireGuard DLL\n");
// return -1; // Failed to load DLL
// }
}
JNIEXPORT void JNICALL Java_tech_nevets_tvpn_wg_WireGuardJNI_cleanup(JNIEnv *env, jobject obj) {
printf("Silly goose, this isn't implemented yet!\n");
// if (hInstLibrary) {
// FreeLibrary(hInstLibrary);
// }
}
}

View File

@ -1,6 +1,8 @@
package tech.nevets.tvpn;
import com.formdev.flatlaf.FlatDarkLaf;
import tech.nevets.jconf.JsonConfig;
import tech.nevets.tvpn.cli.CommandBrigadier;
import tech.nevets.tvpn.ui.UIManager;
import tech.nevets.tvpn.wg.WireGuardJNI;
@ -9,11 +11,16 @@ import java.io.File;
public class Main {
private static final Logger LOGGER = new Logger(Main.class);
public static void main(String[] args) {
LogOutputStream logOut = new LogOutputStream();
Logger.loadLogOutStream(logOut);
JsonConfig conf = new JsonConfig("");
if (args.length > 0) {
new CommandBrigadier().execute(args);
}
try {
javax.swing.UIManager.setLookAndFeel(new FlatDarkLaf());
} catch (UnsupportedLookAndFeelException e) {
@ -26,9 +33,8 @@ public class Main {
UIManager uim = new UIManager(logOut);
uim.startLoginFrame();
WireGuardJNI wgjni = new WireGuardJNI();
//WireGuardJNI wgjni = new WireGuardJNI();
//System.out.println(wgjni.createTunnel("test"));
System.out.println(wgjni.deleteTunnel("test"));
//System.out.println(wgjni.removeTunnel("test"));
}
}

View File

@ -1,5 +1,7 @@
package tech.nevets.tvpn;
import tech.nevets.jconf.JsonConfig;
import java.io.File;
import java.io.IOException;
import java.net.URI;
@ -10,14 +12,24 @@ import java.util.Map;
public class Utils {
private static final Logger LOGGER = new Logger(Utils.class);
public static final File APP_DIR = new File("./tvpn/");
public static final String WG_CONF_DIR = "C:\\Program Files\\WireGuard\\Data\\Configurations\\";
public static final String API_ENDPOINT_BASE = "http://tvpn.lan/testing/";
public static final File APP_DIR = new File("C:\\Program Files\\TVPN\\");
public static final JsonConfig CONFIG = new JsonConfig(APP_DIR + "/config.json", getConfStr());
public static final String API_ENDPOINT_BASE = CONFIG.getString("apiEndpoint");
static {
if (!APP_DIR.exists()) APP_DIR.mkdirs();
}
private static String getConfStr() {
return """
{
"apiEndpoint":"http://tvpn.lan"
}
""";
}
public static String get(URI url, Map<String, String> headers) {
HttpClient client = HttpClient.newHttpClient();
HttpRequest.Builder reqBuilder = HttpRequest.newBuilder()

View File

@ -0,0 +1,12 @@
package tech.nevets.tvpn.cli;
public interface Command {
void execute(String[] args);
String getName();
String getUsage();
String getDescription();
}

View File

@ -0,0 +1,49 @@
package tech.nevets.tvpn.cli;
import tech.nevets.tvpn.Logger;
import tech.nevets.tvpn.cli.commands.HelpCmd;
import tech.nevets.tvpn.cli.commands.InstallTunnelServiceCmd;
import tech.nevets.tvpn.cli.commands.UninstallTunnelServiceCmd;
import java.util.ArrayList;
import java.util.List;
public class CommandBrigadier {
private static final Logger LOGGER = new Logger(CommandBrigadier.class);
private final List<Command> registeredCommands;
private final HelpCmd helpCmd;
public CommandBrigadier() {
this.registeredCommands = new ArrayList<>();
helpCmd = new HelpCmd(this);
registerCommand(helpCmd);
registerCommand(new InstallTunnelServiceCmd());
registerCommand(new UninstallTunnelServiceCmd());
}
public void registerCommand(Command cmd) {
for (Command c : registeredCommands) {
if (c.getName().equals(cmd.getName())) {
LOGGER.warn("Command with name " + cmd.getName() + " already registered, skipping.");
return;
}
}
registeredCommands.add(cmd);
}
public void execute(String[] args) {
for (Command c : registeredCommands) {
if (c.getName().equals(args[0])) {
c.execute(args);
return;
}
}
helpCmd.execute(new String[0]);
}
public List<Command> getCommands() {
return registeredCommands;
}
}

View File

@ -0,0 +1,52 @@
package tech.nevets.tvpn.cli.commands;
import tech.nevets.tvpn.cli.Command;
import tech.nevets.tvpn.cli.CommandBrigadier;
public class HelpCmd implements Command {
private final CommandBrigadier cb;
public HelpCmd(CommandBrigadier cb) {
this.cb = cb;
}
@Override
public void execute(String[] args) {
if (args.length > 0) {
for (Command c : cb.getCommands()) {
if (!(args.length == 1) && args[1].equals(c.getName())) {
System.out.println("TVPN - Usage Menu [" + c.getName() + "]");
System.out.println(c.getName() + " " + c.getUsage() + ": " + c.getDescription());
System.exit(0);
}
}
}
StringBuilder sb = new StringBuilder();
sb.append("TVPN - Help Menu\n");
for (Command c : cb.getCommands()) {
sb.append(" - ").append(c.getName())
.append(" ").append(c.getUsage())
.append(": ").append(c.getDescription())
.append("\n");
}
System.out.println(sb);
System.exit(0);
}
@Override
public String getName() {
return "help";
}
@Override
public String getUsage() {
return "";
}
@Override
public String getDescription() {
return "Displays the help menu";
}
}

View File

@ -0,0 +1,71 @@
package tech.nevets.tvpn.cli.commands;
import tech.nevets.tvpn.Utils;
import tech.nevets.tvpn.cli.Command;
import tech.nevets.tvpn.wg.WireGuardJNI;
import java.util.regex.Pattern;
public class InstallTunnelServiceCmd implements Command {
@Override
public void execute(String[] args) {
System.out.println("Executing InstallTunnelServiceCmd");
String path = Utils.APP_DIR + "/configurations/" + args[1] + ".conf";
System.out.println(new WireGuardJNI().installTunnel(args[1], path));
System.exit(0);
}
@Override
public String getName() {
return "/installtunnelservice";
}
@Override
public String getUsage() {
return "(/path/to/tunnel/config)";
}
@Override
public String getDescription() {
return "Creates and starts a WireGuard Tunnel Service";
}
String[] reservedNames = new String[]{
"CON", "PRN", "AUX", "NUL",
"COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
};
private boolean isReserved(String name) {
if (name.isEmpty()) {
return false;
}
for (String s : reservedNames) {
if (name.contains(s)) {
return true;
}
}
return false;
}
private static final String[] SPECIAL_CHARS = new String[]{"$", "\\", "/", ":", "*", "?", "\"", "'", "<", ">", "|", "\t", "\00"};
private boolean hasSpecialChars(String name) {
for (String s : SPECIAL_CHARS) {
if (name.contains(s)) {
return true;
}
}
return false;
}
private static final Pattern PATTERN = Pattern.compile("^[a-zA-Z0-9_=+.-]{1,32}$");
private boolean tunnelNameIsValid(String name) {
if (isReserved(name) || hasSpecialChars(name)) {
return false;
}
return PATTERN.matcher(name).hasMatch();
}
}

View File

@ -0,0 +1,28 @@
package tech.nevets.tvpn.cli.commands;
import tech.nevets.tvpn.cli.Command;
import tech.nevets.tvpn.wg.WireGuardJNI;
public class UninstallTunnelServiceCmd implements Command {
@Override
public void execute(String[] args) {
System.out.println("Executing UnInstallTunnelServiceCmd");
System.out.println(new WireGuardJNI().removeTunnel(args[1]));
System.exit(0);
}
@Override
public String getName() {
return "/uninstalltunnelservice";
}
@Override
public String getUsage() {
return "(tunnel name)";
}
@Override
public String getDescription() {
return "Stops and removes WireGuard Tunnel Service";
}
}

View File

@ -13,7 +13,7 @@ public class UIManager {
public UIManager(LogOutputStream logOut) {
frame = new JFrame();
tabPane = new JTabbedPane();
tabPane = new JTabbedPane(JTabbedPane.TOP, JTabbedPane.SCROLL_TAB_LAYOUT);
homePanel = new HomePanel();
tabPane.addTab("Home", homePanel);

View File

@ -10,10 +10,14 @@ public class WireGuardJNI {
public native int installAdapter();
public native int removeAdapter();
public native int startTunnel(String tunnelName);
public native int stopTunnel(String tunnelName);
public native int createTunnel(String tunnelName);
public native int deleteTunnel(String tunnelName);
/**
* Creates and starts the WireGuard service
* @param tunnelName Name of the tunnel
* @param pathToConfig Full path to the tunnel's configuration file
* @return 0 if successful, 1 if failed
*/
public native int installTunnel(String tunnelName, String pathToConfig);
public native int removeTunnel(String tunnelName);
public native String getConfig(String tunnelName);
public native int updateConfig(String tunnelName, String newConfig);

BIN
src/main/resources/icon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

BIN
src/main/resources/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 216 KiB