Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion app/src/main/cpp/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ include_directories(src/)
include_directories(libs/fptn/src/)
include_directories(libs/fptn/src/fptn-protocol-lib)

include(libs/fptn/depends/cmake/CamouflageTLS.cmake) # FIXME

# disable pcap++
add_compile_definitions(FPTN_IP_ADDRESS_WITHOUT_PCAP)

Expand All @@ -47,7 +49,9 @@ target_link_libraries(
android
log
fptn::fptn
nlohmann_json::nlohmann_json)
nlohmann_json::nlohmann_json
camouflage-tls # FIXME
)

target_compile_definitions(${CMAKE_PROJECT_NAME} PRIVATE FPTN_VERSION=\"0.0.0\")
set_target_properties(
Expand Down
3 changes: 3 additions & 0 deletions app/src/main/cpp/conanfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ class FptnLib(ConanFile):
def requirements(self):
self._register_local_recipe("fptn", "fptn", "0.0.0")

def build_requirements(self):
self.test_requires("gtest/1.17.0")

def layout(self):
cmake_layout(self)

Expand Down
2 changes: 1 addition & 1 deletion app/src/main/cpp/libs/fptn
Submodule fptn updated from 4baae5 to 0c0ca3
27 changes: 26 additions & 1 deletion app/src/main/cpp/src/https_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -111,9 +111,34 @@ Java_org_fptn_vpn_services_websocket_NativeHttpsClientImpl_nativeCreate(
fptn::protocol::https::CensorshipStrategy::kSni;
if (censorship_strategy_name == "OBFUSCATION") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kTlsObfuscator;
} else if (censorship_strategy_name == "SNI-REALITY") {
} else if (censorship_strategy_name == "SNI-REALITY") { // deprecated
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityMode;
}
/* Chrome */
else if (censorship_strategy_name == "SNI-REALITY-CHROME-147") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome147;
} else if (censorship_strategy_name == "SNI-REALITY-CHROME-146") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome146;
} else if (censorship_strategy_name == "SNI-REALITY-CHROME-145") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome145;
}
/* Firefox */
else if (censorship_strategy_name == "SNI-REALITY-FIREFOX-149") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeFirefox149;
}
/* Yandex */
else if (censorship_strategy_name == "SNI-REALITY-YANDEX-26") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeYandex26;
} else if (censorship_strategy_name == "SNI-REALITY-YANDEX-25") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeYandex25;
} else if (censorship_strategy_name == "SNI-REALITY-YANDEX-24") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeYandex24;
}
/* Safari */
else if (censorship_strategy_name == "SNI-REALITY-SAFARI-26") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeSafari26;
}


auto* https_client = new WrapperHttpsClient(env, global_object_ref,
std::move(host), port, std::move(sni), std::move(md5_fingerprint), censorship_strategy);
Expand Down
26 changes: 25 additions & 1 deletion app/src/main/cpp/src/websocket_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,33 @@ Java_org_fptn_vpn_services_websocket_NativeWebSocketClientImpl_nativeCreate(
fptn::protocol::https::CensorshipStrategy::kSni;
if (censorship_strategy_name == "OBFUSCATION") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kTlsObfuscator;
} else if (censorship_strategy_name == "SNI-REALITY") {
} else if (censorship_strategy_name == "SNI-REALITY") { // deprecated
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityMode;
}
/* Chrome */
else if (censorship_strategy_name == "SNI-REALITY-CHROME-147") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome147;
} else if (censorship_strategy_name == "SNI-REALITY-CHROME-146") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome146;
} else if (censorship_strategy_name == "SNI-REALITY-CHROME-145") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeChrome145;
}
/* Firefox */
else if (censorship_strategy_name == "SNI-REALITY-FIREFOX-149") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeFirefox149;
}
/* Yandex */
else if (censorship_strategy_name == "SNI-REALITY-YANDEX-26") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeYandex26;
} else if (censorship_strategy_name == "SNI-REALITY-YANDEX-25") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeYandex25;
} else if (censorship_strategy_name == "SNI-REALITY-YANDEX-24") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeYandex24;
}
/* Safari */
else if (censorship_strategy_name == "SNI-REALITY-SAFARI-26") {
censorship_strategy = fptn::protocol::https::CensorshipStrategy::kSniRealityModeSafari26;
}

