From 24cebb82f43cdfa5de8337338c1c789e728f282e Mon Sep 17 00:00:00 2001 From: K4YT3X Date: Thu, 13 Jan 2022 16:24:43 +0000 Subject: [PATCH 1/6] using multi-stage build to reduce image size --- Dockerfile | 27 +++++++++++++-------------- 1 file changed, 13 insertions(+), 14 deletions(-) diff --git a/Dockerfile b/Dockerfile index 2656e734..9eeb0aea 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,21 +1,20 @@ -FROM alpine:3.11 - -COPY . trojan -RUN apk add --no-cache --virtual .build-deps \ +FROM alpine:3.15 AS builder +COPY . /trojan +RUN apk add --no-cache \ + boost-dev \ build-base \ cmake \ - boost-dev \ - openssl-dev \ mariadb-connector-c-dev \ - && (cd trojan && cmake . && make -j $(nproc) && strip -s trojan \ - && mv trojan /usr/local/bin) \ - && rm -rf trojan \ - && apk del .build-deps \ - && apk add --no-cache --virtual .trojan-rundeps \ - libstdc++ \ - boost-system \ + openssl-dev \ + && (cd /trojan && cmake . && make -j $(nproc) && strip -s trojan) + +FROM alpine:3.15 +RUN apk add --no-cache \ boost-program_options \ + boost-system \ + libstdc++ \ mariadb-connector-c +COPY --from=builder /trojan/trojan /usr/local/bin/trojan WORKDIR /config -CMD ["trojan", "config.json"] +ENTRYPOINT ["/usr/local/bin/trojan", "/config/config.json"] From 3398c6cc790ada6320cd2c82053b26037bc6d55d Mon Sep 17 00:00:00 2001 From: KujouRinka Date: Fri, 21 Jan 2022 22:31:19 +0800 Subject: [PATCH 2/6] perf: improve Trojan header splicing perf --- src/session/clientsession.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/session/clientsession.cpp b/src/session/clientsession.cpp index 05373484..863a5945 100644 --- a/src/session/clientsession.cpp +++ b/src/session/clientsession.cpp @@ -162,7 +162,10 @@ void ClientSession::in_recv(const string &data) { destroy(); return; } - out_write_buf = config.password.cbegin()->first + "\r\n" + data[1] + data.substr(3) + "\r\n"; + out_write_buf = string().append(config.password.cbegin()->first) + .append("\r\n").append(1, data[1]) + .append(data.substr(3)) + .append("\r\n"); TrojanRequest req; if (req.parse(out_write_buf) == -1) { Log::log_with_endpoint(in_endpoint, "unsupported command", Log::ERROR); From 816ef61d3e3fbe13e26db9169a25ca7f5396d1c8 Mon Sep 17 00:00:00 2001 From: Chigusa0w0 <9378097+Chigusa0w0@users.noreply.github.com> Date: Wed, 1 Jun 2022 02:08:36 -0400 Subject: [PATCH 3/6] Add ACTIVE_DISCONNECT session state --- src/session/serversession.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/session/serversession.h b/src/session/serversession.h index c351f28d..03bfcaca 100644 --- a/src/session/serversession.h +++ b/src/session/serversession.h @@ -30,7 +30,8 @@ class ServerSession : public Session { HANDSHAKE, FORWARD, UDP_FORWARD, - DESTROY + DESTROY, + ACTIVE_DISCONNECT } status; boost::asio::ssl::streamin_socket; boost::asio::ip::tcp::socket out_socket; From 3275c8fdbc26184eb04faa9a8bd43834f0125261 Mon Sep 17 00:00:00 2001 From: Chigusa0w0 <9378097+Chigusa0w0@users.noreply.github.com> Date: Wed, 1 Jun 2022 02:27:20 -0400 Subject: [PATCH 4/6] Add server-side active close mechanism This patch set fixes the behavior of Trojan not immediately attempting to close a frontend connection if the Trojan backend unexpectedly closed the connection. In some cases, an attacker can trick the backend into closing the connection immediately after sending valid data with carefully constructed contents. For connections that are not relayed by Trojan, the attack can observe the closure of the connection immediately. However, in scenarios where Trojan is present, the connection will be kept even after the attacker receives the aforementioned data. This difference in behavior can be used to detect the presence of Trojan. The behavioral difference does not result in the leak of confidential user data. --- src/session/serversession.cpp | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/src/session/serversession.cpp b/src/session/serversession.cpp index fd4bc981..a5a35760 100644 --- a/src/session/serversession.cpp +++ b/src/session/serversession.cpp @@ -67,6 +67,14 @@ void ServerSession::in_async_read() { auto self = shared_from_this(); in_socket.async_read_some(boost::asio::buffer(in_read_buf, MAX_LENGTH), [this, self](const boost::system::error_code error, size_t length) { if (error) { + if ((boost::asio::error::eof == error) || + (boost::asio::error::connection_reset == error) || + (boost::asio::error::operation_aborted == error)) + { + Log::log_with_endpoint(in_endpoint, "remote server actively closed the connection", Log::INFO); + status = ACTIVE_DISCONNECT; + } + destroy(); return; } @@ -330,6 +338,7 @@ void ServerSession::destroy() { if (status == DESTROY) { return; } + auto previous_status = status; status = DESTROY; Log::log_with_endpoint(in_endpoint, "disconnected, " + to_string(recv_len) + " bytes received, " + to_string(sent_len) + " bytes sent, lasted for " + to_string(time(nullptr) - start_time) + " seconds", Log::INFO); if (auth && !auth_password.empty()) { @@ -347,6 +356,11 @@ void ServerSession::destroy() { udp_socket.cancel(ec); udp_socket.close(ec); } + if (previous_status == ACTIVE_DISCONNECT) { + in_socket.next_layer().cancel(ec); + in_socket.next_layer().shutdown(tcp::socket::shutdown_both, ec); + in_socket.next_layer().close(ec); + } if (in_socket.next_layer().is_open()) { auto self = shared_from_this(); auto ssl_shutdown_cb = [this, self](const boost::system::error_code error) { From 3284d1a5574e6dad89e224b42b9390773ecf98a9 Mon Sep 17 00:00:00 2001 From: Syrone Wong Date: Fri, 3 Jun 2022 05:47:28 +0800 Subject: [PATCH 5/6] CI: windows: update openssl to 1.1.1o Signed-off-by: Syrone Wong --- azure-pipelines.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 0521fb80..cdda2615 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -37,8 +37,8 @@ stages: steps: - bash: | set -euo pipefail - curl -LO https://slproweb.com/download/Win64OpenSSL-1_1_1h.exe - powershell ".\\Win64OpenSSL-1_1_1h.exe /silent /sp- /suppressmsgboxes /DIR='C:\\Program Files\\OpenSSL-Win64'" + curl -LO https://slproweb.com/download/Win64OpenSSL-1_1_1o.exe + powershell ".\\Win64OpenSSL-1_1_1o.exe /silent /sp- /suppressmsgboxes /DIR='C:\\Program Files\\OpenSSL-Win64'" cmake -DBoost_INCLUDE_DIR="${BOOST_ROOT_1_72_0}/include" -DBoost_USE_STATIC_LIBS=ON -DOPENSSL_ROOT_DIR='C:/Program Files/OpenSSL-Win64' -DOPENSSL_USE_STATIC_LIBS=ON -DENABLE_MYSQL=OFF . cmake --build . --config Release - publish: $(System.DefaultWorkingDirectory)/Release/trojan.exe From 786008773cd854f5c45d3ae02f1df29081373819 Mon Sep 17 00:00:00 2001 From: abgr Date: Tue, 7 Feb 2023 01:04:39 +0330 Subject: [PATCH 6/6] impl no_auth --- src/core/config.cpp | 4 ++++ src/core/config.h | 1 + src/main.cpp | 3 +++ src/session/serversession.cpp | 32 ++++++++++++++++++++------------ 4 files changed, 28 insertions(+), 12 deletions(-) diff --git a/src/core/config.cpp b/src/core/config.cpp index 425f376a..95d65277 100644 --- a/src/core/config.cpp +++ b/src/core/config.cpp @@ -165,3 +165,7 @@ string Config::SHA224(const string &message) { EVP_MD_CTX_free(ctx); return string(mdString); } + +bool Config::no_auth() const { + return !mysql.enabled && password.empty(); +} \ No newline at end of file diff --git a/src/core/config.h b/src/core/config.h index d3fb0bd6..5406cb3c 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -87,6 +87,7 @@ class Config { void populate(const std::string &JSON); bool sip003(); static std::string SHA224(const std::string &message); + bool no_auth() const; private: void populate(const boost::property_tree::ptree &tree); }; diff --git a/src/main.cpp b/src/main.cpp index 99483403..97a5411f 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -146,6 +146,9 @@ int main(int argc, const char *argv[]) { } else { config.load(config_file); } + if (config.no_auth()){ + Log::log_with_date_time("no authentication method", Log::WARN); + } Service service(config, test); if (test) { Log::log("The config file looks good.", Log::OFF); diff --git a/src/session/serversession.cpp b/src/session/serversession.cpp index a5a35760..ea0820dc 100644 --- a/src/session/serversession.cpp +++ b/src/session/serversession.cpp @@ -145,19 +145,27 @@ void ServerSession::in_recv(const string &data) { TrojanRequest req; bool valid = req.parse(data) != -1; if (valid) { - auto password_iterator = config.password.find(req.password); - if (password_iterator == config.password.end()) { - valid = false; - if (auth && auth->auth(req.password)) { - valid = true; - auth_password = req.password; - Log::log_with_endpoint(in_endpoint, "authenticated by authenticator (" + req.password.substr(0, 7) + ')', Log::INFO); + if (config.no_auth()) { + Log::log_with_endpoint(in_endpoint, "authentication is disabled", Log::INFO); + }else{ + auto password_iterator = config.password.find(req.password); + if (password_iterator == config.password.end()) { + valid = false; + if (auth && auth->auth(req.password)) { + valid = true; + auth_password = req.password; + Log::log_with_endpoint(in_endpoint, + "authenticated by authenticator (" + req.password.substr(0, 7) + ')', + Log::INFO); + } + } else { + Log::log_with_endpoint(in_endpoint, "authenticated as " + password_iterator->second, Log::INFO); + } + if (!valid) { + Log::log_with_endpoint(in_endpoint, + "valid trojan request structure but possibly incorrect password (" + + req.password + ')', Log::WARN); } - } else { - Log::log_with_endpoint(in_endpoint, "authenticated as " + password_iterator->second, Log::INFO); - } - if (!valid) { - Log::log_with_endpoint(in_endpoint, "valid trojan request structure but possibly incorrect password (" + req.password + ')', Log::WARN); } } string query_addr = valid ? req.address.address : config.remote_addr;