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) {
|
||||
jint uid = -1;
|
||||
|
||||
char source[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));
|
||||
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
|
||||
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];
|
||||
memset(daddr128, 0, 10);
|
||||
daddr128[10] = (uint8_t) 0xFF;
|
||||
daddr128[11] = (uint8_t) 0xFF;
|
||||
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)
|
||||
uid = get_uid_sub(version, protocol, saddr, sport, daddr, dport);
|
||||
if (uid == -1) {
|
||||
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)
|
||||
log_android(ANDROID_LOG_ERROR, "uid v%d p%d %u > %s/%u not found",
|
||||
version, protocol, sport, dest, dport);
|
||||
if (uid == -1)
|
||||
log_android(ANDROID_LOG_WARN, "uid v%d p%d %s/%u > %s/%u => not found",
|
||||
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;
|
||||
}
|
||||
|
||||
int uid_cache_size = 0;
|
||||
struct uid_cache_entry *uid_cache = NULL;
|
||||
|
||||
jint get_uid_sub(const int version, const int protocol,
|
||||
const void *saddr, const uint16_t sport,
|
||||
const void *daddr, const uint16_t dport) {
|
||||
char line[250];
|
||||
char hex[16 * 2 + 1];
|
||||
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
|
||||
|
||||
const void *daddr, const uint16_t dport,
|
||||
const char *source, const char *dest,
|
||||
long now) {
|
||||
// NETLINK is not available on Android due to SELinux policies :-(
|
||||
// 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)
|
||||
|
||||
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
|
||||
char *fn = NULL;
|
||||
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)
|
||||
fn = (version == 4 ? "/proc/net/udp" : "/proc/net/udp6");
|
||||
else
|
||||
return uid;
|
||||
return -1;
|
||||
|
||||
// Open proc file
|
||||
FILE *fd = fopen(fn, "r");
|
||||
if (fd == NULL) {
|
||||
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
|
||||
jint u;
|
||||
int i = 0;
|
||||
int l = 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) {
|
||||
if (i++) {
|
||||
*hex = 0;
|
||||
_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 (!l++)
|
||||
continue;
|
||||
|
||||
if (fields == 4 && (version == 4 ? strlen(hex) == 8 : strlen(hex) == 32)) {
|
||||
if (_sport > 0 && u >= 0) {
|
||||
hex2bytes(hex, version == 4 ? _daddr4 : _daddr6);
|
||||
if (version == 4)
|
||||
((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]);
|
||||
fields = sscanf(line, fmt, shex, &_sport, dhex, &_dport, &_uid);
|
||||
if (fields == 5 && strlen(shex) == ws * 8 && strlen(dhex) == ws * 8) {
|
||||
hex2bytes(shex, _saddr);
|
||||
hex2bytes(dhex, _daddr);
|
||||
|
||||
if (_sport == sport) {
|
||||
uid = u;
|
||||
if (_dport == dport &&
|
||||
memcmp(version == 4 ? _daddr4 : _daddr6, daddr,
|
||||
version == 4 ? 4 : 16) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else
|
||||
log_android(ANDROID_LOG_ERROR, "Invalid field #%d: %s", fields, line);
|
||||
for (int w = 0; w < ws; w++)
|
||||
((uint32_t *) _saddr)[w] = htonl(((uint32_t *) _saddr)[w]);
|
||||
|
||||
for (int w = 0; w < ws; w++)
|
||||
((uint32_t *) _daddr)[w] = htonl(((uint32_t *) _daddr)[w]);
|
||||
|
||||
if (_sport == sport &&
|
||||
(_dport == dport || _dport == 0) &&
|
||||
(memcmp(_saddr, saddr, (size_t) (ws * 4)) == 0 ||
|
||||
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))
|
||||
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;
|
||||
}
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
|
||||
#define TAG "NetGuard.JNI"
|
||||
|
||||
// #define PROFILE_UID 5
|
||||
// #define PROFILE_JNI 5
|
||||
|
||||
#define EPOLL_TIMEOUT 3600 // seconds
|
||||
|
@ -61,6 +60,8 @@
|
|||
#define SESSION_MAX 512 // number
|
||||
#define SESSION_LIMIT 30 // percent
|
||||
|
||||
#define UID_MAX_AGE 30000 // milliseconds
|
||||
|
||||
#define SOCKS5_NONE 1
|
||||
#define SOCKS5_HELLO 2
|
||||
#define SOCKS5_AUTH 3
|
||||
|
@ -189,6 +190,17 @@ struct ng_session {
|
|||
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
|
||||
|
||||
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,
|
||||
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);
|
||||
|
||||
|
|
Loading…
Reference in a new issue