Skip to content

Commit

Permalink
generally finish reality client/server
Browse files Browse the repository at this point in the history
  • Loading branch information
radkesvat committed May 9, 2024
1 parent 330415b commit 50f8298
Show file tree
Hide file tree
Showing 5 changed files with 190 additions and 322 deletions.
1 change: 1 addition & 0 deletions tunnels/client/reality/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ add_library(RealityClient STATIC
target_include_directories(RealityClient PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../../ww)
target_link_libraries(RealityClient ww)
target_include_directories(RealityClient PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../shared/openssl)
target_include_directories(RealityClient PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../shared/reality)


# add dependencies
Expand Down
159 changes: 6 additions & 153 deletions tunnels/client/reality/reality_client.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,9 @@
#include "buffer_pool.h"
#include "buffer_stream.h"
#include "context_queue.h"
#include "frand.h"
#include "loggers/network_logger.h"
#include "openssl_globals.h"
#include "shiftbuffer.h"
#include "tunnel.h"
#include "reality_helpers.h"
#include "utils/hashutils.h"
#include "utils/jsonutils.h"
#include "utils/mathutils.h"
Expand All @@ -15,19 +13,6 @@
#include <openssl/evp.h>
#include <openssl/pem.h>
#include <openssl/ssl.h>
#include <stdint.h>
#include <string.h>

// these should not be modified, code may break
enum reality_consts
{
kEncryptionBlockSize = 16,
kSignLen = (224 / 8),
kSignPasswordLen = kEncryptionBlockSize,
kIVlen = 16, // iv size for *most* modes is the same as the block size. For AES this is 128 bits
kTLSVersion12 = 0x0303,
kTLS12ApplicationData = 0x17,
};

typedef struct reailty_client_state_s
{
Expand Down Expand Up @@ -121,138 +106,6 @@ static void flushWriteQueue(tunnel_t *self, context_t *c)
}
}

static bool verifyMessage(shift_buffer_t *buf, reailty_client_con_state_t *cstate)
{
int rc = EVP_DigestSignInit(cstate->sign_context, NULL, cstate->msg_digest, NULL, cstate->sign_key);
uint8_t expect[EVP_MAX_MD_SIZE];
memcpy(expect, rawBuf(buf), kSignLen);
shiftr(buf, kSignLen);
assert(rc == 1);
rc = EVP_DigestSignUpdate(cstate->sign_context, rawBuf(buf), bufLen(buf));
assert(rc == 1);
uint8_t buff[EVP_MAX_MD_SIZE];
size_t size = sizeof(buff);
rc = EVP_DigestSignFinal(cstate->sign_context, buff, &size);
assert(rc == 1);
assert(size == kSignLen);
return ! ! CRYPTO_memcmp(expect, buff, size);
}

static void signMessage(shift_buffer_t *buf, reailty_client_con_state_t *cstate)
{
int rc = EVP_DigestSignInit(cstate->sign_context, NULL, cstate->msg_digest, NULL, cstate->sign_key);
assert(rc == 1);
rc = EVP_DigestSignUpdate(cstate->sign_context, rawBuf(buf), bufLen(buf));
assert(rc == 1);
size_t req = 0;
rc = EVP_DigestSignFinal(cstate->sign_context, NULL, &req);
assert(rc == 1);
shiftl(buf, req);
size_t slen = 0;
rc = EVP_DigestSignFinal(cstate->sign_context, rawBufMut(buf), &slen);
assert(rc == 1);
assert(req == slen == kSignLen);
}

