Skip to content

Commit d4d2f37

Browse files
committed
fix ipv6 bug
2 parents 9c54768 + 7938d47 commit d4d2f37

File tree

7 files changed

+181
-146
lines changed

7 files changed

+181
-146
lines changed

README.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ usage: ipt2socks <options...>. the existing options are as follows:
3737
-l, --listen-port <port> listen port number, default: 60080
3838
-f, --buffer-size <size> tcp socket recv bufsize, default: 8192
3939
-S, --tcp-syncnt <cnt> change the number of tcp syn retransmits
40-
-c, --cache-size <size> udp context cache maxsize, default: 256
41-
-o, --udp-timeout <sec> udp context idle timeout, default: 180
40+
-c, --cache-size <size> udp context cache maxsize, default: 128
41+
-o, --udp-timeout <sec> udp context idle timeout, default: 30
4242
-j, --thread-nums <num> number of the worker threads, default: 1
4343
-n, --nofile-limit <num> set nofile limit, may need root privilege
4444
-u, --run-user <user> run as the given user, need root privilege
@@ -63,8 +63,8 @@ usage: ipt2socks <options...>. the existing options are as follows:
6363
- `-l`选项:本地 IPv4/6 监听端口,默认为 60080。
6464
- `-f`选项:TCP 套接字的缓冲区大小,默认为 8192 字节。
6565
- `-S`选项:与 socks5 服务器建立 TCP 连接的超时参数。
66-
- `-c`选项:UDP 上下文的最大数量,默认为 256 个。
67-
- `-o`选项:UDP 上下文的超时时间,默认为 180 秒。
66+
- `-c`选项:UDP 上下文的最大数量,默认为 128 个。
67+
- `-o`选项:UDP 上下文的超时时间,默认为 30 秒。
6868
- `-j`选项:需要启动的工作线程数量,默认为单个线程。
6969
- `-n`选项:设置 ipt2socks 进程可打开的文件描述符限制。
7070
- `-u`选项:即 run-as-user 功能,需要 root 权限才能生效。

ipt2socks.c

+113-84
Large diffs are not rendered by default.

lrucache.c

+1-1
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
#include "lrucache.h"
33
#undef _GNU_SOURCE
44

5-
static uint16_t g_lrucache_maxsize = 256;
5+
static uint16_t g_lrucache_maxsize = 128;
66

77
uint16_t lrucache_get_maxsize(void) {
88
return g_lrucache_maxsize;

netutils.c

+51-45
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,18 @@ static inline void set_reuse_port(int sockfd) {
169169
}
170170
}
171171

172+
static inline void set_tfo_accept(int sockfd) {
173+
if (setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN, &(int){5}, sizeof(int)) < 0) {
174+
LOGERR("[set_tfo_accept] setsockopt(%d, TCP_FASTOPEN): %s", sockfd, my_strerror(errno));
175+
}
176+
}
177+
178+
static inline void set_tcp_syncnt(int sockfd, int syncnt) {
179+
if (setsockopt(sockfd, IPPROTO_TCP, TCP_SYNCNT, &syncnt, sizeof(int)) < 0) {
180+
LOGERR("[set_tcp_syncnt] setsockopt(%d, TCP_SYNCNT): %s", sockfd, my_strerror(errno));
181+
}
182+
}
183+
172184
static inline void set_tcp_nodelay(int sockfd) {
173185
if (setsockopt(sockfd, IPPROTO_TCP, TCP_NODELAY, &(int){1}, sizeof(int)) < 0) {
174186
LOGERR("[set_tcp_nodelay] setsockopt(%d, TCP_NODELAY): %s", sockfd, my_strerror(errno));
@@ -181,15 +193,32 @@ static inline void set_tcp_quickack(int sockfd) {
181193
}
182194
}
183195

184-
static inline void set_tfo_accept(int sockfd) {
185-
if (setsockopt(sockfd, IPPROTO_TCP, TCP_FASTOPEN, &(int){5}, sizeof(int)) < 0) {
186-
LOGERR("[set_tfo_accept] setsockopt(%d, TCP_FASTOPEN): %s", sockfd, my_strerror(errno));
196+
static inline void set_tcp_solinger0(int sockfd) {
197+
if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &(struct linger){.l_onoff = 1, .l_linger = 0}, sizeof(struct linger)) < 0) {
198+
LOGERR("[set_tcp_solinger0] setsockopt(%d, SO_LINGER): %s", sockfd, my_strerror(errno));
187199
}
188200
}
189201

190-
static inline void set_tcp_syncnt(int sockfd, int syncnt) {
191-
if (setsockopt(sockfd, IPPROTO_TCP, TCP_SYNCNT, &syncnt, sizeof(int)) < 0) {
192-
LOGERR("[set_tcp_syncnt] setsockopt(%d, TCP_SYNCNT): %s", sockfd, my_strerror(errno));
202+
static inline void set_tcp_keepalive(int sockfd) {
203+
/* enable tcp_keepalive */
204+
if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, &(int){1}, sizeof(int)) < 0) {
205+
LOGERR("[set_tcp_keepalive] setsockopt(%d, SO_KEEPALIVE): %s", sockfd, my_strerror(errno));
206+
return;
207+
}
208+
/* tcp connection idle sec */
209+
if (setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPIDLE, &(int){60}, sizeof(int)) < 0) {
210+
LOGERR("[set_tcp_keepalive] setsockopt(%d, TCP_KEEPIDLE): %s", sockfd, my_strerror(errno));
211+
return;
212+
}
213+
/* keepalive probe retry max count */
214+
if (setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPCNT, &(int){3}, sizeof(int)) < 0) {
215+
LOGERR("[set_tcp_keepalive] setsockopt(%d, TCP_KEEPCNT): %s", sockfd, my_strerror(errno));
216+
return;
217+
}
218+
/* keepalive probe retry interval sec */
219+
if (setsockopt(sockfd, IPPROTO_TCP, TCP_KEEPINTVL, &(int){5}, sizeof(int)) < 0) {
220+
LOGERR("[set_tcp_keepalive] setsockopt(%d, TCP_KEEPINTVL): %s", sockfd, my_strerror(errno));
221+
return;
193222
}
194223
}
195224

