mirror of https://github.com/M66B/NetGuard.git
SOCKS5 basic auth
This commit is contained in:
parent
1205e105e9
commit
e1ed149871
|
@ -229,6 +229,8 @@ public class ActivitySettings extends AppCompatActivity implements SharedPrefere
|
|||
// SOCKS5 parameters
|
||||
screen.findPreference("socks5_addr").setTitle(getString(R.string.setting_socks5_addr, prefs.getString("socks5_addr", "-")));
|
||||
screen.findPreference("socks5_port").setTitle(getString(R.string.setting_socks5_port, prefs.getString("socks5_port", "-")));
|
||||
screen.findPreference("socks5_username").setTitle(getString(R.string.setting_socks5_username, prefs.getString("socks5_username", "-")));
|
||||
screen.findPreference("socks5_password").setTitle(getString(R.string.setting_socks5_password, TextUtils.isEmpty(prefs.getString("socks5_username", "")) ? "-" : "*****"));
|
||||
|
||||
// PCAP parameters
|
||||
screen.findPreference("pcap_record_size").setTitle(getString(R.string.setting_pcap_record_size, prefs.getString("pcap_record_size", "64")));
|
||||
|
@ -641,7 +643,10 @@ public class ActivitySettings extends AppCompatActivity implements SharedPrefere
|
|||
getPreferenceScreen().findPreference(name).setTitle(
|
||||
getString(R.string.setting_dns, prefs.getString("dns", Util.getDefaultDNS(this).get(0))));
|
||||
|
||||
} else if ("socks5_addr".equals(name)) {
|
||||
} else if ("socks5_enabled".equals(name))
|
||||
ServiceSinkhole.reload("changed " + name, this);
|
||||
|
||||
else if ("socks5_addr".equals(name)) {
|
||||
String socks5 = prefs.getString("socks5_addr", null);
|
||||
try {
|
||||
checkAddress(socks5);
|
||||
|
@ -659,6 +664,14 @@ public class ActivitySettings extends AppCompatActivity implements SharedPrefere
|
|||
getPreferenceScreen().findPreference(name).setTitle(getString(R.string.setting_socks5_port, prefs.getString(name, "-")));
|
||||
ServiceSinkhole.reload("changed " + name, this);
|
||||
|
||||
} else if ("socks5_username".equals(name)) {
|
||||
getPreferenceScreen().findPreference(name).setTitle(getString(R.string.setting_socks5_username, prefs.getString(name, "-")));
|
||||
ServiceSinkhole.reload("changed " + name, this);
|
||||
|
||||
} else if ("socks5_password".equals(name)) {
|
||||
getPreferenceScreen().findPreference(name).setTitle(getString(R.string.setting_socks5_password, TextUtils.isEmpty(prefs.getString(name, "")) ? "-" : "*****"));
|
||||
ServiceSinkhole.reload("changed " + name, this);
|
||||
|
||||
} else if ("pcap_record_size".equals(name) || "pcap_file_size".equals(name)) {
|
||||
if ("pcap_record_size".equals(name))
|
||||
getPreferenceScreen().findPreference(name).setTitle(getString(R.string.setting_pcap_record_size, prefs.getString(name, "64")));
|
||||
|
|
|
@ -183,7 +183,7 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS
|
|||
|
||||
private static native void jni_pcap(String name, int record_size, int file_size);
|
||||
|
||||
private native void jni_socks5(String ip, int port);
|
||||
private native void jni_socks5(String addr, int port, String username, String password);
|
||||
|
||||
private native void jni_done();
|
||||
|
||||
|
@ -1115,7 +1115,14 @@ public class ServiceSinkhole extends VpnService implements SharedPreferences.OnS
|
|||
|
||||
if (log || log_app || filter) {
|
||||
int prio = Integer.parseInt(prefs.getString("loglevel", Integer.toString(Log.WARN)));
|
||||
jni_socks5(prefs.getString("socks5_addr", ""), Integer.parseInt(prefs.getString("socks5_port", "0")));
|
||||
if (prefs.getBoolean("socks5_enabled", false))
|
||||
jni_socks5(
|
||||
prefs.getString("socks5_addr", ""),
|
||||
Integer.parseInt(prefs.getString("socks5_port", "0")),
|
||||
prefs.getString("socks5_username", ""),
|
||||
prefs.getString("socks5_password", ""));
|
||||
else
|
||||
jni_socks5("", 0, "", "");
|
||||
jni_start(vpn.getFd(), mapForward.containsKey(53), prio);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ pthread_t thread_id = 0;
|
|||
pthread_mutex_t lock;
|
||||
char socks5_addr[INET6_ADDRSTRLEN + 1];
|
||||
int socks5_port = 0;
|
||||
char socks5_username[127 + 1];
|
||||
char socks5_password[127 + 1];
|
||||
int loglevel = ANDROID_LOG_WARN;
|
||||
|
||||
extern int max_tun_msg;
|
||||
|
@ -107,6 +109,8 @@ Java_eu_faircode_netguard_ServiceSinkhole_jni_1init(JNIEnv *env, jobject instanc
|
|||
|
||||
*socks5_addr = 0;
|
||||
socks5_port = 0;
|
||||
*socks5_username = 0;
|
||||
*socks5_password = 0;
|
||||
pcap_file = NULL;
|
||||
|
||||
if (pthread_mutex_init(&lock, NULL))
|
||||
|
@ -299,20 +303,24 @@ Java_eu_faircode_netguard_ServiceSinkhole_jni_1pcap(
|
|||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
Java_eu_faircode_netguard_ServiceSinkhole_jni_1socks5(JNIEnv *env,
|
||||
jobject instance, jstring ip_, jint port) {
|
||||
if (ip_ == NULL || port == 0) {
|
||||
*socks5_addr = 0;
|
||||
socks5_port = 0;
|
||||
} else {
|
||||
const char *ip = (*env)->GetStringUTFChars(env, ip_, 0);
|
||||
strcpy(socks5_addr, ip);
|
||||
socks5_port = port;
|
||||
Java_eu_faircode_netguard_ServiceSinkhole_jni_1socks5(JNIEnv *env, jobject instance, jstring addr_,
|
||||
jint port, jstring username_,
|
||||
jstring password_) {
|
||||
const char *addr = (*env)->GetStringUTFChars(env, addr_, 0);
|
||||
const char *username = (*env)->GetStringUTFChars(env, username_, 0);
|
||||
const char *password = (*env)->GetStringUTFChars(env, password_, 0);
|
||||
|
||||
log_android(ANDROID_LOG_WARN, "SOCKS5 %s:%d", socks5_addr, socks5_port);
|
||||
strcpy(socks5_addr, addr);
|
||||
socks5_port = port;
|
||||
strcpy(socks5_username, username);
|
||||
strcpy(socks5_password, password);
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, ip_, ip);
|
||||
}
|
||||
log_android(ANDROID_LOG_WARN, "SOCKS5 %s:%d user=%s",
|
||||
socks5_addr, socks5_port, socks5_username);
|
||||
|
||||
(*env)->ReleaseStringUTFChars(env, addr_, addr);
|
||||
(*env)->ReleaseStringUTFChars(env, username_, username);
|
||||
(*env)->ReleaseStringUTFChars(env, password_, password);
|
||||
}
|
||||
|
||||
JNIEXPORT void JNICALL
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
extern struct ng_session *ng_session;
|
||||
extern char socks5_addr[INET6_ADDRSTRLEN + 1];
|
||||
extern int socks5_port;
|
||||
extern char socks5_username[127 + 1];
|
||||
extern char socks5_password[127 + 1];
|
||||
|
||||
extern FILE *pcap_file;
|
||||
|
||||
|
@ -267,6 +269,7 @@ void check_tcp_socket(const struct arguments *args,
|
|||
if (ev->events & EPOLLOUT) {
|
||||
log_android(ANDROID_LOG_INFO, "%s connected", session);
|
||||
|
||||
// http://www.rfc-base.org/txt/rfc-1928.txt
|
||||
// https://en.wikipedia.org/wiki/SOCKS#SOCKS5
|
||||
if (*socks5_addr && socks5_port)
|
||||
s->tcp.socks5 = SOCKS5_HELLO;
|
||||
|
@ -291,12 +294,27 @@ void check_tcp_socket(const struct arguments *args,
|
|||
bytes == 2 && buffer[0] == 5) {
|
||||
if (buffer[1] == 0)
|
||||
s->tcp.socks5 = SOCKS5_CONNECT;
|
||||
else if (buffer[1] == 2)
|
||||
s->tcp.socks5 = SOCKS5_AUTH;
|
||||
else {
|
||||
s->tcp.socks5 = 0;
|
||||
log_android(ANDROID_LOG_ERROR, "%s SOCKS5 auth %d not supported",
|
||||
session, buffer[1]);
|
||||
write_rst(args, &s->tcp);
|
||||
}
|
||||
|
||||
} else if (s->tcp.socks5 == SOCKS5_AUTH &&
|
||||
bytes == 2 && buffer[0] == 1) {
|
||||
if (buffer[1] == 0) {
|
||||
s->tcp.socks5 = SOCKS5_CONNECT;
|
||||
log_android(ANDROID_LOG_WARN, "%s SOCKS5 auth OK", session);
|
||||
} else {
|
||||
s->tcp.socks5 = 0;
|
||||
log_android(ANDROID_LOG_ERROR, "%s SOCKS5 auth error %d",
|
||||
session, buffer[1]);
|
||||
write_rst(args, &s->tcp);
|
||||
}
|
||||
|
||||
} else if (s->tcp.socks5 == SOCKS5_CONNECT &&
|
||||
bytes == 6 + (s->tcp.version == 4 ? 4 : 16) &&
|
||||
buffer[0] == 5) {
|
||||
|
@ -304,6 +322,7 @@ void check_tcp_socket(const struct arguments *args,
|
|||
s->tcp.socks5 = SOCKS5_CONNECTED;
|
||||
log_android(ANDROID_LOG_WARN, "%s SOCKS5 connected", session);
|
||||
} else {
|
||||
s->tcp.socks5 = 0;
|
||||
log_android(ANDROID_LOG_ERROR, "%s SOCKS5 connect error %d",
|
||||
session, buffer[1]);
|
||||
write_rst(args, &s->tcp);
|
||||
|
@ -321,6 +340,7 @@ void check_tcp_socket(const struct arguments *args,
|
|||
}
|
||||
|
||||
} else {
|
||||
s->tcp.socks5 = 0;
|
||||
log_android(ANDROID_LOG_ERROR, "%s recv SOCKS5 state %d",
|
||||
session, s->tcp.socks5);
|
||||
write_rst(args, &s->tcp);
|
||||
|
@ -330,7 +350,7 @@ void check_tcp_socket(const struct arguments *args,
|
|||
}
|
||||
|
||||
if (s->tcp.socks5 == SOCKS5_HELLO) {
|
||||
uint8_t buffer[3] = {5, 1, 0};
|
||||
uint8_t buffer[4] = {5, 2, 0, 2};
|
||||
char *h = hex(buffer, sizeof(buffer));
|
||||
log_android(ANDROID_LOG_INFO, "%s sending SOCKS5 hello: %s",
|
||||
session, h);
|
||||
|
@ -342,6 +362,30 @@ void check_tcp_socket(const struct arguments *args,
|
|||
write_rst(args, &s->tcp);
|
||||
}
|
||||
|
||||
} else if (s->tcp.socks5 == SOCKS5_AUTH) {
|
||||
uint8_t ulen = strlen(socks5_username);
|
||||
uint8_t plen = strlen(socks5_password);
|
||||
uint8_t buffer[512];
|
||||
*(buffer + 0) = 1; // Version
|
||||
*(buffer + 1) = ulen;
|
||||
memcpy(buffer + 2, socks5_username, ulen);
|
||||
*(buffer + 2 + ulen) = plen;
|
||||
memcpy(buffer + 2 + ulen + 1, socks5_password, plen);
|
||||
|
||||
size_t len = 2 + ulen + 1 + plen;
|
||||
|
||||
char *h = hex(buffer, len);
|
||||
log_android(ANDROID_LOG_INFO, "%s sending SOCKS5 auth: %s",
|
||||
session, h);
|
||||
free(h);
|
||||
ssize_t sent = send(s->socket, buffer, len, MSG_NOSIGNAL);
|
||||
if (sent < 0) {
|
||||
log_android(ANDROID_LOG_ERROR,
|
||||
"%s send SOCKS5 connect error %d: %s",
|
||||
session, errno, strerror(errno));
|
||||
write_rst(args, &s->tcp);
|
||||
}
|
||||
|
||||
} else if (s->tcp.socks5 == SOCKS5_CONNECT) {
|
||||
uint8_t buffer[22];
|
||||
*(buffer + 0) = 5; // version
|
||||
|
|
|
@ -92,8 +92,11 @@ however it is impossible to guarantee NetGuard will work correctly on every devi
|
|||
<string name="setting_vpn4">VPN IPv4: %s</string>
|
||||
<string name="setting_vpn6">VPN IPv6: %s</string>
|
||||
<string name="setting_dns">VPN DNS: %s</string>
|
||||
<string name="setting_socks5_enabled">SOCKS5 enabled</string>
|
||||
<string name="setting_socks5_addr">SOCKS5 address: %s</string>
|
||||
<string name="setting_socks5_port">SOCKS5 port: %s</string>
|
||||
<string name="setting_socks5_username">SOCKS5 username: %s</string>
|
||||
<string name="setting_socks5_password">SOCKS5 password: %s</string>
|
||||
<string name="setting_pcap_record_size">PCAP record size: %s B</string>
|
||||
<string name="setting_pcap_file_size">PCAP max. file size: %s MB</string>
|
||||
|
||||
|
|
|
@ -186,6 +186,11 @@
|
|||
android:dependency="filter"
|
||||
android:inputType="text"
|
||||
android:key="dns" />
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:dependency="filter"
|
||||
android:key="socks5_enabled"
|
||||
android:title="@string/setting_socks5_enabled" />
|
||||
<EditTextPreference
|
||||
android:dependency="filter"
|
||||
android:hint="127.0.0.1"
|
||||
|
@ -196,6 +201,14 @@
|
|||
android:hint="1080"
|
||||
android:inputType="text"
|
||||
android:key="socks5_port" />
|
||||
<EditTextPreference
|
||||
android:dependency="filter"
|
||||
android:inputType="text"
|
||||
android:key="socks5_username" />
|
||||
<EditTextPreference
|
||||
android:dependency="filter"
|
||||
android:inputType="text"
|
||||
android:key="socks5_password" />
|
||||
<EditTextPreference
|
||||
android:defaultValue="64"
|
||||
android:inputType="number"
|
||||
|
|
|
@ -186,6 +186,11 @@
|
|||
android:dependency="filter"
|
||||
android:inputType="text"
|
||||
android:key="dns" />
|
||||
<eu.faircode.netguard.SwitchPreference
|
||||
android:defaultValue="false"
|
||||
android:dependency="filter"
|
||||
android:key="socks5_enabled"
|
||||
android:title="@string/setting_socks5_enabled" />
|
||||
<EditTextPreference
|
||||
android:dependency="filter"
|
||||
android:hint="127.0.0.1"
|
||||
|
@ -196,6 +201,14 @@
|
|||
android:hint="1080"
|
||||
android:inputType="text"
|
||||
android:key="socks5_port" />
|
||||
<EditTextPreference
|
||||
android:dependency="filter"
|
||||
android:inputType="text"
|
||||
android:key="socks5_username" />
|
||||
<EditTextPreference
|
||||
android:dependency="filter"
|
||||
android:inputType="text"
|
||||
android:key="socks5_password" />
|
||||
<EditTextPreference
|
||||
android:defaultValue="64"
|
||||
android:inputType="number"
|
||||
|
|
Loading…
Reference in New Issue