static shift_buffer_t *genericDecrypt(shift_buffer_t *in, reailty_client_con_state_t *cstate, char *password,
buffer_pool_t *pool)
{
shift_buffer_t *out = popBuffer(pool);
uint16_t input_length = bufLen(in);

uint8_t iv[kIVlen];
memcpy(iv, rawBuf(in), kIVlen);
shiftr(in, kIVlen);

EVP_DecryptInit_ex(cstate->decryption_context, EVP_aes_128_cbc(), NULL, (const uint8_t *) password,
(const uint8_t *) iv);

reserveBufSpace(out, input_length + (2 * kEncryptionBlockSize));
int out_len = 0;

/*
* Provide the message to be decrypted, and obtain the plaintext output.
* EVP_DecryptUpdate can be called multiple times if necessary.
*/
if (1 != EVP_DecryptUpdate(cstate->decryption_context, rawBufMut(out), &out_len, rawBuf(in), input_length))
{
printSSLErrorAndAbort();
}
setLen(out, out_len);

/*
* Finalise the decryption. Further plaintext bytes may be written at
* this stage.
*/
if (1 != EVP_DecryptFinal_ex(cstate->decryption_context, rawBufMut(out) + out_len, &out_len))
{
printSSLErrorAndAbort();
}
reuseBuffer(pool, in);

setLen(out, bufLen(out) + out_len);
return out;
}
static shift_buffer_t *genericEncrypt(shift_buffer_t *in, reailty_client_con_state_t *cstate, char *password,
buffer_pool_t *pool)
{
shift_buffer_t *out = popBuffer(pool);
int input_length = (int) bufLen(in);

uint8_t iv[kIVlen];
for (int i; i < kIVlen / sizeof(uint32_t); i++)
{
((uint32_t *) iv)[i] = fastRand();
}

EVP_EncryptInit_ex(cstate->encryption_context, EVP_aes_128_cbc(), NULL, (const uint8_t *) password,
(const uint8_t *) iv);

reserveBufSpace(out, input_length + (input_length % kEncryptionBlockSize));
int out_len = 0;

/*
* Provide the message to be encrypted, and obtain the encrypted output.
* EVP_EncryptUpdate can be called multiple times if necessary
*/
if (1 != EVP_EncryptUpdate(cstate->encryption_context, rawBufMut(out), &out_len, rawBuf(in), input_length))
{
printSSLErrorAndAbort();
}

setLen(out, bufLen(out) + out_len);

/*
* Finalise the encryption. Further ciphertext bytes may be written at
* this stage.
*/
if (1 != EVP_EncryptFinal_ex(cstate->encryption_context, rawBufMut(out) + out_len, &out_len))
{
printSSLErrorAndAbort();
}
reuseBuffer(pool, in);
setLen(out, bufLen(out) + out_len);

shiftl(out, kIVlen);
memcpy(rawBufMut(out), iv, kIVlen);
return out;
}

static void appendTlsHeader(shift_buffer_t *buf)
{
unsigned int data_length = bufLen(buf);
assert(data_length < (1U << 16));

shiftl(buf, sizeof(uint16_t));
writeUI16(buf, (uint16_t) data_length);

shiftl(buf, sizeof(uint16_t));
writeUI16(buf, kTLSVersion12);

shiftl(buf, sizeof(uint8_t));
writeUI8(buf, kTLS12ApplicationData);
}

