diff --git a/README.md b/README.md index 30b7a48..4cfa05e 100644 --- a/README.md +++ b/README.md @@ -5,14 +5,30 @@ Proximac is an open-source alternative to Proxifier. With Proximac, users can force App to use SOCKS5 proxy. I hope more developers can join this project. -**New feature**: +Note: Proximac only works on Mac OSX. + +##### Major change + +User now must specifiy exact process name. We abandon the old way to compare pid to determine whether the process should be hooked since pid is frequently changed due to program restart and will make proximac unable to find specified process. + +**process name under the new way**: + +```Unibox``` found from the path ```/Applications/Unibox.app/Contents/MacOS/Unibox``` +```Google Chrome``` found from the path ```/Applications/Google Chrome.app/Contents/MacOS/Google Chrome``` + +Binary file in ```Contents/MacOS``` determines the process name. + + +##### New feature + +** Now support forcing multiple Apps to use SOCKS5 proxy. +** -Note: Proximac only works on Mac OSX. -####How to build: +####How to build NOTE: Proximac is based on libuv. So, before compile this project, make sure [libuv](https://github.com/libuv/libuv) was successfully installed: $ git clone https://github.com/libuv/libuv.git @@ -44,7 +60,7 @@ We use almost the same config file as shadowsocks do but add new arguments. ``` { "process_name": - ["Unibox", "Chrome Canary", "Thunder"], + ["Unibox", "Google Chrome", "Thunder"], "local_port":1080, "local_address":"127.0.0.1", "proximac_listen_address":"127.0.0.1", @@ -53,7 +69,7 @@ We use almost the same config file as shadowsocks do but add new arguments. ``` Note: -```process_name``` shoule better be the full name outputed from ```ps -e```. +```process_name``` are names of processes that you want to force to use SOCKS5 proxy, which can be found in ```Contents/MacOS``` folder inside those Apps (right click on Apps to get inside). ```local_address``` and ```local_port``` is the ip address and the listen port of your SOCKS5 proxy, respectively. @@ -64,6 +80,8 @@ leave ```proximac_listen_address``` and ```proximac_port``` alone because these This software is partly based on projects below. 1. [Shadowsocks-libev](https://github.com/shadowsocks/shadowsocks-libev). +2. [Shadowsocks-libuv](https://github.com/dndx/shadowsocks-libuv). +3. [libuv](https://github.com/libuv/libuv). 2. [js0n](https://github.com/quartzjer/js0n). 3. tcplognke (Apple). diff --git a/src/jconf.c b/src/jconf.c index fea7f0a..981e2dc 100644 --- a/src/jconf.c +++ b/src/jconf.c @@ -51,13 +51,14 @@ if (val != NULL) LOGI("Process List:"); while ((buf = js0n(NULL, index, val, (int)pos, &vlen))!= NULL) { index++; +#define MAX_PROC_NAME_LEN 16 struct pid *pid_to_insert = malloc(sizeof(struct pid)); - pid_to_insert->name = malloc(vlen + 1); + pid_to_insert->name = calloc(1, vlen + 1); memcpy(pid_to_insert->name, buf, vlen); pid_to_insert->name[vlen] = '\0'; - pid_to_insert->pid = index; + pid_to_insert->pid = hash(pid_to_insert->name); RB_INSERT(pid_tree, &pid_list, pid_to_insert); - LOGI("%d. %s", index, pid_to_insert->name); + LOGI("%d. %s hash %x", index, pid_to_insert->name, pid_to_insert->pid); } conf->total_process_num = index; diff --git a/src/local.c b/src/local.c index d95e333..e7a23a7 100644 --- a/src/local.c +++ b/src/local.c @@ -444,6 +444,7 @@ void signal_handler_ctl_c(uv_signal_t *handle, int signum) exit(0); } + int main(int argc, char **argv) { int c, option_index = 0, daemon = 0; char* configfile = NULL; @@ -486,12 +487,12 @@ int main(int argc, char **argv) { read_conf(configfile, &conf); } - int r = process_find(); - if (r) - FATAL("unable to find process PID"); +// int r = process_find(); +// if (r) +// FATAL("unable to find process PID"); // exit(0); - r = tell_kernel_to_hook(); + int r = tell_kernel_to_hook(); if (r) FATAL("kernel cannot hook this PID due to various reasons"); diff --git a/src/proximac.c b/src/proximac.c index c339a7a..f3f61c2 100755 --- a/src/proximac.c +++ b/src/proximac.c @@ -249,6 +249,7 @@ struct TCPLogEntry { uint32_t numPktInDefer; uint32_t magic; /* magic value to ensure that system is passing me my buffer */ uint32_t init; + uint32_t pidhash_value; }; typedef struct TCPLogEntry TCPLogEntry; @@ -852,6 +853,18 @@ tl_unregistered_fn_ip6(sflt_handle handle) } +/* pid hash function */ +unsigned int pid_hash(char *str) +{ + unsigned int h; + unsigned char *p; +#define MULTIPLIER 33 + h = 0; + for (p = (unsigned char*)str; *p != '\0'; p++) + h = MULTIPLIER * h + *p; + return h; // or, h % ARRAY_SIZE; +} + /*! @typedef sf_attach_func_locked @@ -888,7 +901,11 @@ tl_attach_fn_locked(socket_t so, struct TCPLogEntry *tlp) // to get the ucred structure. // important note: the pid associated with this socket is the pid of the process which created the // socket. The socket may have been passed to another process with a different pid. - tlp->tle_pid = proc_selfpid(); + char proc_name[64] = {0}; + proc_selfname(proc_name, 63); + tlp->pidhash_value = pid_hash(proc_name); + printf("[proximac]: pid hash value = %d\n", tlp->pidhash_value); + tlp->tle_pid = proc_selfpid(); // get the uid tlp->tle_uid = kauth_getuid(); TAILQ_INSERT_TAIL(&tl_active, tlp, tle_link); @@ -1243,7 +1260,7 @@ tl_notify_fn(void *cookie, socket_t so, sflt_event_t event, void *param) // added prepend proximac_hdr for proximac struct pid find_pid; - find_pid.pid = tlp->tle_pid; + find_pid.pid = tlp->pidhash_value; lck_mtx_lock(gmutex_pid); struct pid *exist = RB_FIND(pid_tree, &pid_list, &find_pid); lck_mtx_unlock(gmutex_pid); @@ -1319,6 +1336,7 @@ tl_notify_fn(void *cookie, socket_t so, sflt_event_t event, void *param) #if SHOW_PACKET_FLOW tl_printf("sock_evt_closing - so: 0x%X\n", so); #endif + break; default: @@ -1784,7 +1802,7 @@ tl_connect_out_fn(void *cookie, socket_t so, const struct sockaddr *to) // inet_pton(AF_INET, localhost_str, &remote_addr->sin_addr); tlp->tle_remote4.sin_port = ntohs(tlp->tle_remote4.sin_port); struct pid find_pid; - find_pid.pid = tlp->tle_pid; + find_pid.pid = tlp->pidhash_value; lck_mtx_lock(gmutex_pid); struct pid *exist = RB_FIND(pid_tree, &pid_list, &find_pid); lck_mtx_unlock(gmutex_pid); diff --git a/src/tcplognke.xcodeproj/project.xcworkspace/xcuserdata/jedihy.xcuserdatad/UserInterfaceState.xcuserstate b/src/tcplognke.xcodeproj/project.xcworkspace/xcuserdata/jedihy.xcuserdatad/UserInterfaceState.xcuserstate index f3600a3..de7359f 100644 Binary files a/src/tcplognke.xcodeproj/project.xcworkspace/xcuserdata/jedihy.xcuserdatad/UserInterfaceState.xcuserstate and b/src/tcplognke.xcodeproj/project.xcworkspace/xcuserdata/jedihy.xcuserdatad/UserInterfaceState.xcuserstate differ diff --git a/src/utils.c b/src/utils.c index 3fbc5fa..6688855 100644 --- a/src/utils.c +++ b/src/utils.c @@ -70,4 +70,18 @@ struct timeval GetTimeStamp() { struct timeval tv; gettimeofday(&tv,NULL); return tv; +} + +unsigned int hash(char *str) +{ + unsigned int h; + unsigned char *p; + unsigned int i; +#define MULTIPLIER 33 + h = 0; + i = 0; + for (p = (unsigned char*)str; (*p != '\0')&&(i < 16); p++,i++) + h = MULTIPLIER * h + *p; +#undef MULTIPLIER + return h; // or, h % ARRAY_SIZE; } \ No newline at end of file diff --git a/src/utils.h b/src/utils.h index a6a9693..2812c09 100644 --- a/src/utils.h +++ b/src/utils.h @@ -270,5 +270,6 @@ struct timeval GetTimeStamp(); void setup_signal_handler(uv_loop_t *loop); void signal_handler(uv_signal_t *handle, int signum); void init_daemon(); +unsigned int hash(char *str); #endif \ No newline at end of file