Skip to content

Commit

Permalink
fix ipv6 bug
Browse files Browse the repository at this point in the history
  • Loading branch information
zfl9 committed May 10, 2020
2 parents 9c54768 + 7938d47 commit d4d2f37
Show file tree
Hide file tree
Showing 7 changed files with 181 additions and 146 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ usage: ipt2socks <options...>. the existing options are as follows:
-l, --listen-port <port> listen port number, default: 60080
-f, --buffer-size <size> tcp socket recv bufsize, default: 8192
-S, --tcp-syncnt <cnt> change the number of tcp syn retransmits
-c, --cache-size <size> udp context cache maxsize, default: 256
-o, --udp-timeout <sec> udp context idle timeout, default: 180
-c, --cache-size <size> udp context cache maxsize, default: 128
-o, --udp-timeout <sec> udp context idle timeout, default: 30
-j, --thread-nums <num> number of the worker threads, default: 1
-n, --nofile-limit <num> set nofile limit, may need root privilege
-u, --run-user <user> run as the given user, need root privilege
Expand All @@ -63,8 +63,8 @@ usage: ipt2socks <options...>. the existing options are as follows:
- `-l`选项:本地 IPv4/6 监听端口,默认为 60080。
- `-f`选项:TCP 套接字的缓冲区大小,默认为 8192 字节。
- `-S`选项:与 socks5 服务器建立 TCP 连接的超时参数。
- `-c`选项:UDP 上下文的最大数量,默认为 256 个。
- `-o`选项:UDP 上下文的超时时间,默认为 180 秒。
- `-c`选项:UDP 上下文的最大数量,默认为 128 个。
- `-o`选项:UDP 上下文的超时时间,默认为 30 秒。
- `-j`选项:需要启动的工作线程数量,默认为单个线程。
- `-n`选项:设置 ipt2socks 进程可打开的文件描述符限制。
- `-u`选项:即 run-as-user 功能,需要 root 权限才能生效。
Expand Down
197 changes: 113 additions & 84 deletions ipt2socks.c

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion lrucache.c
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
#include "lrucache.h"
#undef _GNU_SOURCE

static uint16_t g_lrucache_maxsize = 256;
static uint16_t g_lrucache_maxsize = 128;

uint16_t lrucache_get_maxsize(void) {
return g_lrucache_maxsize;
Expand Down
96 changes: 51 additions & 45 deletions netutils.c
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,18 @@ static inline void set_reuse_port(int sockfd) {
}
}

static inline void set_tfo_accept(int sockfd) {
if (setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN, &(int){5}, sizeof(int)) < 0) {
LOGERR("[set_tfo_accept] setsockopt(%d, TCP_FASTOPEN): %s", sockfd, my_strerror(errno));
}
}

static inline void set_tcp_syncnt(int sockfd, int syncnt) {
if (setsockopt(sockfd, IPPROTO_TCP, TCP_SYNCNT, &syncnt, sizeof(int)) < 0) {
LOGERR("[set_tcp_syncnt] setsockopt(%d, TCP_SYNCNT): %s", sockfd, my_strerror(errno));
}
}

static inline void set_tcp_nodelay(int sockfd) {
if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &(int){1}, sizeof(int)) < 0) {
LOGERR("[set_tcp_nodelay] setsockopt(%d, TCP_NODELAY): %s", sockfd, my_strerror(errno));
Expand All @@ -181,15 +193,32 @@ static inline void set_tcp_quickack(int sockfd) {
}
}

static inline void set_tfo_accept(int sockfd) {
if (setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN, &(int){5}, sizeof(int)) < 0) {
LOGERR("[set_tfo_accept] setsockopt(%d, TCP_FASTOPEN): %s", sockfd, my_strerror(errno));
static inline void set_tcp_solinger0(int sockfd) {
if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &(struct linger){.l_onoff = 1, .l_linger = 0}, sizeof(struct linger)) < 0) {
LOGERR("[set_tcp_solinger0] setsockopt(%d, SO_LINGER): %s", sockfd, my_strerror(errno));
}
}