@@ -225,12 +254,7 @@ static inline void setup_accepted_sockfd(int sockfd) {
225254
set_non_block(sockfd);
226255
set_tcp_nodelay(sockfd);
227256
set_tcp_quickack(sockfd);
228-
}
229-
230-
static inline void send_reset_to_peer(int sockfd) {
231-
if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER, &(struct linger){.l_onoff = 1, .l_linger = 0}, sizeof(struct linger)) < 0) {
232-
LOGERR("[send_reset_to_peer] setsockopt(%d, SO_LINGER): %s", sockfd, my_strerror(errno));
233-
}
257+
set_tcp_keepalive(sockfd);
234258
}
235259

236260
static inline int new_nonblock_sockfd(int family, int sktype) {
@@ -257,6 +281,7 @@ int new_tcp_connect_sockfd(int family, uint8_t tcp_syncnt) {
257281
int sockfd = new_nonblock_sockfd(family, SOCK_STREAM);
258282
set_tcp_nodelay(sockfd);
259283
set_tcp_quickack(sockfd);
284+
set_tcp_keepalive(sockfd);
260285
if (tcp_syncnt) set_tcp_syncnt(sockfd, tcp_syncnt);
261286
return sockfd;
262287
}
@@ -320,50 +345,31 @@ bool get_udp_orig_dstaddr(int family, struct msghdr *msg, void *dstaddr) {
320345
return false;
321346
}
322347

323-
bool tcp_accept(int sockfd, int *conn_sockfd, void *from_skaddr) {
324-
*conn_sockfd = accept(sockfd, from_skaddr, from_skaddr ? &(socklen_t){sizeof(skaddr6_t)} : NULL);
325-
if (*conn_sockfd < 0 && errno != EAGAIN && errno != EWOULDBLOCK) return false;
326-
if (*conn_sockfd >= 0) setup_accepted_sockfd(*conn_sockfd);
327-
return true;
348+
/* same as `accept()`, just a simple wrapper */
349+
int tcp_accept(int sockfd, void *addr, socklen_t *addrlen) {
350+
int newsockfd = accept(sockfd, addr, addrlen);
351+
if (newsockfd >= 0) setup_accepted_sockfd(newsockfd);
352+
return newsockfd;
328353
}
329354

330-
bool tcp_connect(int sockfd, const void *skaddr, const void *data, size_t datalen, ssize_t *nsend) {
331-
socklen_t skaddrlen = ((skaddr4_t *)skaddr)->sin_family == AF_INET ? sizeof(skaddr4_t) : sizeof(skaddr6_t);
332-
if (data && datalen && nsend) {
333-
if ((*nsend = sendto(sockfd, data, datalen, MSG_FASTOPEN, skaddr, skaddrlen)) < 0 && errno != EINPROGRESS) return false;
355+
/* return: is_succ, tfo_succ if tfo_nsend >= 0 */
356+
bool tcp_connect(int sockfd, const void *addr, const void *tfo_data, size_t tfo_datalen, ssize_t *tfo_nsend) {
357+
socklen_t addrlen = ((skaddr4_t *)addr)->sin_family == AF_INET ? sizeof(skaddr4_t) : sizeof(skaddr6_t);
358+
if (tfo_data && tfo_datalen && tfo_nsend) {
359+
if ((*tfo_nsend = sendto(sockfd, tfo_data, tfo_datalen, MSG_FASTOPEN, addr, addrlen)) < 0 && errno != EINPROGRESS) return false;
334360
} else {
335-
if (connect(sockfd, skaddr, skaddrlen) < 0 && errno != EINPROGRESS) return false;
361+
if (connect(sockfd, addr, addrlen) < 0 && errno != EINPROGRESS) return false;
336362
}
337363
return true;
338364
}
339365

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

344-
bool tcp_recv_data(int sockfd, void *data, size_t datalen, size_t *nrecv, bool *is_eof) {
345-
ssize_t ret = recv(sockfd, data + *nrecv, datalen - *nrecv, 0);
346-
if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
347-
return false;
348-
} else if (ret == 0) {
349-
*is_eof = true;
350-
} else if (ret > 0) {
351-
*nrecv += ret;
352-
}
353-
return true;
354-
}
355-
356-
bool tcp_send_data(int sockfd, const void *data, size_t datalen, size_t *nsend) {
357-
ssize_t ret = send(sockfd, data + *nsend, datalen - *nsend, 0);
358-
if (ret < 0 && errno != EAGAIN && errno != EWOULDBLOCK) {
359-
return false;
360-
} else if (ret > 0) {
361-
*nsend += ret;
362-
}
363-
return true;
364-
}
365-
371+
/* set so_linger(delay=0) and call close(sockfd) */
366372
void tcp_close_by_rst(int sockfd) {
367-
send_reset_to_peer(sockfd);
373+
set_tcp_solinger0(sockfd);
368374
close(sockfd);
369375
}

netutils.h

+10-6
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,16 @@ int new_udp_normal_sockfd(int family);
5959
bool get_tcp_orig_dstaddr(int family, int sockfd, void *dstaddr, bool is_tproxy);
6060
bool get_udp_orig_dstaddr(int family, struct msghdr *msg, void *dstaddr);
6161

62-
/* false if error (errno is set); true if EAGAIN or succeed */
63-
bool tcp_accept(int sockfd, int *conn_sockfd, void *from_skaddr);
64-
bool tcp_connect(int sockfd, const void *skaddr, const void *data, size_t datalen, ssize_t *nsend);
65-
bool tcp_has_error(int sockfd); /* getsockopt(SO_ERROR), save to errno */
66-
bool tcp_recv_data(int sockfd, void *data, size_t datalen, size_t *nrecv, bool *is_eof);
67-
bool tcp_send_data(int sockfd, const void *data, size_t datalen, size_t *nsend);
62+
/* same as `accept()`, just a simple wrapper */
63+
int tcp_accept(int sockfd, void *addr, socklen_t *addrlen);
64+
65+
/* return: is_succ, tfo_succ if tfo_nsend >= 0 */
66+
bool tcp_connect(int sockfd, const void *addr, const void *tfo_data, size_t tfo_datalen, ssize_t *tfo_nsend);
67+
68+
/* on connect error, errno is set appropriately */
69+
bool tcp_has_error(int sockfd);
70+
71+
/* set so_linger(delay=0) and call close(sockfd) */
6872
void tcp_close_by_rst(int sockfd);
6973

7074
#endif

protocol.c

+1-5
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ bool socks5_usrpwd_response_check(const char *funcname, const socks5_usrpwdresp_
111111
return true;
112112
}
113113

114-
bool socks5_proxy_response_check(const char *funcname, const socks5_ipv4resp_t *response, bool isipv4) {
114+
bool socks5_proxy_response_check(const char *funcname, const socks5_ipv4resp_t *response) {
115115
if (response->version != SOCKS5_VERSION) {
116116
LOGERR("[%s] response->version:%#hhx is not SOCKS5:%#hhx", funcname, response->version, SOCKS5_VERSION);
117117
return false;
@@ -120,9 +120,5 @@ bool socks5_proxy_response_check(const char *funcname, const socks5_ipv4resp_t *
120120
LOGERR("[%s] response->respcode:%#hhx(%s) is not SUCCEEDED:%#hhx", funcname, response->respcode, socks5_rcode2string(response->respcode), SOCKS5_RESPCODE_SUCCEEDED);
121121
return false;
122122
}
123-
if (response->addrtype != (isipv4 ? SOCKS5_ADDRTYPE_IPV4 : SOCKS5_ADDRTYPE_IPV6)) {
124-
LOGERR("[%s] response->addrtype:%#hhx is not ADDRTYPE_IPV%s:%#hhx", funcname, response->addrtype, isipv4 ? "4" : "6", isipv4 ? SOCKS5_ADDRTYPE_IPV4 : SOCKS5_ADDRTYPE_IPV6);
125-
return false;
126-
}
127123
return true;
128124
}

protocol.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -140,6 +140,6 @@ void socks5_proxy_request_make(socks5_ipv4req_t *request, const void *skaddr);
140140

141141
bool socks5_auth_response_check(const char *funcname, const socks5_authresp_t *response);
142142
bool socks5_usrpwd_response_check(const char *funcname, const socks5_usrpwdresp_t *response);
143-
bool socks5_proxy_response_check(const char *funcname, const socks5_ipv4resp_t *response, bool isipv4);
143+
bool socks5_proxy_response_check(const char *funcname, const socks5_ipv4resp_t *response);
144144

145145
#endif

0 commit comments

Comments
 (0)