static void upStream(tunnel_t *self, context_t *c)
{
reailty_client_state_t *state = STATE(self);
Expand All @@ -275,8 +128,8 @@ static void upStream(tunnel_t *self, context_t *c)
shift_buffer_t *chunk = shallowSliceBuffer(buf, remain);
shiftl(chunk, 2);
writeUI16(chunk, remain);
chunk = genericEncrypt(chunk, cstate, state->context_password, getContextBufferPool(c));
signMessage(chunk, cstate);
chunk = genericEncrypt(chunk, cstate->encryption_context, state->context_password, getContextBufferPool(c));
signMessage(chunk, cstate->msg_digest, cstate->sign_context, cstate->sign_key);
appendTlsHeader(chunk);
context_t *cout = newContextFrom(c);
cout->payload = chunk;
Expand Down Expand Up @@ -394,14 +247,15 @@ static void downStream(tunnel_t *self, context_t *c)
shift_buffer_t *buf = bufferStreamRead(cstate->read_stream, sizeof(tls_header) + length);
shiftr(buf, sizeof(tls_header));

if (! verifyMessage(buf, cstate))
if (! verifyMessage(buf, cstate->msg_digest, cstate->sign_context, cstate->sign_key))
{
LOGE("RealityClient: verifyMessage failed");
reuseBuffer(getContextBufferPool(c), buf);
goto failed;
}

buf = genericDecrypt(buf, cstate, state->context_password, getContextBufferPool(c));
buf = genericDecrypt(buf, cstate->decryption_context, state->context_password,
getContextBufferPool(c));
uint16_t length = 0;
readUI16(buf, &(length));
shiftr(buf, sizeof(uint16_t));
Expand Down Expand Up @@ -528,7 +382,6 @@ static void downStream(tunnel_t *self, context_t *c)
// queue is flushed and we are done
}
}

}
// done with socket data
reuseContextBuffer(c);
Expand Down
1 change: 1 addition & 0 deletions tunnels/server/reality/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ target_include_directories(RealityServer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../.
target_link_libraries(RealityServer ww)

target_include_directories(RealityServer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../shared/openssl)
target_include_directories(RealityServer PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/../../shared/reality)


# add dependencies
Expand Down
Loading

8 comments on commit 50f8298

@Saleh-Mumtaz
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

عرض درود و خسته نباشید خدمت مهندس عزیز
در مورد RTT مسئله محدودیت روی ایپی دیتا سنترهای معروف پیش امد، که رفتید سراغ RTCF
میخواستم بدونم با توجه به اینکه WW یک هسته انعطاف پذیر هست، میشه کانکشن ریورس رو با ریلیتی انجام داد یا ریلیتی نمیتونه اون محدودیت رو دور بزنه؟

@radkesvat
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

میشه ریورس رو با ریلیتی یا tls یا هر ترکیب دیگه ای هم انجام داد؛ نسخه که منتشر شد ادامه داکیومنت هارو میرم و کامل تر توضیح میدم

@omidcrfx
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

سلام و عرض ادب خسته نباشید
احتراما من میخواستم شیوه ی Direct trojan رو ران کنم ، اسکریپت رو در کنار فایل های core و config ران کردم ولی متاسفانه اررور فایل ssl میده، ممنون میشم راهنمایی بفرمایید.

@radkesvat
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

تروجان نیاز به دامنه و سرتیفکیت داره ؛ که باید فایل های fullchain.pem و همچنین privkey.pem رو هم اونجا داشته باشید (این ها فایل های سرتیفکیت هستن)

اگه این فایل هارو داشتین و بازم ارور داد یا کلا مشکلی بود ؛ متن ارور هم بفرستین کمک میکنه

@omidcrfx
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

متشکرم ssl رو فعال کردم و اسکریپت ران شد
فقط اینکه سمت کلاینت بخش های مختلف از جمله fingerprint و alpn و... هم نیازه که چی قرار بدیم یا کلا خالی بمونن؟
ممنون از زحماتتون

@radkesvat
Copy link
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

مهم نیست هرچی باشن فرقی نمیکنه

@omidcrfx
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

متشکرم🌹🙏

@omidcrfx
Copy link

@omidcrfx omidcrfx commented on 50f8298 May 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

سلام مجدد روز بخیر
با مصرف شدن حدودا 100 گیگ، آی پی سرور و ساب دامنه روی همراه اول فیلتر شد، آیا پسوند دامنه مهمه در فیلتر شدن؟ اگر بله چه پسوندی رو پیشنهاد میفرمایید
و اینکه با یه ساب دامنه دیگه میخواستم مجدد ران کنم و براش ssl هم گرفتم و جایگزین ssl فعلی در فایل های fullchain.pem و همچنین privkey.pem کردم ولی این ارور رو میده

WARN TrojanAuthServer: detected non trojan protocol, rejected [trojan_auth_server.c:103:upStream]
ERROR E0E1568AFFFF0000:error:0A000412:SSL routines:ssl3_read_bytes:ssl/tls alert bad certificate:../openssl-source-src/ssl/record/rec_layer_s3.c:907:SSL alert number 42
[openssl_globals.h:168:printSSLError]

Please sign in to comment.