static inline void set_tcp_syncnt(int sockfd, int syncnt) {
if (setsockopt(sockfd, IPPROTO_TCP, TCP_SYNCNT, &syncnt, sizeof(int)) < 0) {
LOGERR("[set_tcp_syncnt] setsockopt(%d, TCP_SYNCNT): %s", sockfd, my_strerror(errno));
static inline void set_tcp_keepalive(int sockfd) {
/* enable tcp_keepalive */
if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &(int){1}, sizeof(int)) < 0) {
LOGERR("[set_tcp_keepalive] setsockopt(%d, SO_KEEPALIVE): %s", sockfd, my_strerror(errno));
return;
}
/* tcp connection idle sec */
if (setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &(int){60}, sizeof(int)) < 0) {
LOGERR("[set_tcp_keepalive] setsockopt(%d, TCP_KEEPIDLE): %s", sockfd, my_strerror(errno));
return;
}
/* keepalive probe retry max count */
if (setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT, &(int){3}, sizeof(int)) < 0) {
LOGERR("[set_tcp_keepalive] setsockopt(%d, TCP_KEEPCNT): %s", sockfd, my_strerror(errno));
return;
}
/* keepalive probe retry interval sec */
if (setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, &(int){5}, sizeof(int)) < 0) {
LOGERR("[set_tcp_keepalive] setsockopt(%d, TCP_KEEPINTVL): %s", sockfd, my_strerror(errno));
return;
}
}

Expand Down Expand Up @@ -225,12 +254,7 @@ static inline void setup_accepted_sockfd(int sockfd) {
set_non_block(sockfd);
set_tcp_nodelay(sockfd);
set_tcp_quickack(sockfd);
}

static inline void send_reset_to_peer(int sockfd) {
if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &(struct linger){.l_onoff = 1, .l_linger = 0}, sizeof(struct linger)) < 0) {
LOGERR("[send_reset_to_peer] setsockopt(%d, SO_LINGER): %s", sockfd, my_strerror(errno));
}
set_tcp_keepalive(sockfd);
}

