diff --git a/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java b/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java
index 2cee4f09..5656d13a 100644
--- a/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java
+++ b/app/src/main/java/com/emanuelef/remote_capture/CaptureService.java
@@ -29,8 +29,6 @@ import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.Network;
import android.net.NetworkCapabilities;
@@ -49,7 +47,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.RequiresApi;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
-import androidx.core.content.ContextCompat;
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
import androidx.preference.PreferenceManager;
@@ -77,13 +74,13 @@ public class CaptureService extends VpnService implements Runnable {
private String vpn_dns;
private String dns_server;
private String collector_address;
- private String tls_proxy_address;
+ private String socks5_proxy_address;
private Prefs.DumpMode dump_mode;
- private boolean tls_decryption_enabled;
+ private boolean socks5_enabled;
private boolean ipv6_enabled;
private int collector_port;
private int http_server_port;
- private int tls_proxy_port;
+ private int socks5_proxy_port;
private long last_bytes;
private int last_connections;
private static CaptureService INSTANCE;
@@ -186,9 +183,9 @@ public class CaptureService extends VpnService implements Runnable {
collector_address = Prefs.getCollectorIp(prefs);
collector_port = Prefs.getCollectorPort(prefs);
http_server_port = Prefs.getHttpServerPort(prefs);
- tls_decryption_enabled = Prefs.getTlsDecryptionEnabled(prefs);
- tls_proxy_address = Prefs.getTlsProxyAddress(prefs);
- tls_proxy_port = Prefs.getTlsProxyPort(prefs);
+ socks5_enabled = Prefs.getTlsDecryptionEnabled(prefs); // TODO rename
+ socks5_proxy_address = Prefs.getSocks5ProxyAddress(prefs);
+ socks5_proxy_port = Prefs.getSocks5ProxyPort(prefs);
dump_mode = Prefs.getDumpMode(prefs);
ipv6_enabled = Prefs.getIPv6Enabled(prefs);
last_bytes = 0;
@@ -541,11 +538,11 @@ public class CaptureService extends VpnService implements Runnable {
return(collector_port);
}
- public String getTlsProxyAddress() { return(tls_proxy_address); }
+ public String getSocks5ProxyAddress() { return(socks5_proxy_address); }
- public int getTlsDecryptionEnabled() { return tls_decryption_enabled ? 1 : 0; }
+ public int getSocks5Enabled() { return socks5_enabled ? 1 : 0; }
- public int getTlsProxyPort() { return(tls_proxy_port); }
+ public int getSocks5ProxyPort() { return(socks5_proxy_port); }
public int getIPv6Enabled() { return(ipv6_enabled ? 1 : 0); }
diff --git a/app/src/main/java/com/emanuelef/remote_capture/activities/SettingsActivity.java b/app/src/main/java/com/emanuelef/remote_capture/activities/SettingsActivity.java
index 9e25ddae..d956f3bc 100644
--- a/app/src/main/java/com/emanuelef/remote_capture/activities/SettingsActivity.java
+++ b/app/src/main/java/com/emanuelef/remote_capture/activities/SettingsActivity.java
@@ -82,9 +82,9 @@ public class SettingsActivity extends BaseActivity {
}
public static class SettingsFragment extends PreferenceFragmentCompat {
- private SwitchPreference mTlsDecryptionEnabled;
- private EditTextPreference mTlsProxyIp;
- private EditTextPreference mTlsProxyPort;
+ private SwitchPreference mTlsDecryptionEnabled; // TODO rename
+ private EditTextPreference mSocks5ProxyIp;
+ private EditTextPreference mSocks5ProxyPort;
private Preference mTlsHelp;
@Override
@@ -93,10 +93,10 @@ public class SettingsActivity extends BaseActivity {
setupUdpExporterPrefs();
setupHttpServerPrefs();
- setupTlsProxyPrefs();
+ setupSocks5ProxyPrefs();
setupOtherPrefs();
- tlsDecryptionHideShow(mTlsDecryptionEnabled.isChecked());
+ socks5ProxyHideShow(mTlsDecryptionEnabled.isChecked());
}
private boolean validatePort(String value) {
@@ -128,32 +128,35 @@ public class SettingsActivity extends BaseActivity {
mHttpServerPort.setOnPreferenceChangeListener((preference, newValue) -> validatePort(newValue.toString()));
}
- private void setupTlsProxyPrefs() {
+ private void setupSocks5ProxyPrefs() {
mTlsHelp = findPreference("tls_how_to");
mTlsDecryptionEnabled = findPreference(Prefs.PREF_TLS_DECRYPTION_ENABLED_KEY);
mTlsDecryptionEnabled.setOnPreferenceChangeListener((preference, newValue) -> {
- tlsDecryptionHideShow((Boolean) newValue);
+ socks5ProxyHideShow((Boolean) newValue);
return true;
});
/* TLS Proxy IP validation */
- mTlsProxyIp = findPreference(Prefs.PREF_TLS_PROXY_IP_KEY);
- mTlsProxyIp.setOnPreferenceChangeListener((preference, newValue) -> {
+ mSocks5ProxyIp = findPreference(Prefs.PREF_SOCKS5_PROXY_IP_KEY);
+ mSocks5ProxyIp.setOnPreferenceChangeListener((preference, newValue) -> {
Matcher matcher = Patterns.IP_ADDRESS.matcher(newValue.toString());
return(matcher.matches());
});
/* TLS Proxy port validation */
- mTlsProxyPort = findPreference(Prefs.PREF_TLS_PROXY_PORT_KEY);
- mTlsProxyPort.setOnBindEditTextListener(editText -> editText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED));
- mTlsProxyPort.setOnPreferenceChangeListener((preference, newValue) -> validatePort(newValue.toString()));
+ mSocks5ProxyPort = findPreference(Prefs.PREF_SOCKS5_PROXY_PORT_KEY);
+ mSocks5ProxyPort.setOnBindEditTextListener(editText -> editText.setInputType(InputType.TYPE_CLASS_NUMBER | InputType.TYPE_NUMBER_FLAG_SIGNED));
+ mSocks5ProxyPort.setOnPreferenceChangeListener((preference, newValue) -> validatePort(newValue.toString()));
}
- private void tlsDecryptionHideShow(boolean decryptionEnabled) {
- mTlsProxyIp.setVisible(decryptionEnabled);
- mTlsProxyPort.setVisible(decryptionEnabled);
- mTlsHelp.setVisible(decryptionEnabled);
+ private void socks5ProxyHideShow(boolean decryptionEnabled) {
+ mSocks5ProxyIp.setVisible(decryptionEnabled);
+ mSocks5ProxyPort.setVisible(decryptionEnabled);
+
+ // TODO
+ //mTlsHelp.setVisible(decryptionEnabled);
+ mTlsHelp.setVisible(false);
}
private void setupOtherPrefs() {
diff --git a/app/src/main/java/com/emanuelef/remote_capture/model/Prefs.java b/app/src/main/java/com/emanuelef/remote_capture/model/Prefs.java
index 5b691984..109eb1c7 100644
--- a/app/src/main/java/com/emanuelef/remote_capture/model/Prefs.java
+++ b/app/src/main/java/com/emanuelef/remote_capture/model/Prefs.java
@@ -29,8 +29,8 @@ public class Prefs {
public static final String DUMP_PCAP_FILE = "pcap_file";
public static final String PREF_COLLECTOR_IP_KEY = "collector_ip_address";
public static final String PREF_COLLECTOR_PORT_KEY = "collector_port";
- public static final String PREF_TLS_PROXY_IP_KEY = "tls_proxy_ip_address";
- public static final String PREF_TLS_PROXY_PORT_KEY = "tls_proxy_port";
+ public static final String PREF_SOCKS5_PROXY_IP_KEY = "socks5_proxy_ip_address";
+ public static final String PREF_SOCKS5_PROXY_PORT_KEY = "socks5_proxy_port";
public static final String PREF_TLS_DECRYPTION_ENABLED_KEY = "tls_decryption_enabled";
public static final String PREF_APP_FILTER = "app_filter";
public static final String PREF_HTTP_SERVER_PORT = "http_server_port";
@@ -65,8 +65,8 @@ public class Prefs {
public static DumpMode getDumpMode(SharedPreferences p) { return(getDumpMode(p.getString(PREF_PCAP_DUMP_MODE, DEFAULT_DUMP_MODE))); }
public static int getHttpServerPort(SharedPreferences p) { return(Integer.parseInt(p.getString(Prefs.PREF_HTTP_SERVER_PORT, "8080"))); }
public static boolean getTlsDecryptionEnabled(SharedPreferences p) { return(p.getBoolean(PREF_TLS_DECRYPTION_ENABLED_KEY, false)); }
- public static String getTlsProxyAddress(SharedPreferences p) { return(p.getString(PREF_TLS_PROXY_IP_KEY, "0.0.0.0")); }
- public static int getTlsProxyPort(SharedPreferences p) { return(Integer.parseInt(p.getString(Prefs.PREF_TLS_PROXY_PORT_KEY, "8080"))); }
+ public static String getSocks5ProxyAddress(SharedPreferences p) { return(p.getString(PREF_SOCKS5_PROXY_IP_KEY, "0.0.0.0")); }
+ public static int getSocks5ProxyPort(SharedPreferences p) { return(Integer.parseInt(p.getString(Prefs.PREF_SOCKS5_PROXY_PORT_KEY, "8080"))); }
public static String getAppFilter(SharedPreferences p) { return(p.getString(PREF_APP_FILTER, "")); }
public static boolean getIPv6Enabled(SharedPreferences p) { return(p.getBoolean(PREF_IPV6_ENABLED, false)); }
public static boolean useEnglishLanguage(SharedPreferences p){ return("english".equals(p.getString(PREF_APP_LANGUAGE, "system")));}
diff --git a/app/src/main/jni/vpnproxy-jni/vpnproxy.c b/app/src/main/jni/vpnproxy-jni/vpnproxy.c
index be15f5f1..72bc989b 100644
--- a/app/src/main/jni/vpnproxy-jni/vpnproxy.c
+++ b/app/src/main/jni/vpnproxy-jni/vpnproxy.c
@@ -54,13 +54,6 @@ typedef struct dns_packet {
/* ******************************************************* */
-typedef struct mitm_proxy_hdr {
- uint32_t dst_ip;
- uint16_t dst_port;
-} __attribute__((packed)) mitm_proxy_hdr_t;
-
-/* ******************************************************* */
-
typedef struct jni_methods {
jmethodID getApplicationByUid;
jmethodID protect;
@@ -90,23 +83,6 @@ static bool dump_capture_stats_now = false;
static ndpi_protocol_bitmask_struct_t masterProtos;
static uint32_t new_dns_server = 0;
-/* TCP/IP packet to hold the mitmproxy header */
-static char mitmproxy_pkt_buffer[] = {
- "\x45\x00" \
-
- /* Total length: 52 + 6 (sizeof mitm_proxy_hdr_t) */
- "\x00\x3a" \
-
- "\xb8\x9e\x40\x00\x40\x06\xf7\xe1\x00\x00\x00\x00\x00\x00" \
- "\x00\x00\x00\x00\x00\x00\x65\xbf\xc2\xaf\x08\x93\x36\x09\x80\x18" \
- "\x01\xf5\x00\x00\x00\x00\x01\x01\x08\x0a\x6c\xe2\x4f\x95\x4a\xe0" \
- "\x92\x51" \
-
- /* TCP payload */
- "\x01\x02\x03\x04\x05\x06"
-};
-static zdtun_pkt_t mitm_pkt;
-
/* ******************************************************* */
/* NOTE: these must be reset during each run, as android may reuse the service */
@@ -742,49 +718,14 @@ static bool check_dns_req_allowed(struct vpnproxy_data *proxy, zdtun_conn_t *con
/* ******************************************************* */
-/*
- * Check if the packet should be redirected to the mitmproxy
- */
-static void check_tls_mitm(zdtun_t *tun, struct vpnproxy_data *proxy, zdtun_pkt_t *pkt, zdtun_conn_t *conn) {
+static void check_socks5_redirection(zdtun_t *tun, struct vpnproxy_data *proxy, zdtun_pkt_t *pkt, zdtun_conn_t *conn) {
conn_data_t *data = zdtun_conn_get_userdata(conn);
if(shouldIgnoreConn(proxy, zdtun_conn_get_5tuple(conn), data))
return;
- if(pkt->tuple.ipproto == IPPROTO_TCP) {
- uint32_t mitm_ip = proxy->tls_decryption.proxy_ip;
- uint16_t mitm_port = proxy->tls_decryption.proxy_port;
-
- bool is_new = ((data->sent_pkts + data->rcvd_pkts) == 0);
-
- if(is_new) {
- uint16_t port = ntohs(pkt->tuple.dst_port);
-
- if (port == 443) {
- zdtun_ip_t dnatip = {0};
- dnatip.ip4 = mitm_ip;
- zdtun_conn_dnat(conn, &dnatip, mitm_port);
- data->mitm_header_needed = true;
- }
- } else if(data->mitm_header_needed && (pkt->l7_len > 0) && (pkt->tuple.ipver == 4)) {
- // TODO allow IPv6 -> IPv4 redirection
- /* First L7 packet, send the mitmproxy header first */
- mitm_proxy_hdr_t *mitm = (mitm_proxy_hdr_t*) mitm_pkt.l7;
-
- /* Fix the packet with the correct peers */
- mitm_pkt.tuple.src_ip.ip4 = mitm_pkt.ip4->saddr = pkt->ip4->saddr;
- mitm_pkt.tuple.dst_ip.ip4 = mitm_pkt.ip4->daddr = mitm_ip;
- mitm_pkt.tuple.src_port = mitm_pkt.tcp->th_sport = pkt->tcp->th_sport;
- mitm_pkt.tuple.dst_port = mitm_pkt.tcp->th_dport = mitm_port;
-
- /* Send the original (pre-nat) IP and port */
- mitm->dst_ip = pkt->tuple.dst_ip.ip4;
- mitm->dst_port = pkt->tuple.dst_port;
- zdtun_send_oob(tun, &mitm_pkt, conn);
-
- data->mitm_header_needed = false;
- }
- }
+ if((pkt->tuple.ipproto == IPPROTO_TCP) && (((data->sent_pkts + data->rcvd_pkts) == 0)))
+ zdtun_conn_proxy(conn);
}
/* ******************************************************* */
@@ -1034,8 +975,6 @@ static int run_tun(JNIEnv *env, jclass vpn, int tunfd, jint sdk) {
init_log(ANDROID_LOG_DEBUG, env, vpn_class, vpn);
- zdtun_parse_pkt(mitmproxy_pkt_buffer, sizeof(mitmproxy_pkt_buffer)-1, &mitm_pkt);
-
/* Classes */
cls.vpn_service = vpn_class;
cls.conn = jniFindClass(env, "com/emanuelef/remote_capture/model/ConnectionDescriptor");
@@ -1076,10 +1015,10 @@ static int run_tun(JNIEnv *env, jclass vpn, int tunfd, jint sdk) {
.tcp_socket = false,
.enabled = (bool) getIntPref(env, vpn, "dumpPcapToUdp"),
},
- .tls_decryption = {
- .enabled = (bool) getIntPref(env, vpn, "getTlsDecryptionEnabled"),
- .proxy_ip = getIPv4Pref(env, vpn, "getTlsProxyAddress"),
- .proxy_port = htons(getIntPref(env, vpn, "getTlsProxyPort")),
+ .socks5 = {
+ .enabled = (bool) getIntPref(env, vpn, "getSocks5Enabled"),
+ .proxy_ip = getIPv4Pref(env, vpn, "getSocks5ProxyAddress"),
+ .proxy_port = htons(getIntPref(env, vpn, "getSocks5ProxyPort")),
},
.ipv6 = {
.enabled = (bool) getIntPref(env, vpn, "getIPv6Enabled"),
@@ -1161,6 +1100,12 @@ static int run_tun(JNIEnv *env, jclass vpn, int tunfd, jint sdk) {
}
}
+ if(proxy.socks5.enabled) {
+ zdtun_ip_t dnatip = {0};
+ dnatip.ip4 = proxy.socks5.proxy_ip;
+ zdtun_set_socks5_proxy(tun, &dnatip, proxy.socks5.proxy_port);
+ }
+
new_dns_server = 0;
gettimeofday(&now_tv, NULL);
now_ms = now_tv.tv_sec * 1000 + now_tv.tv_usec / 1000;
@@ -1235,8 +1180,8 @@ static int run_tun(JNIEnv *env, jclass vpn, int tunfd, jint sdk) {
goto housekeeping;
}
- if(proxy.tls_decryption.enabled)
- check_tls_mitm(tun, &proxy, &pkt, conn);
+ if(proxy.socks5.enabled)
+ check_socks5_redirection(tun, &proxy, &pkt, conn);
if((rc = zdtun_forward(tun, &pkt, conn)) != 0) {
char buf[512];
diff --git a/app/src/main/jni/vpnproxy-jni/vpnproxy.h b/app/src/main/jni/vpnproxy-jni/vpnproxy.h
index 41498428..de46038a 100644
--- a/app/src/main/jni/vpnproxy-jni/vpnproxy.h
+++ b/app/src/main/jni/vpnproxy-jni/vpnproxy.h
@@ -57,7 +57,6 @@ typedef struct conn_data {
char *url;
jint uid;
bool pending_notification;
- bool mitm_header_needed;
} conn_data_t;
typedef struct vpn_conn {
@@ -110,7 +109,7 @@ typedef struct vpnproxy_data {
bool enabled;
u_int32_t proxy_ip;
u_int32_t proxy_port;
- } tls_decryption;
+ } socks5;
struct {
bool enabled;
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
index fd36c264..3f87b1f2 100644
--- a/app/src/main/res/values/strings.xml
+++ b/app/src/main/res/values/strings.xml
@@ -121,5 +121,10 @@
Light
Dark
Theme
+ Enable SOCKS5 Proxy
+ When enabled, all the TCP connections will be redirected to the specified SOCKS5 proxy.
+ Proxy
+ Proxy IP Address
+ Proxy Port
diff --git a/app/src/main/res/xml/root_preferences.xml b/app/src/main/res/xml/root_preferences.xml
index 2a4847a6..52efec28 100644
--- a/app/src/main/res/xml/root_preferences.xml
+++ b/app/src/main/res/xml/root_preferences.xml
@@ -43,12 +43,12 @@
app:useSimpleSummaryProvider="true" />
-
+
diff --git a/submodules/zdtun b/submodules/zdtun
index a29c548a..e5d24d18 160000
--- a/submodules/zdtun
+++ b/submodules/zdtun
@@ -1 +1 @@
-Subproject commit a29c548af21f5e09a6111f3c08b7f8edf804991b
+Subproject commit e5d24d18cad9ee460900955ec7cb12b32df0b7c2