mirror of
https://github.com/M66B/NetGuard.git
synced 2024-12-27 18:30:09 +00:00
Cache uids
This commit is contained in:
parent
927c53b8bb
commit
928eab71a6
2 changed files with 141 additions and 71 deletions
|
@ -328,53 +328,85 @@ jint get_uid(const int version, const int protocol,
|
||||||
const void *daddr, const uint16_t dport) {
|
const void *daddr, const uint16_t dport) {
|
||||||
jint uid = -1;
|
jint uid = -1;
|
||||||
|
|
||||||
|
char source[INET6_ADDRSTRLEN + 1];
|
||||||
char dest[INET6_ADDRSTRLEN + 1];
|
char dest[INET6_ADDRSTRLEN + 1];
|
||||||
|
inet_ntop(version == 4 ? AF_INET : AF_INET6, saddr, source, sizeof(source));
|
||||||
inet_ntop(version == 4 ? AF_INET : AF_INET6, daddr, dest, sizeof(dest));
|
inet_ntop(version == 4 ? AF_INET : AF_INET6, daddr, dest, sizeof(dest));
|
||||||
log_android(ANDROID_LOG_INFO, "get uid v%d p%d %u > %s/%u",
|
|
||||||
version, protocol, sport, dest, dport);
|
struct timeval time;
|
||||||
|
gettimeofday(&time, NULL);
|
||||||
|
long now = (time.tv_sec * 1000) + (time.tv_usec / 1000);
|
||||||
|
|
||||||
// Check IPv6 table first
|
// Check IPv6 table first
|
||||||
if (version == 4) {
|
if (version == 4) {
|
||||||
|
int8_t saddr128[16];
|
||||||
|
memset(saddr128, 0, 10);
|
||||||
|
saddr128[10] = (uint8_t) 0xFF;
|
||||||
|
saddr128[11] = (uint8_t) 0xFF;
|
||||||
|
memcpy(saddr128 + 12, saddr, 4);
|
||||||
|
|
||||||
int8_t daddr128[16];
|
int8_t daddr128[16];
|
||||||
memset(daddr128, 0, 10);
|
memset(daddr128, 0, 10);
|
||||||
daddr128[10] = (uint8_t) 0xFF;
|
daddr128[10] = (uint8_t) 0xFF;
|
||||||
daddr128[11] = (uint8_t) 0xFF;
|
daddr128[11] = (uint8_t) 0xFF;
|
||||||
memcpy(daddr128 + 12, daddr, 4);
|
memcpy(daddr128 + 12, daddr, 4);
|
||||||
uid = get_uid_sub(6, protocol, saddr, sport, daddr128, dport);
|
|
||||||
|
uid = get_uid_sub(6, protocol, saddr128, sport, daddr128, dport, source, dest, now);
|
||||||
|
log_android(ANDROID_LOG_DEBUG, "uid v%d p%d %s/%u > %s/%u => %d as inet6",
|
||||||
|
version, protocol, source, sport, dest, dport, uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (uid < 0)
|
if (uid == -1) {
|
||||||
uid = get_uid_sub(version, protocol, saddr, sport, daddr, dport);
|
uid = get_uid_sub(version, protocol, saddr, sport, daddr, dport, source, dest, now);
|
||||||
|
log_android(ANDROID_LOG_DEBUG, "uid v%d p%d %s/%u > %s/%u => %d fallback",
|
||||||
|
version, protocol, source, sport, dest, dport, uid);
|
||||||
|
}
|
||||||
|
|
||||||
if (uid < 0)
|
if (uid == -1)
|
||||||
log_android(ANDROID_LOG_ERROR, "uid v%d p%d %u > %s/%u not found",
|
log_android(ANDROID_LOG_WARN, "uid v%d p%d %s/%u > %s/%u => not found",
|
||||||
version, protocol, sport, dest, dport);
|
version, protocol, source, sport, dest, dport);
|
||||||
|
else if (uid >= 0)
|
||||||
|
log_android(ANDROID_LOG_INFO, "uid v%d p%d %s/%u > %s/%u => %d",
|
||||||
|
version, protocol, source, sport, dest, dport, uid);
|
||||||
|
|
||||||
return uid;
|
return uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int uid_cache_size = 0;
|
||||||
|
struct uid_cache_entry *uid_cache = NULL;
|
||||||
|
|
||||||
jint get_uid_sub(const int version, const int protocol,
|
jint get_uid_sub(const int version, const int protocol,
|
||||||
const void *saddr, const uint16_t sport,
|
const void *saddr, const uint16_t sport,
|
||||||
const void *daddr, const uint16_t dport) {
|
const void *daddr, const uint16_t dport,
|
||||||
char line[250];
|
const char *source, const char *dest,
|
||||||
char hex[16 * 2 + 1];
|
long now) {
|
||||||
int fields;
|
|
||||||
uint8_t _daddr4[4];
|
|
||||||
uint8_t _daddr6[16];
|
|
||||||
int _sport;
|
|
||||||
int _dport;
|
|
||||||
jint uid = -1;
|
|
||||||
|
|
||||||
#ifdef PROFILE_UID
|
|
||||||
float mselapsed;
|
|
||||||
struct timeval start, end;
|
|
||||||
gettimeofday(&start, NULL);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// NETLINK is not available on Android due to SELinux policies :-(
|
// NETLINK is not available on Android due to SELinux policies :-(
|
||||||
// http://stackoverflow.com/questions/27148536/netlink-implementation-for-the-android-ndk
|
// http://stackoverflow.com/questions/27148536/netlink-implementation-for-the-android-ndk
|
||||||
// https://android.googlesource.com/platform/system/sepolicy/+/master/private/app.te (netlink_tcpdiag_socket)
|
// https://android.googlesource.com/platform/system/sepolicy/+/master/private/app.te (netlink_tcpdiag_socket)
|
||||||
|
|
||||||
|
static uint8_t zero[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
|
||||||
|
|
||||||
|
// Check cache
|
||||||
|
for (int i = 0; i < uid_cache_size; i++)
|
||||||
|
if (now - uid_cache[i].time <= UID_MAX_AGE &&
|
||||||
|
uid_cache[i].version == version &&
|
||||||
|
uid_cache[i].protocol == protocol &&
|
||||||
|
uid_cache[i].sport == sport &&
|
||||||
|
(uid_cache[i].dport == dport || uid_cache[i].dport == 0) &&
|
||||||
|
(memcmp(uid_cache[i].saddr, saddr, version == 4 ? 4 : 16) == 0 ||
|
||||||
|
memcmp(uid_cache[i].saddr, zero, version == 4 ? 4 : 16) == 0) &&
|
||||||
|
(memcmp(uid_cache[i].daddr, daddr, version == 4 ? 4 : 16) == 0 ||
|
||||||
|
memcmp(uid_cache[i].daddr, zero, version == 4 ? 4 : 16) == 0)) {
|
||||||
|
|
||||||
|
log_android(ANDROID_LOG_INFO, "uid v%d p%d %s/%u > %s/%u => %d (from cache)",
|
||||||
|
version, protocol, source, sport, dest, dport, uid_cache[i].uid);
|
||||||
|
|
||||||
|
if (protocol == IPPROTO_UDP)
|
||||||
|
return -2;
|
||||||
|
else
|
||||||
|
return uid_cache[i].uid;
|
||||||
|
}
|
||||||
|
|
||||||
// Get proc file name
|
// Get proc file name
|
||||||
char *fn = NULL;
|
char *fn = NULL;
|
||||||
if (protocol == IPPROTO_ICMP && version == 4)
|
if (protocol == IPPROTO_ICMP && version == 4)
|
||||||
|
@ -386,68 +418,92 @@ jint get_uid_sub(const int version, const int protocol,
|
||||||
else if (protocol == IPPROTO_UDP)
|
else if (protocol == IPPROTO_UDP)
|
||||||
fn = (version == 4 ? "/proc/net/udp" : "/proc/net/udp6");
|
fn = (version == 4 ? "/proc/net/udp" : "/proc/net/udp6");
|
||||||
else
|
else
|
||||||
return uid;
|
return -1;
|
||||||
|
|
||||||
// Open proc file
|
// Open proc file
|
||||||
FILE *fd = fopen(fn, "r");
|
FILE *fd = fopen(fn, "r");
|
||||||
if (fd == NULL) {
|
if (fd == NULL) {
|
||||||
log_android(ANDROID_LOG_ERROR, "fopen %s error %d: %s", fn, errno, strerror(errno));
|
log_android(ANDROID_LOG_ERROR, "fopen %s error %d: %s", fn, errno, strerror(errno));
|
||||||
return uid;
|
return -2;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jint uid = -1;
|
||||||
|
|
||||||
|
char line[250];
|
||||||
|
int fields;
|
||||||
|
|
||||||
|
char shex[16 * 2 + 1];
|
||||||
|
uint8_t _saddr[16];
|
||||||
|
int _sport;
|
||||||
|
|
||||||
|
char dhex[16 * 2 + 1];
|
||||||
|
uint8_t _daddr[16];
|
||||||
|
int _dport;
|
||||||
|
|
||||||
|
jint _uid;
|
||||||
|
|
||||||
// Scan proc file
|
// Scan proc file
|
||||||
jint u;
|
int l = 0;
|
||||||
int i = 0;
|
|
||||||
*line = 0;
|
*line = 0;
|
||||||
|
int c = 0;
|
||||||
|
int ws = (version == 4 ? 1 : 4);
|
||||||
|
const char *fmt = (version == 4
|
||||||
|
? "%*d: %8s:%X %8s:%X %*X %*lX:%*lX %*X:%*X %*X %d %*d %*ld"
|
||||||
|
: "%*d: %32s:%X %32s:%X %*X %*lX:%*lX %*X:%*X %*X %d %*d %*ld");
|
||||||
while (fgets(line, sizeof(line), fd) != NULL) {
|
while (fgets(line, sizeof(line), fd) != NULL) {
|
||||||
if (i++) {
|
if (!l++)
|
||||||
*hex = 0;
|
continue;
|
||||||
_sport = -1;
|
|
||||||
_dport = -1;
|
|
||||||
u = -1;
|
|
||||||
if (version == 4)
|
|
||||||
fields = sscanf(
|
|
||||||
line,
|
|
||||||
"%*d: %*X:%X %8s:%X %*X %*lX:%*lX %*X:%*X %*X %d %*d %*ld",
|
|
||||||
&_sport, hex, &_dport, &u);
|
|
||||||
else
|
|
||||||
fields = sscanf(
|
|
||||||
line,
|
|
||||||
"%*d: %*X:%X %32s:%X %*X %*lX:%*lX %*X:%*X %*X %d %*d %*ld",
|
|
||||||
&_sport, hex, &_dport, &u);
|
|
||||||
|
|
||||||
if (fields == 4 && (version == 4 ? strlen(hex) == 8 : strlen(hex) == 32)) {
|
fields = sscanf(line, fmt, shex, &_sport, dhex, &_dport, &_uid);
|
||||||
if (_sport > 0 && u >= 0) {
|
if (fields == 5 && strlen(shex) == ws * 8 && strlen(dhex) == ws * 8) {
|
||||||
hex2bytes(hex, version == 4 ? _daddr4 : _daddr6);
|
hex2bytes(shex, _saddr);
|
||||||
if (version == 4)
|
hex2bytes(dhex, _daddr);
|
||||||
((uint32_t *) _daddr4)[0] = htonl(((uint32_t *) _daddr4)[0]);
|
|
||||||
else
|
|
||||||
for (int w = 0; w < 4; w++)
|
|
||||||
((uint32_t *) _daddr6)[w] = htonl(((uint32_t *) _daddr6)[w]);
|
|
||||||
|
|
||||||
if (_sport == sport) {
|
for (int w = 0; w < ws; w++)
|
||||||
uid = u;
|
((uint32_t *) _saddr)[w] = htonl(((uint32_t *) _saddr)[w]);
|
||||||
if (_dport == dport &&
|
|
||||||
memcmp(version == 4 ? _daddr4 : _daddr6, daddr,
|
for (int w = 0; w < ws; w++)
|
||||||
version == 4 ? 4 : 16) == 0)
|
((uint32_t *) _daddr)[w] = htonl(((uint32_t *) _daddr)[w]);
|
||||||
break;
|
|
||||||
}
|
if (_sport == sport &&
|
||||||
}
|
(_dport == dport || _dport == 0) &&
|
||||||
} else
|
(memcmp(_saddr, saddr, (size_t) (ws * 4)) == 0 ||
|
||||||
log_android(ANDROID_LOG_ERROR, "Invalid field #%d: %s", fields, line);
|
memcmp(_saddr, zero, (size_t) (ws * 4)) == 0) &&
|
||||||
|
(memcmp(_daddr, daddr, (size_t) (ws * 4)) == 0 ||
|
||||||
|
memcmp(_daddr, zero, (size_t) (ws * 4)) == 0))
|
||||||
|
uid = _uid;
|
||||||
|
|
||||||
|
for (; c < uid_cache_size; c++)
|
||||||
|
if (now - uid_cache[c].time > UID_MAX_AGE)
|
||||||
|
break;
|
||||||
|
|
||||||
|
if (c >= uid_cache_size) {
|
||||||
|
if (uid_cache_size == 0)
|
||||||
|
uid_cache = malloc(sizeof(struct uid_cache_entry));
|
||||||
|
else
|
||||||
|
uid_cache = realloc(uid_cache,
|
||||||
|
sizeof(struct uid_cache_entry) *
|
||||||
|
(uid_cache_size + 1));
|
||||||
|
c = uid_cache_size;
|
||||||
|
uid_cache_size++;
|
||||||
|
}
|
||||||
|
|
||||||
|
uid_cache[c].version = (uint8_t) version;
|
||||||
|
uid_cache[c].protocol = (uint8_t) protocol;
|
||||||
|
memcpy(uid_cache[c].saddr, _saddr, (size_t) (ws * 4));
|
||||||
|
uid_cache[c].sport = (uint16_t) _sport;
|
||||||
|
memcpy(uid_cache[c].daddr, daddr, (size_t) (ws * 4));
|
||||||
|
uid_cache[c].dport = (uint16_t) _dport;
|
||||||
|
uid_cache[c].uid = _uid;
|
||||||
|
uid_cache[c].time = now;
|
||||||
|
} else {
|
||||||
|
log_android(ANDROID_LOG_ERROR, "Invalid field #%d: %s", fields, line);
|
||||||
|
return -2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fclose(fd))
|
if (fclose(fd))
|
||||||
log_android(ANDROID_LOG_ERROR, "fclose %s error %d: %s", fn, errno, strerror(errno));
|
log_android(ANDROID_LOG_ERROR, "fclose %s error %d: %s", fn, errno, strerror(errno));
|
||||||
|
|
||||||
#ifdef PROFILE_UID
|
|
||||||
gettimeofday(&end, NULL);
|
|
||||||
mselapsed = (end.tv_sec - start.tv_sec) * 1000.0 +
|
|
||||||
(end.tv_usec - start.tv_usec) / 1000.0;
|
|
||||||
if (mselapsed > PROFILE_UID)
|
|
||||||
log_android(ANDROID_LOG_WARN, "get uid ip %f", mselapsed);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return uid;
|
return uid;
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,6 @@
|
||||||
|
|
||||||
#define TAG "NetGuard.JNI"
|
#define TAG "NetGuard.JNI"
|
||||||
|
|
||||||
// #define PROFILE_UID 5
|
|
||||||
// #define PROFILE_JNI 5
|
// #define PROFILE_JNI 5
|
||||||
|
|
||||||
#define EPOLL_TIMEOUT 3600 // seconds
|
#define EPOLL_TIMEOUT 3600 // seconds
|
||||||
|
@ -61,6 +60,8 @@
|
||||||
#define SESSION_MAX 512 // number
|
#define SESSION_MAX 512 // number
|
||||||
#define SESSION_LIMIT 30 // percent
|
#define SESSION_LIMIT 30 // percent
|
||||||
|
|
||||||
|
#define UID_MAX_AGE 30000 // milliseconds
|
||||||
|
|
||||||
#define SOCKS5_NONE 1
|
#define SOCKS5_NONE 1
|
||||||
#define SOCKS5_HELLO 2
|
#define SOCKS5_HELLO 2
|
||||||
#define SOCKS5_AUTH 3
|
#define SOCKS5_AUTH 3
|
||||||
|
@ -189,6 +190,17 @@ struct ng_session {
|
||||||
struct ng_session *next;
|
struct ng_session *next;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct uid_cache_entry {
|
||||||
|
uint8_t version;
|
||||||
|
uint8_t protocol;
|
||||||
|
uint8_t saddr[16];
|
||||||
|
uint16_t sport;
|
||||||
|
uint8_t daddr[16];
|
||||||
|
uint16_t dport;
|
||||||
|
jint uid;
|
||||||
|
long time;
|
||||||
|
};
|
||||||
|
|
||||||
// IPv6
|
// IPv6
|
||||||
|
|
||||||
struct ip6_hdr_pseudo {
|
struct ip6_hdr_pseudo {
|
||||||
|
@ -461,7 +473,9 @@ jint get_uid(const int version, const int protocol,
|
||||||
|
|
||||||
jint get_uid_sub(const int version, const int protocol,
|
jint get_uid_sub(const int version, const int protocol,
|
||||||
const void *saddr, const uint16_t sport,
|
const void *saddr, const uint16_t sport,
|
||||||
const void *daddr, const uint16_t dport);
|
const void *daddr, const uint16_t dport,
|
||||||
|
const char *source, const char *dest,
|
||||||
|
long now);
|
||||||
|
|
||||||
int protect_socket(const struct arguments *args, int socket);
|
int protect_socket(const struct arguments *args, int socket);
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue