2024-07-21 00:31:22 +03:30
using Microsoft.Extensions.DependencyInjection ;
2024-01-25 20:38:47 +03:30
using MTWireGuard.Application.Repositories ;
2024-07-21 00:31:22 +03:30
using Serilog ;
using System.Net.NetworkInformation ;
2024-01-25 20:38:47 +03:30
using System.Net.Sockets ;
using System.Text ;
namespace MTWireGuard.Application
{
public class SetupValidator ( IServiceProvider serviceProvider )
{
private IMikrotikRepository api ;
2024-07-21 00:31:22 +03:30
private ILogger logger ;
2024-01-25 20:38:47 +03:30
2024-07-21 00:31:22 +03:30
public static bool IsValid { get ; private set ; }
public static string Title { get ; private set ; }
public static string Description { get ; private set ; }
public async Task < bool > Validate ( )
2024-01-25 20:38:47 +03:30
{
2024-07-21 00:31:22 +03:30
InitializeServices ( ) ;
if ( ValidateEnvironmentVariables ( ) )
2024-01-25 20:38:47 +03:30
{
2024-07-21 00:31:22 +03:30
LogAndDisplayError ( "Environment variables are not set!" , "Please set \"MT_IP\", \"MT_USER\", \"MT_PASS\", \"MT_PUBLIC_IP\" variables in container environment." ) ;
IsValid = false ;
return false ;
2024-01-25 20:38:47 +03:30
}
2024-07-21 00:31:22 +03:30
if ( ! File . Exists ( Helper . GetIDFile ( ) ) )
{
using var fs = File . OpenWrite ( Helper . GetIDFile ( ) ) ;
var id = Guid . NewGuid ( ) . ToString ( ) ;
id = id [ ( id . LastIndexOf ( '-' ) + 1 ) . . ] ;
byte [ ] identifier = new UTF8Encoding ( true ) . GetBytes ( id ) ;
fs . Write ( identifier , 0 , identifier . Length ) ;
}
2024-01-25 20:38:47 +03:30
var ( apiConnection , apiConnectionMessage ) = await ValidateAPIConnection ( ) ;
if ( ! apiConnection )
{
2024-07-21 00:31:22 +03:30
var MT_IP = Environment . GetEnvironmentVariable ( "MT_IP" ) ;
var ping = new Ping ( ) ;
var reply = ping . Send ( MT_IP , 60 * 1000 ) ;
if ( reply . Status = = IPStatus . Success )
{
LogAndDisplayError ( "Error connecting to the router api!" , apiConnectionMessage ) ;
}
else
{
LogAndDisplayError ( "Error connecting to the router api!" , $"Can't find Mikrotik API server at address: {MT_IP}\r\nping status: {reply.Status}" ) ;
}
IsValid = false ;
return false ;
2024-01-25 20:38:47 +03:30
}
var ip = GetIPAddress ( ) ;
if ( string . IsNullOrEmpty ( ip ) )
{
2024-07-21 00:31:22 +03:30
LogAndDisplayError ( "Error getting container IP address!" , "Invalid container IP address." ) ;
IsValid = false ;
return false ;
2024-01-25 20:38:47 +03:30
}
2024-07-21 00:31:22 +03:30
if ( ! await api . TryConnectAsync ( ) )
2024-01-25 20:38:47 +03:30
{
2024-07-21 00:31:22 +03:30
LogAndDisplayError ( "Error connecting to the router api!" , "Connecting to API failed." ) ;
IsValid = false ;
return false ;
2024-01-25 20:38:47 +03:30
}
2024-07-21 00:31:22 +03:30
await EnsureTrafficScripts ( ip ) ;
IsValid = true ;
return true ;
2024-01-25 20:38:47 +03:30
}
private static bool ValidateEnvironmentVariables ( )
{
string? IP = Environment . GetEnvironmentVariable ( "MT_IP" ) ;
string? USER = Environment . GetEnvironmentVariable ( "MT_USER" ) ;
string? PASS = Environment . GetEnvironmentVariable ( "MT_PASS" ) ;
string? PUBLICIP = Environment . GetEnvironmentVariable ( "MT_PUBLIC_IP" ) ;
return string . IsNullOrEmpty ( IP ) | | string . IsNullOrEmpty ( USER ) | | string . IsNullOrEmpty ( PUBLICIP ) ;
}
private async Task < ( bool status , string? message ) > ValidateAPIConnection ( )
{
try
{
return ( await api . TryConnectAsync ( ) , string . Empty ) ;
}
catch ( Exception ex )
{
return ( false , ex . Message ) ;
}
}
2024-07-21 00:31:22 +03:30
private string GetIPAddress ( )
2024-01-25 20:38:47 +03:30
{
try
{
var name = System . Net . Dns . GetHostName ( ) ;
var port = Environment . GetEnvironmentVariable ( "ASPNETCORE_HTTP_PORTS" ) ;
return System . Net . Dns . GetHostEntry ( name ) . AddressList . FirstOrDefault ( x = > x . AddressFamily = = AddressFamily . InterNetwork ) . ToString ( ) + $":{port}" ;
}
catch ( Exception ex )
{
2024-07-21 00:31:22 +03:30
logger . Error ( ex , "Error getting container IP address." ) ;
2024-01-25 20:38:47 +03:30
return string . Empty ;
}
}
2024-07-21 00:31:22 +03:30
private void LogAndDisplayError ( string title , string description )
{
Title = title ;
Description = description ;
Console . BackgroundColor = ConsoleColor . Black ;
Console . ForegroundColor = ConsoleColor . Red ;
Console . WriteLine ( $"[-] {Title}" ) ;
Console . WriteLine ( $"[!] {Description}" ) ;
Console . ResetColor ( ) ;
logger . Error ( "Error in container configuration" , new { Error = Title , Description } ) ;
}
private void InitializeServices ( )
{
serviceProvider . GetService < DBContext > ( ) . Database . EnsureCreated ( ) ;
api = serviceProvider . GetService < IMikrotikRepository > ( ) ;
logger = serviceProvider . GetService < ILogger > ( ) ;
}
private async Task EnsureTrafficScripts ( string ip )
{
var scripts = await api . GetScripts ( ) ;
var schedulers = await api . GetSchedulers ( ) ;
//if (scripts.Find(x => x.Name == "SendTrafficUsage") == null)
//{
// var create = await api.CreateScript(new()
// {
// Name = "SendTrafficUsage",
// Policies = ["write", "read", "test", "ftp"],
// DontRequiredPermissions = false,
// Source = Helper.PeersTrafficUsageScript($"http://{ip}/api/usage")
// });
// var result = create.Code;
// logger.Information("Created TrafficUsage Script", new
// {
// result = create
// });
//}
if ( schedulers . Find ( x = > x . Name = = "TrafficUsage" ) = = null )
{
var create = await api . CreateScheduler ( new ( )
{
Name = "TrafficUsage" ,
Interval = new TimeSpan ( 0 , 5 , 0 ) ,
//OnEvent = "SendTrafficUsage",
OnEvent = Helper . PeersTrafficUsageScript ( $"http://{ip}/api/usage" ) ,
Policies = [ "write" , "read" , "test" , "ftp" ] ,
Comment = "update wireguard peers traffic usage"
} ) ;
var result = create . Code ;
logger . Information ( "Created TrafficUsage Scheduler" , new
{
result = create
} ) ;
}
}
2024-01-25 20:38:47 +03:30
private static void Shutdown ( )
{
Environment . Exit ( 0 ) ;
}
}
}