From e2dd49bbcba7d010078a7dc4ff134049cf4d1641 Mon Sep 17 00:00:00 2001 From: Timerix22 Date: Thu, 4 Jan 2024 01:02:08 +0600 Subject: [PATCH] TunnelProtocol and InputMode --- TODO.md | 81 +++++++++++++++++++++++++-- kerep | 2 +- src/help_message.c | 44 +++++++++++---- src/main.c | 137 ++++++++++++++++++++++++++++++++++++--------- 4 files changed, 220 insertions(+), 44 deletions(-) diff --git a/TODO.md b/TODO.md index 049c6f9..036dbe1 100644 --- a/TODO.md +++ b/TODO.md @@ -1,5 +1,78 @@ # TODO: -- listen to tcp/udp://:port -- connect to tcp/udp://ip:port -- generate temp password from key every 10 minutes: rng(seed: time()/(10\*60\*CLOCKS_PER_SECOND), salt: hash(key)) -- encrypt/decrypt +- listen and connect for UDP + ```js + listener { + mainsock = new UdpSocket(true) + mainsock.bind(in_end) + + do { + pac = mainsock.receiveAny(out sender_end) + } while (pac is not ConnectionRequest) skip package + connector_end = sender_end + mainsock.sendTo(ConnectionConfirmation, connector_end) + + attemptN = 0 + while(attemptN < 20){ + try { + pac = mainsock.receiveAny(out sender_end) + if(sender_end == connector_end) { + connector_pac = new ConnectorPackage.parse(pac) + mainsock.sendTo(connector_pac.data, connector_pac.destination), + } + else { + extern_pac = new ExternPackage(pac, sender_end) + mainsock.sendTo(extern_pac, connector_end) + } + attemptN = 0 + } + catch { + attemptN++ + sleep(10ms) + } + } + log("connector is unreachable") + } + + connector { + if(output_mode == bind) { + mainsock = new UdpSocket(true) + mainsock.bind(out_end) + } + else if(output_mode == send) { + mainsock = new UdpSocket(false) + } + else throw + + attemptN = 0 + while(attemptN < 20) { + try { + pac = mainsock.receiveAny(out sender_end) + if(sender_end == out_end) { + connector_pac = new ConnectorPackage(pac) + } + else { + extern_pac = ExternPackage.parse(pac) + mainsock.sendTo(extern_pac.data, out_end) + } + attemptN = 0 + } + catch { + attemptN++ + sleep(10ms) + } + } + log("connector is unreachable") + } + + ``` +- listen and connect for TCP + ```js + + ``` + +- encrypt/decrypt input/output + - generate temp password from key every 10 minutes: + ```js + rng(seed: time()/(10*60*CLOCKS_PER_SECOND), salt: hash(key)) + ``` + diff --git a/kerep b/kerep index 7ba15b2..95a9fcf 160000 --- a/kerep +++ b/kerep @@ -1 +1 @@ -Subproject commit 7ba15b208f105b0a6c2a9dfdb522c149e2d36620 +Subproject commit 95a9fcfd5e7bbe14962156a4fa4eb8d686fc4c13 diff --git a/src/help_message.c b/src/help_message.c index 9a21777..a5f7316 100644 --- a/src/help_message.c +++ b/src/help_message.c @@ -18,33 +18,53 @@ const char* help_message = ( FWHI"Usage: port-tunnel " - HELP_PRM("program_mode") - " " HELP_PRM("other_options...") "\n" + HELP_PRM("protocol_options") " " + HELP_PRM("input_options") " " + HELP_PRM("output_options") " " + HELP_PRMN("other_options") "\n" - FWHI" Options syntax: --"FCYN" " HELP_PRM("options") "\n" + FWHI" Help syntax:\n" " " HELP_PRM("val") FGRY" - some value\n" " " HELP_PRMN("val") FGRY" - value or nothing\n" " " HELP_PRM2("variant1", "variant2") FGRY" - variant1 or variant2\n" - FWHI" Program mode options:\n" + FWHI" Protocol options:\n" - HELP_OPT("-c, --connect", - HELP_PRM2("tcp","udp") "://" HELP_PRMN("ip") ":" HELP_PRM("port"), - " Connect to a listening instance of port-tunnel.\n") + HELP_OPT("-p, --protocol", + HELP_PRM2("tcp","udp"), + " Set tunnel protocol.\n") + + FWHI" Input mode options:\n" HELP_OPT("-l, --listen", - HELP_PRM2("tcp","udp") "://" HELP_PRMN("ip") ":" HELP_PRM("port"), + HELP_PRM("ip") ":" HELP_PRM("port"), " Listen for incomming packets at the address (if provided) and the port\n") + HELP_OPT("-c, --connect", + HELP_PRM("ip") ":" HELP_PRM("port") " " + HELP_PRM2( + "-s " HELP_PRM("ip") ":" HELP_PRM("port"), + "-b " HELP_PRM("ip") ":" HELP_PRM("port") + ), + " Connect to a listening instance of port-tunnel.\n") + + FWHI" Output mode options:\n" + + HELP_OPT("-s, --send-to", + HELP_PRM("ip") ":" HELP_PRM("port"), + " Redirect packets from tunnel to "FCYN"ip:port"FWHI".\n" + " Use this flag if you need to create tunnel to an existing socket bound at "FCYN"ip:port"FWHI".\n") + + HELP_OPT("-b, --bind-to", + HELP_PRM("ip") ":" HELP_PRM("port"), + " Bind new socket to "FCYN"ip:port"FWHI" and redirect packets from tunnel to it.\n" + " Use this flag if you want to connect something to "FCYN"ip:port"FWHI".\n") + FWHI" Other options:\n" HELP_OPT("-h, --help, /?", "", " Show this message.\n") - HELP_OPT("-p, --out-port", - HELP_PRM("port"), - " Port incoming packets will be sent to.\n") - HELP_OPT("-d, --decrypt", HELP_PRM("key"), " Decrypt incoming packets with a key.\n") diff --git a/src/main.c b/src/main.c index ed83609..fc8b350 100644 --- a/src/main.c +++ b/src/main.c @@ -1,4 +1,5 @@ #include "../kerep/src/base/base.h" +#include "../kerep/src/Network/network.h" extern const char* help_message; @@ -12,10 +13,22 @@ int errs(char* err_msg){ #define argNext() argv[++argi < argc ? argi : errs(cptr_concat("option '",arg,"' must have a parameter"))] typedef enum { - ProgramMode_None, - ProgramMode_Listen, - ProgramMode_Connect -} ProgramMode; + TunnelProtocol_None, + TunnelProtocol_TCP, + TunnelProtocol_UDP +} TunnelProtocol; + +typedef enum { + InputMode_None, + InputMode_Listen, + InputMode_Connect +} InputMode; + +typedef enum { + OutputMode_None, + OutputMode_Bind, + OutputMode_Send +} OutputMode; int main(int argc, const char* const* argv){ kt_beginInit(false); @@ -23,9 +36,13 @@ int main(int argc, const char* const* argv){ // kt_register(...); kt_endInit(); - ProgramMode mode = ProgramMode_None; - const char* endpoint_str = ""; - const char* out_port_str = ""; + TunnelProtocol tunnel_protocol = TunnelProtocol_None; + InputMode input_mode = InputMode_None; + OutputMode output_mode = OutputMode_None; + knIPV4Endpoint input_end = knIPV4Endpoint_INVALID; + knIPV4Endpoint output_end = knIPV4Endpoint_INVALID; + const char* encryption_key = NULL; + const char* decryption_key = NULL; if(argc < 2) throw("No arguments provided. Run the program with argument -h to see help message"); @@ -36,35 +53,101 @@ int main(int argc, const char* const* argv){ kprintf("%s"FGRY"\n", help_message); return 0; } - else if(argIs("-c") || argIs("--connect")){ - if(mode != ProgramMode_None) - throw(cptr_concat("invalid option '",arg,"': program mode has been selected already")); + else if(argIs("-p") || argIs("--protocol")){ + if(tunnel_protocol != TunnelProtocol_None) + throw(cptr_concat("invalid option '",arg,"': tunnel protocol has been set already")); - mode = ProgramMode_Connect; - endpoint_str = argNext(); - } - else if(argIs("-l") || argIs("--listen")){ - if(mode != ProgramMode_None) - throw(cptr_concat("invalid option '",arg,"': program mode has been selected already")); - - mode = ProgramMode_Listen; - endpoint_str = argNext(); + const char* protocol_str = argNext(); + char* protocol_str_lower = cptr_toLower(protocol_str); + if(cptr_equals(protocol_str_lower, "tcp")) + tunnel_protocol = TunnelProtocol_TCP; + else if(cptr_equals(protocol_str_lower, "udp")) + tunnel_protocol = TunnelProtocol_UDP; + else throw(cptr_concat("invalid parameter '",protocol_str,"': unknown protocol")); + free(protocol_str_lower); } - else if(argIs("-p") || argIs("--out-port")){ - if(out_port_str[0] != 0) - throw(cptr_concat("invalid option '",arg,"': out port has been selected already")); - if(mode != ProgramMode_Connect) - throw(cptr_concat("invalid option '",arg,"': out port setting is avaliable only for 'connect' program mode")); + else if(argIs("-l") || argIs("--listen")){ + if(input_mode != InputMode_None) + throw(cptr_concat("invalid option '",arg,"': input mode has been set already")); - out_port_str = argNext(); + input_mode = InputMode_Listen; + const char* input_end_str = argNext(); + tryLast(knIPV4Endpoint_fromStr(input_end_str, &input_end), _m8612, ;); + } + else if(argIs("-c") || argIs("--connect")){ + if(input_mode != InputMode_None) + throw(cptr_concat("invalid option '",arg,"': input mode has been set already")); + + input_mode = InputMode_Connect; + const char* input_end_str = argNext(); + tryLast(knIPV4Endpoint_fromStr(input_end_str, &input_end), _m2612, ;); + } + else if(argIs("-s") || argIs("--send-to")){ + if(output_mode != OutputMode_None) + throw(cptr_concat("invalid option '",arg,"': output mode has been set already")); + if(input_mode != InputMode_Connect) + throw(cptr_concat("invalid option '",arg,"': out endpoint setting is avaliable only in 'connect' program mode")); + + output_mode = OutputMode_Send; + const char* output_end_str = argNext(); + tryLast(knIPV4Endpoint_fromStr(output_end_str, &output_end), _m8613, ;); + } + else if(argIs("-b") || argIs("--bind-to")){ + if(output_mode != OutputMode_None) + throw(cptr_concat("invalid option '",arg,"': output mode has been set already")); + if(input_mode != InputMode_Connect) + throw(cptr_concat("invalid option '",arg,"': out endpoint setting is avaliable only in 'connect' program mode")); + + output_mode = OutputMode_Bind; + const char* output_end_str = argNext(); + tryLast(knIPV4Endpoint_fromStr(output_end_str, &output_end), _m2613, ;); + } + else if(argIs("-e") || argIs("--encrypt")){ + if(encryption_key != NULL) + throw(cptr_concat("invalid option '",arg,"': encryption key has been set already")); + + encryption_key = argNext(); + if(cptr_length(encryption_key) < 16) + throw("too short encryption key (min length 16)"); + if(cptr_length(encryption_key) > 512) + throw("too long encryption key (max length 512)"); + } + else if(argIs("-d") || argIs("--decrypt")){ + if(decryption_key != NULL) + throw(cptr_concat("invalid option '",arg,"': decryption key has been set already")); + + decryption_key = argNext(); + if(cptr_length(decryption_key) < 16) + throw("too short decryption key (min length 16)"); + if(cptr_length(decryption_key) > 512) + throw("too long decryption key (max length 512)"); } else { throw(cptr_concat("invalid argument: ", arg)); } } - kprintf("endpoint_str: %s\n", endpoint_str); - kprintf("out_port_str: %s\n", out_port_str); + kprintf("tunnel_protocol: %i\n", tunnel_protocol); + kprintf("input_mode: %i\n", input_mode); + kprintf("output_mode: %i\n", output_mode); + + char* temps; + if(!knIPV4Endpoint_isINVALID(input_end)){ + temps = knIPV4Endpoint_toString(&input_end); + kprintf("input_end: %s\n", temps); + free(temps); + } + else kprintf("input_end: INVALID\n"); + + if(!knIPV4Endpoint_isINVALID(output_end)){ + temps = knIPV4Endpoint_toString(&output_end); + kprintf("output_end: %s\n", temps); + free(temps); + } + else kprintf("output_end: INVALID\n"); + + kprintf("encryption_key: %s\n", encryption_key ? encryption_key : "NULL"); + kprintf("decryption_key: %s\n", decryption_key ? decryption_key : "NULL"); return 0; }