diff --git a/extend.c b/extend.c index 54e2a87..a7d2bbe 100644 --- a/extend.c +++ b/extend.c @@ -7,6 +7,8 @@ #else #include #include + #include + #include #endif #include @@ -357,3 +359,56 @@ int on_desync(struct poolhd *pool, struct eval *val, val->pair->type = EV_PRE_TUNNEL; return 0; } + +#ifdef __linux__ +int protect(int conn_fd, const char *path) +{ + struct sockaddr_un sa; + sa.sun_family = AF_UNIX; + strcpy(sa.sun_path, path); + + int fd = socket(AF_UNIX, SOCK_STREAM, 0); + if (fd < 0) { + uniperror("socket"); + return -1; + } + struct timeval tv = { .tv_sec = 1 }; + setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)); + setsockopt(fd, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)); + + int err = connect(fd, (struct sockaddr *)&sa, sizeof(sa)); + if (err) { + uniperror("connect"); + close(fd); + return -1; + } + char buf[CMSG_SPACE(sizeof(fd))] = {}; + struct iovec io = { .iov_base = "1", .iov_len = 1 }; + struct msghdr msg = { .msg_iov = &io }; + + msg.msg_iovlen = 1; + msg.msg_control = buf; + msg.msg_controllen = sizeof(buf); + + struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(conn_fd)); + + *((int *)CMSG_DATA(cmsg)) = conn_fd; + msg.msg_controllen = CMSG_SPACE(sizeof(conn_fd)); + + if (sendmsg(fd, &msg, 0) < 0) { + uniperror("sendmsg"); + close(fd); + return -1; + } + if (recv(fd, buf, 1, 0) < 1) { + uniperror("recv"); + close(fd); + return -1; + } + close(fd); + return 0; +} +#endif diff --git a/extend.h b/extend.h index bbedb5e..ef72bbf 100644 --- a/extend.h +++ b/extend.h @@ -6,3 +6,9 @@ int on_tunnel_check(struct poolhd *pool, struct eval *val, int on_desync(struct poolhd *pool, struct eval *val, char *buffer, size_t bfsize); + +#ifdef __linux__ +int protect(int conn_fd, const char *path); +#else +#define protect(fd, path) 0 +#endif \ No newline at end of file diff --git a/main.c b/main.c index e058f05..be8c4f5 100644 --- a/main.c +++ b/main.c @@ -26,10 +26,7 @@ #define VERSION "10" -#define MPOOL_INC 16 - char oob_char[1] = "a"; - char ip_option[1] = "\0"; struct packet fake_tls = { @@ -152,6 +149,9 @@ const struct option options[] = { {"def-ttl", 1, 0, 'g'}, {"delay", 1, 0, 'w'}, // {"not-wait-send", 0, 0, 'W'}, // + #ifdef __linux__ + {"protect-path", 1, 0, 'P'}, // + #endif {0} }; @@ -391,9 +391,9 @@ void *add(void **root, int *n, size_t ss) } #ifndef _WIN32 -#define FREE(p, s) munmap(p, s) +#define FREE_MAP(p, s) munmap(p, s) #else -#define FREE(p, s) free(p) +#define FREE_MAP(p, s) free(p) #endif void clear_params(void) @@ -417,15 +417,19 @@ void clear_params(void) s.parts = 0; } if (s.fake_data.data) { - FREE(s.fake_data.data, s.fake_data.size); + FREE_MAP(s.fake_data.data, s.fake_data.size); s.fake_data.data = 0; } + if (s.file_ptr) { + FREE_MAP(s.file_ptr, s.file_size); + s.file_ptr = 0; + } } free(params.dp); params.dp = 0; } if (oob_data.data != oob_char) { - FREE(oob_data.data, oob_data.size); + FREE_MAP(oob_data.data, oob_data.size); oob_data.data = oob_char; } } @@ -634,13 +638,15 @@ int main(int argc, char **argv) break; case 'H':; - ssize_t size; - char *data = ftob(optarg, &size); - if (!data) { + if (dp->file_ptr) { + continue; + } + dp->file_ptr = ftob(optarg, &dp->file_size); + if (!dp->file_ptr) { uniperror("read/parse"); invalid = 1; } - dp->hosts = parse_hosts(data, size); + dp->hosts = parse_hosts(dp->file_ptr, dp->file_size); if (!dp->hosts) { perror("parse_hosts"); clear_params(); @@ -690,6 +696,9 @@ int main(int argc, char **argv) break; case 'k': + if (dp->ip_options != ip_option) { + continue; + } if (optarg) dp->ip_options = ftob(optarg, &dp->ip_options_len); else { @@ -716,6 +725,9 @@ int main(int argc, char **argv) break; case 'l': + if (dp->fake_data.data) { + continue; + } dp->fake_data.data = ftob(optarg, &dp->fake_data.size); if (!dp->fake_data.data) { uniperror("read/parse"); @@ -724,6 +736,9 @@ int main(int argc, char **argv) break; case 'e': + if (oob_data.data != oob_char) { + continue; + } oob_data.data = ftob(optarg, &oob_data.size); if (!oob_data.data) { uniperror("read/parse"); @@ -787,7 +802,11 @@ int main(int argc, char **argv) case 'W': params.wait_send = 0; break; - + #ifdef __linux__ + case 'P': + params.protect_path = optarg; + break; + #endif case 0: break; diff --git a/params.h b/params.h index 9eef291..d3559e4 100644 --- a/params.h +++ b/params.h @@ -68,6 +68,9 @@ struct desync_params { int detect; struct mphdr *hosts; + char *file_ptr; + ssize_t file_size; + char to_ip; struct sockaddr_in6 addr; }; @@ -93,6 +96,8 @@ struct params { struct sockaddr_in6 baddr; struct sockaddr_in6 laddr; struct mphdr *mempool; + + char *protect_path; }; extern struct params params; diff --git a/proxy.c b/proxy.c index 7a260b0..f1e8d5a 100644 --- a/proxy.c +++ b/proxy.c @@ -328,6 +328,10 @@ int create_conn(struct poolhd *pool, uniperror("socket"); return -1; } + if (params.protect_path + && protect(sfd, params.protect_path) < 0) { + return -1; + } if (addr.sa.sa_family == AF_INET6) { int no = 0; if (setsockopt(sfd, IPPROTO_IPV6, @@ -403,6 +407,10 @@ int udp_associate(struct poolhd *pool, perror("socket"); return -1; } + if (params.protect_path + && protect(ufd, params.protect_path) < 0) { + return -1; + } if (params.baddr.sin6_family == AF_INET6) { int no = 0; if (setsockopt(ufd, IPPROTO_IPV6,