Merge branch 'master' into dev

This commit is contained in:
emanuele-f 2021-02-19 14:40:18 +01:00
commit 8d508b7cd1
7 changed files with 130 additions and 34 deletions

View File

@ -28,6 +28,7 @@ import android.net.ConnectivityManager;
import android.net.VpnService;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.widget.Toast;
@ -46,6 +47,7 @@ public class CaptureService extends VpnService implements Runnable {
private static final String TAG = "CaptureService";
private static final String VpnSessionName = "PCAPdroid VPN";
private ParcelFileDescriptor mParcelFileDescriptor = null;
private Handler mHandler;
private Thread mThread;
private String vpn_ipv4;
private String vpn_dns;
@ -103,6 +105,8 @@ public class CaptureService extends VpnService implements Runnable {
public int onStartCommand(Intent intent, int flags, int startId) {
Context app_ctx = getApplicationContext();
mHandler = new Handler();
if (intent == null) {
Log.d(CaptureService.TAG, "NULL intent onStartCommand");
return super.onStartCommand(null, flags, startId);
@ -289,10 +293,12 @@ public class CaptureService extends VpnService implements Runnable {
public void run() {
if(mParcelFileDescriptor != null) {
int fd = mParcelFileDescriptor.getFd();
int fd_setsize = getFdSetSize();
if(fd > 0)
if((fd > 0) && (fd < fd_setsize)) {
Log.d(TAG, "VPN fd: " + fd + " - FD_SETSIZE: " + fd_setsize);
runPacketLoop(fd, this, Build.VERSION.SDK_INT);
else
} else
Log.e(TAG, "Invalid VPN fd: " + fd);
}
}
@ -401,7 +407,14 @@ public class CaptureService extends VpnService implements Runnable {
mHttpServer.pushData(data);
}
public void reportError(String msg) {
mHandler.post(() -> {
Toast.makeText(this, msg, Toast.LENGTH_LONG).show();
});
}
public static native void runPacketLoop(int fd, CaptureService vpn, int sdk);
public static native void stopPacketLoop();
public static native void askStatsDump();
public static native int getFdSetSize();
}

View File

@ -175,6 +175,9 @@ public class Utils {
if(connInfo != null) {
int ipAddress = connInfo.getIpAddress();
if(ipAddress == 0)
return(null);
if (ByteOrder.nativeOrder().equals(ByteOrder.LITTLE_ENDIAN)) {
ipAddress = Integer.reverseBytes(ipAddress);
}
@ -206,7 +209,7 @@ public class Utils {
// try to get the WiFi IP address first
String wifi_ip = getLocalWifiIpAddress(context);
if(wifi_ip != null) {
if((wifi_ip != null) && (!wifi_ip.equals("0.0.0.0"))) {
Log.d("getLocalIPAddress", "Using WiFi IP: " + wifi_ip);
return wifi_ip;
}
@ -223,9 +226,8 @@ public class Utils {
&& addr.isSiteLocalAddress() /* Exclude public IPs */
&& !addr.equals(vpn_ip)) {
String sAddr = addr.getHostAddress();
boolean isIPv4 = sAddr.indexOf(':') < 0;
if (isIPv4) {
if ((addr instanceof Inet4Address) && !sAddr.equals("0.0.0.0")) {
Log.d("getLocalIPAddress", "Using interface '" + intf.getName() + "' IP: " + sAddr);
return sAddr;
}

View File

@ -184,6 +184,10 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa
if (status.equals(CaptureService.SERVICE_STATUS_STARTED) && (mState == AppState.starting)) {
appStateRunning();
} else if (status.equals(CaptureService.SERVICE_STATUS_STOPPED)) {
// The service may still be active (on premature native termination)
if (CaptureService.isServiceActive())
CaptureService.stopService();
appStateReady();
}
}
@ -191,6 +195,14 @@ public class MainActivity extends AppCompatActivity implements LoaderManager.Loa
}, new IntentFilter(CaptureService.ACTION_SERVICE_STATUS));
}
@Override
public void onResume() {
super.onResume();
if(mMenu != null)
initAppState();
}
private void notifyAppState() {
for(AppStateListener listener: mStateListeners)
listener.appStateChanged(mState);

View File

@ -27,6 +27,33 @@
#include <malloc.h>
static int loglevel = 0;
static JNIEnv *cur_env = NULL;
static jclass vpnclass = 0;
static jclass vpn_inst = 0;
static jmethodID reportError = NULL;
jmethodID jniGetMethodID(JNIEnv *env, jclass cls, const char *name, const char *signature);
int jniCheckException(JNIEnv *env);
void DeleteLocalRef(JNIEnv *env, jobject *jresource);
/* ******************************************************* */
void init_log(int lvl, JNIEnv *env, jclass _vpnclass, jclass _vpn_inst) {
loglevel = lvl;
cur_env = env;
vpnclass = _vpnclass;
vpn_inst = _vpn_inst;
reportError = jniGetMethodID(cur_env, vpnclass, "reportError", "(Ljava/lang/String;)V");
}
/* ******************************************************* */
void finish_log() {
cur_env = NULL;
vpnclass = 0;
vpn_inst = 0;
reportError = 0;
}
/* ******************************************************* */
@ -37,8 +64,22 @@ void log_android(int prio, const char *fmt, ...) {
va_start(argptr, fmt);
vsnprintf(line, sizeof(line), fmt, argptr);
__android_log_print(prio, "VPNProxy", "%s", line);
va_end(argptr);
__android_log_print(prio, "VPNProxy", "%s", line);
if((prio >= ANDROID_LOG_FATAL) && (cur_env != NULL) && (reportError != NULL)) {
// This is a fatal error, report it to the gui
jobject info_string = (*cur_env)->NewStringUTF(cur_env, line);
if((jniCheckException(cur_env) != 0) || (info_string == NULL))
return;
(*cur_env)->CallVoidMethod(cur_env, vpn_inst, reportError, info_string);
jniCheckException(cur_env);
DeleteLocalRef(cur_env, info_string);
}
}
}

View File

@ -110,6 +110,25 @@ static bool send_header;
/* ******************************************************* */
static char* tuple2str(const zdtun_5tuple_t *tuple, char *buf, size_t bufsize) {
char srcip[64], dstip[64];
struct in_addr addr;
addr.s_addr = tuple->src_ip;
strncpy(srcip, inet_ntoa(addr), sizeof(srcip));
addr.s_addr = tuple->dst_ip;
strncpy(dstip, inet_ntoa(addr), sizeof(dstip));
snprintf(buf, bufsize, "[proto %d]: %s:%u -> %s:%u",
tuple->ipproto,
srcip, ntohs(tuple->src_port),
dstip, ntohs(tuple->dst_port));
return buf;
}
/* ******************************************************* */
void free_ndpi(conn_data_t *data) {
if(data->ndpi_flow) {
ndpi_free_flow(data->ndpi_flow);
@ -484,9 +503,8 @@ static int resolve_uid(vpnproxy_data_t *proxy, const zdtun_5tuple_t *conn_info)
if(uid >= 0) {
#if 1
char appbuf[256];
char srcip[64], dstip[64];
struct in_addr addr;
char buf[256];
char appbuf[128];
if(uid == 0)
strncpy(appbuf, "ROOT", sizeof(appbuf));
@ -495,16 +513,8 @@ static int resolve_uid(vpnproxy_data_t *proxy, const zdtun_5tuple_t *conn_info)
else
getApplicationByUid(proxy, uid, appbuf, sizeof(appbuf));
addr.s_addr = conn_info->src_ip;
strncpy(srcip, inet_ntoa(addr), sizeof(srcip));
addr.s_addr = conn_info->dst_ip;
strncpy(dstip, inet_ntoa(addr), sizeof(dstip));
log_android(ANDROID_LOG_INFO, "[proto=%d]: %s:%u -> %s:%u [%d/%s]",
conn_info->ipproto,
srcip, ntohs(conn_info->src_port),
dstip, ntohs(conn_info->dst_port),
uid, appbuf);
log_android(ANDROID_LOG_INFO, "%s [%d/%s]",
tuple2str(conn_info, buf, sizeof(buf)), uid, appbuf);
#endif
} else
uid = -1;
@ -676,16 +686,24 @@ static int net2tap(zdtun_t *tun, char *pkt_buf, int pkt_size, const zdtun_conn_t
int rv = write(proxy->tapfd, pkt_buf, pkt_size);
if(rv < 0) {
if(errno == EIO) {
if(errno == ENOBUFS) {
char buf[256];
// Do not abort, the connection will be terminated
log_android(ANDROID_LOG_ERROR, "Got ENOBUFS %s", tuple2str(zdtun_conn_get_5tuple(conn_info), buf, sizeof(buf)));
} else if(errno == EIO) {
log_android(ANDROID_LOG_INFO, "Got I/O error (terminating?)");
running = false;
} else
log_android(ANDROID_LOG_ERROR,
"tap write (%d) failed [%d]: %s", pkt_size, errno, strerror(errno));
} else if(rv != pkt_size)
log_android(ANDROID_LOG_WARN,
} else {
log_android(ANDROID_LOG_FATAL,
"tap write (%d) failed [%d]: %s", pkt_size, errno, strerror(errno));
running = false;
}
} else if(rv != pkt_size) {
log_android(ANDROID_LOG_FATAL,
"partial tap write (%d / %d)", rv, pkt_size);
else
rv = -1;
} else
rv = 0;
return rv;
@ -859,7 +877,7 @@ static int connect_dumper(vpnproxy_data_t *proxy) {
dumper_socket = socket(AF_INET, proxy->pcap_dump.tcp_socket ? SOCK_STREAM : SOCK_DGRAM, 0);
if (!dumper_socket) {
log_android(ANDROID_LOG_ERROR,
log_android(ANDROID_LOG_FATAL,
"could not open UDP pcap dump socket [%d]: %s", errno,
strerror(errno));
return(-1);
@ -874,7 +892,7 @@ static int connect_dumper(vpnproxy_data_t *proxy) {
servaddr.sin_addr.s_addr = proxy->pcap_dump.collector_addr;
if(connect(dumper_socket, (struct sockaddr*)&servaddr, sizeof(servaddr)) < 0) {
log_android(ANDROID_LOG_ERROR,
log_android(ANDROID_LOG_FATAL,
"connection to the PCAP receiver failed [%d]: %s", errno,
strerror(errno));
return(-2);
@ -896,6 +914,8 @@ static int run_tun(JNIEnv *env, jclass vpn, int tapfd, jint sdk) {
time_t last_connections_dump = (time(NULL) * 1000) - CONNECTION_DUMP_UPDATE_FREQUENCY_MS + 1000 /* update in a second */;
jclass vpn_class = (*env)->GetObjectClass(env, vpn);
init_log(ANDROID_LOG_DEBUG, env, vpn_class, vpn);
zdtun_parse_pkt(mitmproxy_pkt_buffer, sizeof(mitmproxy_pkt_buffer)-1, &mitm_pkt);
/* Classes */
@ -984,8 +1004,8 @@ static int run_tun(JNIEnv *env, jclass vpn, int tapfd, jint sdk) {
// Limit the segments size for two reasons:
// 1. to be able to encapsulate the packets for the UDP export
// 2. to avoid ENOBUFS while writing to the tapfd (for big packets).
zdtun_set_max_window_size(tun, 32768);
// 2. to avoid ENOBUFS while writing to the tapfd (for big packets, e.g. speedtest).
zdtun_set_max_window_size(tun, 8192);
log_android(ANDROID_LOG_DEBUG, "Starting packet loop [tapfd=%d]", tapfd);
@ -1001,7 +1021,7 @@ static int run_tun(JNIEnv *env, jclass vpn, int tapfd, jint sdk) {
proxy.java_dump.buffer_idx = 0;
if(!proxy.java_dump.buffer) {
log_android(ANDROID_LOG_ERROR, "malloc(java_dump.buffer) failed with code %d/%s",
log_android(ANDROID_LOG_FATAL, "malloc(java_dump.buffer) failed with code %d/%s",
errno, strerror(errno));
running = false;
}
@ -1063,7 +1083,7 @@ static int run_tun(JNIEnv *env, jclass vpn, int tapfd, jint sdk) {
check_tls_mitm(tun, &proxy, &pkt, conn);
if ((rc = zdtun_forward(tun, &pkt, conn)) != 0) {
log_android(ANDROID_LOG_ERROR, "zdtun_forward failed with code %d", rc);
log_android(ANDROID_LOG_ERROR, "zdtun_forward (proto=%d) failed with code %d", pkt.tuple.ipproto, rc);
proxy.num_dropped_connections++;
zdtun_destroy_conn(tun, conn);
@ -1120,6 +1140,8 @@ housekeeping:
}
notifyServiceStatus(&proxy, "stopped");
finish_log();
return(0);
}
@ -1145,4 +1167,9 @@ Java_com_emanuelef_remote_1capture_CaptureService_askStatsDump(JNIEnv *env, jcla
dump_vpn_stats_now = true;
dump_capture_stats_now = true;
}
}
}
JNIEXPORT jint JNICALL
Java_com_emanuelef_remote_1capture_CaptureService_getFdSetSize(JNIEnv *env, jclass clazz) {
return FD_SETSIZE;
}

View File

@ -79,5 +79,6 @@
<string name="packets_sent">发送数据包</string>
<string name="packets_rcvd">接收数据包</string>
<string name="dns_queries">DNS 查询</string>
<string name="dns_server">DNS 服务器</string>
</resources>

@ -1 +1 @@
Subproject commit b5fa5c3ffaae5746aa9c9434ac7198c818ecede4
Subproject commit 220344447ec72773e90245324999af976c5568cd