static inline int new_nonblock_sockfd(int family, int sktype) {
Expand All @@ -257,6 +281,7 @@ int new_tcp_connect_sockfd(int family, uint8_t tcp_syncnt) {
int sockfd = new_nonblock_sockfd(family, SOCK_STREAM);
set_tcp_nodelay(sockfd);
set_tcp_quickack(sockfd);
set_tcp_keepalive(sockfd);
if (tcp_syncnt) set_tcp_syncnt(sockfd, tcp_syncnt);
return sockfd;
}
Expand Down Expand Up @@ -320,50 +345,31 @@ bool get_udp_orig_dstaddr(int family, struct msghdr *msg, void *dstaddr) {
return false;
}

bool tcp_accept(int sockfd, int *conn_sockfd, void *from_skaddr) {
*conn_sockfd = accept(sockfd, from_skaddr, from_skaddr ? &(socklen_t){sizeof(skaddr6_t)} : NULL);
if (*conn_sockfd < 0 && errno != EAGAIN && errno != EWOULDBLOCK) return false;
if (*conn_sockfd >= 0) setup_accepted_sockfd(*conn_sockfd);
return true;
/* same as `accept()`, just a simple wrapper */
int tcp_accept(int sockfd, void *addr, socklen_t *addrlen) {
int newsockfd = accept(sockfd, addr, addrlen);
if (newsockfd >= 0) setup_accepted_sockfd(newsockfd);
return newsockfd;
}

bool tcp_connect(int sockfd, const void *skaddr, const void *data, size_t datalen, ssize_t *nsend) {
socklen_t skaddrlen = ((skaddr4_t *)skaddr)->sin_family == AF_INET ? sizeof(skaddr4_t) : sizeof(skaddr6_t);
if (data && datalen && nsend) {
if ((*nsend = sendto(sockfd, data, datalen, MSG_FASTOPEN, skaddr, skaddrlen)) < 0 && errno != EINPROGRESS) return false;
/* return: is_succ, tfo_succ if tfo_nsend >= 0 */
bool tcp_connect(int sockfd, const void *addr, const void *tfo_data, size_t tfo_datalen, ssize_t *tfo_nsend) {
socklen_t addrlen = ((skaddr4_t *)addr)->sin_family == AF_INET ? sizeof(skaddr4_t) : sizeof(skaddr6_t);
if (tfo_data && tfo_datalen && tfo_nsend) {
if ((*tfo_nsend = sendto(sockfd, tfo_data, tfo_datalen, MSG_FASTOPEN, addr, addrlen)) < 0 && errno != EINPROGRESS) return false;
} else {
if (connect(sockfd, skaddr, skaddrlen) < 0 && errno != EINPROGRESS) return false;
if (connect(sockfd, addr, addrlen) < 0 && errno != EINPROGRESS) return false;
}
return true;
}

/* on connect error, errno is set appropriately */
bool tcp_has_error(int sockfd) {
return getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &errno, &(socklen_t){sizeof(errno)}) < 0 || errno;
}

bool tcp_recv_data(int sockfd, void *data, size_t datalen, size_t *nrecv, bool *is_eof) {
ssize_t ret = recv(sockfd, data + *nrecv, datalen - *nrecv, 0);
if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
return false;
} else if (ret == 0) {
*is_eof = true;
} else if (ret > 0) {
*nrecv += ret;
}
return true;
}

bool tcp_send_data(int sockfd, const void *data, size_t datalen, size_t *nsend) {
ssize_t ret = send(sockfd, data + *nsend, datalen - *nsend, 0);
if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
return false;
} else if (ret > 0) {
*nsend += ret;
}
return true;
}

/* set so_linger(delay=0) and call close(sockfd) */
void tcp_close_by_rst(int sockfd) {
send_reset_to_peer(sockfd);
set_tcp_solinger0(sockfd);
close(sockfd);
}
16 changes: 10 additions & 6 deletions netutils.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,12 +59,16 @@ int new_udp_normal_sockfd(int family);
bool get_tcp_orig_dstaddr(int family, int sockfd, void *dstaddr, bool is_tproxy);
bool get_udp_orig_dstaddr(int family, struct msghdr *msg, void *dstaddr);

/* false if error (errno is set); true if EAGAIN or succeed */
bool tcp_accept(int sockfd, int *conn_sockfd, void *from_skaddr);
bool tcp_connect(int sockfd, const void *skaddr, const void *data, size_t datalen, ssize_t *nsend);
bool tcp_has_error(int sockfd); /* getsockopt(SO_ERROR), save to errno */
bool tcp_recv_data(int sockfd, void *data, size_t datalen, size_t *nrecv, bool *is_eof);
bool tcp_send_data(int sockfd, const void *data, size_t datalen, size_t *nsend);
/* same as `accept()`, just a simple wrapper */
int tcp_accept(int sockfd, void *addr, socklen_t *addrlen);

/* return: is_succ, tfo_succ if tfo_nsend >= 0 */
bool tcp_connect(int sockfd, const void *addr, const void *tfo_data, size_t tfo_datalen, ssize_t *tfo_nsend);

/* on connect error, errno is set appropriately */
bool tcp_has_error(int sockfd);

/* set so_linger(delay=0) and call close(sockfd) */
void tcp_close_by_rst(int sockfd);

#endif
6 changes: 1 addition & 5 deletions protocol.c
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ bool socks5_usrpwd_response_check(const char *funcname, const socks5_usrpwdresp_
return true;
}

bool socks5_proxy_response_check(const char *funcname, const socks5_ipv4resp_t *response, bool isipv4) {
bool socks5_proxy_response_check(const char *funcname, const socks5_ipv4resp_t *response) {
if (response->version != SOCKS5_VERSION) {
LOGERR("[%s] response->version:%#hhx is not SOCKS5:%#hhx", funcname, response->version, SOCKS5_VERSION);
return false;
Expand All @@ -120,9 +120,5 @@ bool socks5_proxy_response_check(const char *funcname, const socks5_ipv4resp_t *
LOGERR("[%s] response->respcode:%#hhx(%s) is not SUCCEEDED:%#hhx", funcname, response->respcode, socks5_rcode2string(response->respcode), SOCKS5_RESPCODE_SUCCEEDED);
return false;
}
if (response->addrtype != (isipv4 ? SOCKS5_ADDRTYPE_IPV4 : SOCKS5_ADDRTYPE_IPV6)) {
LOGERR("[%s] response->addrtype:%#hhx is not ADDRTYPE_IPV%s:%#hhx", funcname, response->addrtype, isipv4 ? "4" : "6", isipv4 ? SOCKS5_ADDRTYPE_IPV4 : SOCKS5_ADDRTYPE_IPV6);
return false;
}
return true;
}
2 changes: 1 addition & 1 deletion protocol.h
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,6 @@ void socks5_proxy_request_make(socks5_ipv4req_t *request, const void *skaddr);

bool socks5_auth_response_check(const char *funcname, const socks5_authresp_t *response);
bool socks5_usrpwd_response_check(const char *funcname, const socks5_usrpwdresp_t *response);
bool socks5_proxy_response_check(const char *funcname, const socks5_ipv4resp_t *response, bool isipv4);
bool socks5_proxy_response_check(const char *funcname, const socks5_ipv4resp_t *response);

#endif

0 comments on commit d4d2f37

Please sign in to comment.