jobject global_object_ref = env->NewWeakGlobalRef(thiz);
auto* websocket_client = new WrapperWebsocketClient(global_object_ref,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -311,9 +311,12 @@ bool WrapperWebsocketClient::Send(std::string pkt) {
if (!running_) {
return false;
}

try {
auto ip_packet = fptn::common::network::IPPacket::Parse(std::move(pkt));
std::vector<uint8_t> packet_data;
packet_data.reserve(pkt.size());
std::move(pkt.begin(), pkt.end(), std::back_inserter(packet_data));

auto ip_packet = fptn::common::network::IPPacket::Parse(std::move(packet_data));
if (!ip_packet) {
SPDLOG_ERROR("Failed to parse IP packet in Send");
return false;
Expand Down
16 changes: 14 additions & 2 deletions app/src/main/java/org/fptn/vpn/enums/BypassCensorshipMethod.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,19 @@
package org.fptn.vpn.enums;

public enum BypassCensorshipMethod {
SNI_SPOOFING,
SNI_SPOOFING, // deprecated
TLS_OBFUSCATION,
SNI_REALITY
SNI_REALITY, // deprecated
/* Chrome */
SNI_REALITY_CHROME_147,
SNI_REALITY_CHROME_146,
SNI_REALITY_CHROME_145,
/* Firefox */
SNI_REALITY_FIREFOX_149,
/* Yandex Browser */
SNI_REALITY_YANDEX_26,
SNI_REALITY_YANDEX_25,
SNI_REALITY_YANDEX_24,
/* Safari */
SNI_REALITY_SAFARI_26
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,15 +36,12 @@ public NativeSpeedTestTask(ServerEntity serverEntity, String sniHost, BypassCens
@Override
public NativeSpeedTestResult call() throws PVNClientException {
Instant start = Instant.now();
Log.d(getTag(), "call() start test: " + serverEntity.getName());
NativeResponse response = nativeHttpsClient.Get(GET_FILE_PATH, TIMEOUT);
if (response.code == 200) {
Instant end = Instant.now();
long durationsMillis = Duration.between(start, end).toMillis();
Log.d(getTag(), "call() end test: " + serverEntity.getName() + " duration: " + durationsMillis + " ms");
return new NativeSpeedTestResult(serverEntity, durationsMillis);
} else {
Log.d(getTag(), "call() end test: " + serverEntity.getName() + " error: " + response.errorMessage);
throw new PVNClientException(response.errorMessage);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,36 @@ public NativeHttpsClientImpl(String serverIP,
String md5Fingerprint,
String sni,
BypassCensorshipMethod censorshipStrategy) {
String censorshipStrategyName = "SNI";
String censorshipStrategyName = "SNI-REALITY-YANDEX-25";
if (censorshipStrategy == BypassCensorshipMethod.TLS_OBFUSCATION) {
censorshipStrategyName = "OBFUSCATION";
} else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY) {
} else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY) { // deprecated
censorshipStrategyName = "SNI-REALITY";
}

/* Chrome */
else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY_CHROME_147) {
censorshipStrategyName = "SNI-REALITY-CHROME-147";
} else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY_CHROME_146) {
censorshipStrategyName = "SNI-REALITY-CHROME-146";
} else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY_CHROME_145) {
censorshipStrategyName = "SNI-REALITY-CHROME-145";
}
/* Firefox */
else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY_FIREFOX_149) {
censorshipStrategyName = "SNI-REALITY-FIREFOX-149";
}
/* Yandex */
else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY_YANDEX_26) {
censorshipStrategyName = "SNI-REALITY-YANDEX-26";
} else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY_YANDEX_25) {
censorshipStrategyName = "SNI-REALITY-YANDEX-25";
} else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY_YANDEX_24) {
censorshipStrategyName = "SNI-REALITY-YANDEX-24";
}
/* Safari */
else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY_SAFARI_26) {
censorshipStrategyName = "SNI-REALITY-SAFARI-26";
}
this.nativeHandle = nativeCreate(
serverIP,
serverPort,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,16 +39,40 @@ public NativeWebSocketClientImpl(
OnMessageReceivedCallback onMessageReceivedCallback,
OnFailureCallback onFailureCallback,
String sniHostName,
BypassCensorshipMethod censorship_strategy) throws PVNClientException {
BypassCensorshipMethod censorshipStrategy) throws PVNClientException {
this.onOpenCallback = onOpenCallback;
this.onMessageReceivedCallback = onMessageReceivedCallback;
this.onFailureCallback = onFailureCallback;

String censorship_strategy_name = "SNI";
if (censorship_strategy == BypassCensorshipMethod.TLS_OBFUSCATION) {
censorship_strategy_name = "OBFUSCATION";
} else if (censorship_strategy == BypassCensorshipMethod.SNI_REALITY) {
censorship_strategy_name = "SNI-REALITY";
String censorshipStrategyName = "SNI-REALITY-YANDEX-25";
if (censorshipStrategy == BypassCensorshipMethod.TLS_OBFUSCATION) {
censorshipStrategyName = "OBFUSCATION";
} else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY) { // deprecated
censorshipStrategyName = "SNI-REALITY";
}
/* Chrome */
else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY_CHROME_147) {
censorshipStrategyName = "SNI-REALITY-CHROME-147";
} else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY_CHROME_146) {
censorshipStrategyName = "SNI-REALITY-CHROME-146";
} else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY_CHROME_145) {
censorshipStrategyName = "SNI-REALITY-CHROME-145";
}
/* Firefox */
else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY_FIREFOX_149) {
censorshipStrategyName = "SNI-REALITY-FIREFOX-149";
}
/* Yandex */
else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY_YANDEX_26) {
censorshipStrategyName = "SNI-REALITY-YANDEX-26";
} else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY_YANDEX_25) {
censorshipStrategyName = "SNI-REALITY-YANDEX-25";
} else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY_YANDEX_24) {
censorshipStrategyName = "SNI-REALITY-YANDEX-24";
}
/* Safari */
else if (censorshipStrategy == BypassCensorshipMethod.SNI_REALITY_SAFARI_26) {
censorshipStrategyName = "SNI-REALITY-SAFARI-26";
}

this.nativeHandle = nativeCreate(
Expand All @@ -59,7 +83,7 @@ public NativeWebSocketClientImpl(
sniHostName,
accessToken,
md5ServerFingerprint,
censorship_strategy_name
censorshipStrategyName
);

this.serialNum = SERIAL_NUM.getAndIncrement();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@

public class BypassMethodsActivity extends AppCompatActivity {
private final String TAG = this.getClass().getSimpleName();

private View sniLayout;

private BypassMethodsViewModel viewModel;
private ActivityResultLauncher<Intent> filePickerLauncher;
private AlertDialog autoSelectDialog;
Expand Down Expand Up @@ -113,35 +116,107 @@ private void initializeVariable() {
// Setup RadioGroup listener
RadioGroup protocolRadioGroup = findViewById(R.id.bypass_method_radio_button_group);
protocolRadioGroup.setOnCheckedChangeListener((group, checkedId) -> {
if (checkedId == R.id.sni_spoofing_radio_button) {
Log.d(TAG, "Selected SNI spoofing");
viewModel.setBypassMethod(BypassCensorshipMethod.SNI_SPOOFING);
} else if (checkedId == R.id.obfuscation_radio_button) {
if (checkedId == R.id.obfuscation_radio_button) {
Log.d(TAG, "Selected TLS obfuscation");
viewModel.setBypassMethod(BypassCensorshipMethod.TLS_OBFUSCATION);
} else if (checkedId == R.id.sni_reality_radio_button) {
Log.d(TAG, "Selected SNI Reality");
viewModel.setBypassMethod(BypassCensorshipMethod.SNI_REALITY);
}
/* Chrome */
else if (checkedId == R.id.sni_reality_radio_button_chrome_147) {
Log.d(TAG, "Selected SNI Reality Chrome 147");
viewModel.setBypassMethod(BypassCensorshipMethod.SNI_REALITY_CHROME_147);
} else if (checkedId == R.id.sni_reality_radio_button_chrome_146) {
Log.d(TAG, "Selected SNI Reality Chrome 146");
viewModel.setBypassMethod(BypassCensorshipMethod.SNI_REALITY_CHROME_146);
} else if (checkedId == R.id.sni_reality_radio_button_chrome_145) {
Log.d(TAG, "Selected SNI Reality Chrome 145");
viewModel.setBypassMethod(BypassCensorshipMethod.SNI_REALITY_CHROME_145);
}
/* Firefox */
else if (checkedId == R.id.sni_reality_radio_button_firefox_149) {
Log.d(TAG, "Selected SNI Reality Firefox 149");
viewModel.setBypassMethod(BypassCensorshipMethod.SNI_REALITY_FIREFOX_149);
}
/* Yandex */
else if (checkedId == R.id.sni_reality_radio_button_yandex_26) {
Log.d(TAG, "Selected SNI Reality Yandex 26");
viewModel.setBypassMethod(BypassCensorshipMethod.SNI_REALITY_YANDEX_26);
} else if (checkedId == R.id.sni_reality_radio_button_yandex_25) {
Log.d(TAG, "Selected SNI Reality Yandex 25");
viewModel.setBypassMethod(BypassCensorshipMethod.SNI_REALITY_YANDEX_25);
} else if (checkedId == R.id.sni_reality_radio_button_yandex_24) {
Log.d(TAG, "Selected SNI Reality Yandex 24");
viewModel.setBypassMethod(BypassCensorshipMethod.SNI_REALITY_YANDEX_24);
}
/* Safari */
else if (checkedId == R.id.sni_reality_radio_button_safari_26) {
Log.d(TAG, "Selected SNI Reality Safari 26");
viewModel.setBypassMethod(BypassCensorshipMethod.SNI_REALITY_SAFARI_26);
} else {
// default
viewModel.setBypassMethod(BypassCensorshipMethod.SNI_REALITY_YANDEX_25);
}
});

View sniLayout = findViewById(R.id.sni_layout);

RadioButton sniSpoofingRadioButton = findViewById(R.id.sni_spoofing_radio_button);
RadioButton obfuscationRadioButton = findViewById(R.id.obfuscation_radio_button);
RadioButton sniRealityRadioButton = findViewById(R.id.sni_reality_radio_button);

RadioButton sniRealityRadioButtonChrome147 = findViewById(R.id.sni_reality_radio_button_chrome_147);
RadioButton sniRealityRadioButtonChrome146 = findViewById(R.id.sni_reality_radio_button_chrome_146);
RadioButton sniRealityRadioButtonChrome145 = findViewById(R.id.sni_reality_radio_button_chrome_145);

RadioButton sniRealityRadioButtonFirefox149 = findViewById(R.id.sni_reality_radio_button_firefox_149);

RadioButton sniRealityRadioButtonYandex26 = findViewById(R.id.sni_reality_radio_button_yandex_26);
RadioButton sniRealityRadioButtonYandex25 = findViewById(R.id.sni_reality_radio_button_yandex_25);
RadioButton sniRealityRadioButtonYandex24 = findViewById(R.id.sni_reality_radio_button_yandex_24);

RadioButton sniRealityRadioButtonSafari26 = findViewById(R.id.sni_reality_radio_button_safari_26);

viewModel.getBypassCensorshipMethodMutableLiveData().observe(this, bypassCensorshipMethod -> {
switch (bypassCensorshipMethod) {
case SNI_SPOOFING:
sniSpoofingRadioButton.setChecked(true);
ViewUtils.showView(sniLayout);
break;
case TLS_OBFUSCATION:
obfuscationRadioButton.setChecked(true);
ViewUtils.hideView(sniLayout);
break;
case SNI_REALITY:
sniRealityRadioButton.setChecked(true);
case SNI_SPOOFING: // deprecated
case SNI_REALITY: // deprecated
/* Yandex */
case SNI_REALITY_YANDEX_25:
sniRealityRadioButtonYandex25.setChecked(true);
ViewUtils.showView(sniLayout);
break;
case SNI_REALITY_YANDEX_26:
sniRealityRadioButtonYandex26.setChecked(true);
ViewUtils.showView(sniLayout);
break;
case SNI_REALITY_YANDEX_24:
sniRealityRadioButtonYandex24.setChecked(true);
ViewUtils.showView(sniLayout);
break;
/* Chrome */
case SNI_REALITY_CHROME_147:
sniRealityRadioButtonChrome147.setChecked(true);
ViewUtils.showView(sniLayout);
break;
case SNI_REALITY_CHROME_146:
sniRealityRadioButtonChrome146.setChecked(true);
ViewUtils.showView(sniLayout);
break;
case SNI_REALITY_CHROME_145:
sniRealityRadioButtonChrome145.setChecked(true);
ViewUtils.showView(sniLayout);
break;
/* Firefox */
case SNI_REALITY_FIREFOX_149:
sniRealityRadioButtonFirefox149.setChecked(true);
ViewUtils.showView(sniLayout);
break;
/* Safari */
case SNI_REALITY_SAFARI_26:
sniRealityRadioButtonSafari26.setChecked(true);
ViewUtils.showView(sniLayout);
break;
default:
sniRealityRadioButtonYandex25.setChecked(true);
ViewUtils.showView(sniLayout);
break;
}
Expand Down
Loading