Skip to content
This repository was archived by the owner on Aug 22, 2021. It is now read-only.

Commit e837e8d

Browse files
committed
tun2socks: Remove localhost limination for SOCKS5 UDP.
The UDP socket is bound to the same IP address as was automatically selected for the TCP socket, and the port number is set to zero to let the kernel pick it. The actual bound address with the assigned port number is sent to the SOCKS server as DST.ADDR.
1 parent 6241fc2 commit e837e8d

File tree

9 files changed

+254
-99
lines changed

9 files changed

+254
-99
lines changed

socks_udp_client/SocksUdpClient.c

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -83,17 +83,52 @@ void socks_state_handler (struct SocksUdpClient_connection *con, int event)
8383
DebugObject_Access(&con->client->d_obj);
8484

8585
switch (event) {
86-
case BSOCKSCLIENT_EVENT_UP: {
87-
// Figure out the localhost address.
88-
BIPAddr localhost;
89-
BIPAddr_InitLocalhost(&localhost, con->client->server_addr.type);
86+
case BSOCKSCLIENT_EVENT_CONNECTED: {
87+
// Get the local address of the SOCKS TCP connection.
88+
BAddr tcp_local_addr;
89+
if (!BSocksClient_GetLocalAddr(&con->socks, &tcp_local_addr)) {
90+
BLog(BLOG_ERROR, "Failed to get TCP local address.");
91+
return connection_free(con);
92+
}
93+
94+
// Sanity check the address type (required by SetPort below).
95+
if (tcp_local_addr.type != BADDR_TYPE_IPV4 &&
96+
tcp_local_addr.type != BADDR_TYPE_IPV6)
97+
{
98+
BLog(BLOG_ERROR, "Bad address type in TCP local address.");
99+
return connection_free(con);
100+
}
101+
102+
// Bind the UDP socket to the same IP address and let the kernel pick the port.
103+
BAddr udp_bound_addr = tcp_local_addr;
104+
BAddr_SetPort(&udp_bound_addr, 0);
105+
if (!BDatagram_Bind(&con->socket, udp_bound_addr)) {
106+
BLog(BLOG_ERROR, "Failed to bind the UDP socket.");
107+
return connection_free(con);
108+
}
109+
110+
// Update udp_bound_addr to the actual address that was bound.
111+
if (!BDatagram_GetLocalAddr(&con->socket, &udp_bound_addr)) {
112+
BLog(BLOG_ERROR, "Failed to get UDP bound address.");
113+
return connection_free(con);
114+
}
115+
116+
// Set the DST.ADDR for SOCKS.
117+
BSocksClient_SetDestAddr(&con->socks, udp_bound_addr);
118+
} break;
90119

91-
// Get the address to send datagrams to from BSocksClient.
120+
case BSOCKSCLIENT_EVENT_UP: {
121+
// The remote address to send datagrams to is the BND.ADDR provided by the
122+
// SOCKS server.
92123
BAddr remote_addr = BSocksClient_GetBindAddr(&con->socks);
93124

94-
// Set the local/remote send address for BDatagram.
125+
// Don't bother setting a source address for datagrams since we are bound.
126+
BIPAddr local_addr;
127+
BIPAddr_InitInvalid(&local_addr);
128+
129+
// Set the addresses for BDatagram.
95130
// This will unblock the queue of outgoing packets.
96-
BDatagram_SetSendAddrs(&con->socket, remote_addr, localhost);
131+
BDatagram_SetSendAddrs(&con->socket, remote_addr, local_addr);
97132
} break;
98133

99134
case BSOCKSCLIENT_EVENT_ERROR: {
@@ -113,10 +148,6 @@ void socks_state_handler (struct SocksUdpClient_connection *con, int event)
113148

114149
connection_free(con);
115150
} break;
116-
117-
default: {
118-
BLog(BLOG_ERROR, "Unknown SOCKS event");
119-
} break;
120151
}
121152
}
122153

@@ -294,31 +325,13 @@ struct SocksUdpClient_connection * connection_init (
294325
goto fail2;
295326
}
296327

297-
// Bind to localhost, port 0 signals the kernel to choose an open port.
298-
BIPAddr localhost;
299-
BIPAddr_InitLocalhost(&localhost, local_addr.type);
300-
BAddr socket_addr = BAddr_MakeFromIpaddrAndPort(localhost, 0);
301-
if (!BDatagram_Bind(&con->socket, socket_addr)) {
302-
BLog(BLOG_ERROR, "Bind to localhost failed");
303-
goto fail3;
304-
}
305-
306-
// Bind succeeded, so the kernel has found an open port.
307-
// Update socket_addr to the actual port that was bound.
308-
uint16_t port;
309-
if (!BDatagram_GetLocalPort(&con->socket, &port)) {
310-
BLog(BLOG_ERROR, "Failed to get bound port");
311-
goto fail3;
312-
}
313-
if (socket_addr.type == BADDR_TYPE_IPV4) {
314-
socket_addr.ipv4.port = port;
315-
} else {
316-
socket_addr.ipv6.port = port;
317-
}
318-
328+
// We will set the DST.ADDR for SOCKS later (BSOCKSCLIENT_EVENT_CONNECTED).
329+
BAddr dummy_dst_addr;
330+
BAddr_InitNone(&dummy_dst_addr);
331+
319332
// Initiate connection to socks server
320333
if (!BSocksClient_Init(&con->socks, o->server_addr, o->auth_info, o->num_auth_info,
321-
socket_addr, true, (BSocksClient_handler)socks_state_handler, con, o->reactor))
334+
dummy_dst_addr, true, (BSocksClient_handler)socks_state_handler, con, o->reactor))
322335
{
323336
BLog(BLOG_ERROR, "Failed to initialize SOCKS client");
324337
goto fail3;

socks_udp_client/SocksUdpClient.h

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -94,17 +94,12 @@ struct SocksUdpClient_connection {
9494
*
9595
* This function only initialzies the object and does not perform network access.
9696
*
97-
* Currently, this function only supports connection to a SOCKS5 server that is routable from
98-
* localhost (i.e. running on the local machine). It may be possible to add support for
99-
* remote servers, but SOCKS5 does not support UDP if there is a NAT or firewall between the
100-
* client and the proxy.
101-
*
10297
* @param o the object
10398
* @param udp_mtu the maximum size of packets that will be sent through the tunnel
10499
* @param max_connections how many local ports to track before dropping packets
105100
* @param send_buf_size maximum number of buffered outgoing packets per connection
106101
* @param keepalive_time how long to track an idle local port before forgetting it
107-
* @param server_addr SOCKS5 server address. MUST BE ON LOCALHOST.
102+
* @param server_addr SOCKS5 server address
108103
* @param auth_info List of authentication info for BSocksClient. The pointer must remain
109104
* valid while this object exists, the data is not copied.
110105
* @param num_auth_info Number of the above.

socksclient/BSocksClient.c

Lines changed: 85 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,15 @@
3838
#include <generated/blog_channel_BSocksClient.h>
3939

4040
#define STATE_CONNECTING 1
41-
#define STATE_SENDING_HELLO 2
42-
#define STATE_SENT_HELLO 3
43-
#define STATE_SENDING_PASSWORD 10
44-
#define STATE_SENT_PASSWORD 11
45-
#define STATE_SENDING_REQUEST 4
46-
#define STATE_SENT_REQUEST 5
47-
#define STATE_RECEIVED_REPLY_HEADER 6
48-
#define STATE_UP 7
41+
#define STATE_CONNECTED_HANDLER 2
42+
#define STATE_SENDING_HELLO 3
43+
#define STATE_SENT_HELLO 4
44+
#define STATE_SENDING_PASSWORD 5
45+
#define STATE_SENT_PASSWORD 6
46+
#define STATE_SENDING_REQUEST 7
47+
#define STATE_SENT_REQUEST 8
48+
#define STATE_RECEIVED_REPLY_HEADER 9
49+
#define STATE_UP 10
4950

5051
static void report_error (BSocksClient *o, int error);
5152
static void init_control_io (BSocksClient *o);
@@ -57,6 +58,7 @@ static void start_receive (BSocksClient *o, uint8_t *dest, int total);
5758
static void do_receive (BSocksClient *o);
5859
static void connector_handler (BSocksClient* o, int is_error);
5960
static void connection_handler (BSocksClient* o, int event);
61+
static void continue_job_handler (BSocksClient *o);
6062
static void recv_handler_done (BSocksClient *o, int data_len);
6163
static void send_handler_done (BSocksClient *o);
6264
static void auth_finished (BSocksClient *p);
@@ -166,12 +168,45 @@ void connector_handler (BSocksClient* o, int is_error)
166168
// init control I/O
167169
init_control_io(o);
168170

171+
// go to STATE_CONNECTED_HANDLER and set the continue job in order to continue
172+
// in continue_job_handler
173+
o->state = STATE_CONNECTED_HANDLER;
174+
BPending_Set(&o->continue_job);
175+
176+
// call the handler with the connected event
177+
o->handler(o->user, BSOCKSCLIENT_EVENT_CONNECTED);
178+
return;
179+
180+
fail0:
181+
report_error(o, BSOCKSCLIENT_EVENT_ERROR);
182+
return;
183+
}
184+
185+
void connection_handler (BSocksClient* o, int event)
186+
{
187+
DebugObject_Access(&o->d_obj);
188+
ASSERT(o->state != STATE_CONNECTING)
189+
190+
if (o->state == STATE_UP && event == BCONNECTION_EVENT_RECVCLOSED) {
191+
report_error(o, BSOCKSCLIENT_EVENT_ERROR_CLOSED);
192+
return;
193+
}
194+
195+
report_error(o, BSOCKSCLIENT_EVENT_ERROR);
196+
return;
197+
}
198+
199+
void continue_job_handler (BSocksClient *o)
200+
{
201+
DebugObject_Access(&o->d_obj);
202+
ASSERT(o->state == STATE_CONNECTED_HANDLER)
203+
169204
// check number of methods
170205
if (o->num_auth_info == 0 || o->num_auth_info > 255) {
171206
BLog(BLOG_ERROR, "invalid number of authentication methods");
172-
goto fail1;
207+
goto fail0;
173208
}
174-
209+
175210
// allocate buffer for sending hello
176211
bsize_t size = bsize_add(
177212
bsize_fromsize(sizeof(struct socks_client_hello_header)),
@@ -181,7 +216,7 @@ void connector_handler (BSocksClient* o, int is_error)
181216
)
182217
);
183218
if (!reserve_buffer(o, size)) {
184-
goto fail1;
219+
goto fail0;
185220
}
186221

187222
// write hello header
@@ -202,27 +237,10 @@ void connector_handler (BSocksClient* o, int is_error)
202237

203238
// set state
204239
o->state = STATE_SENDING_HELLO;
205-
206-
return;
207-
208-
fail1:
209-
free_control_io(o);
210-
BConnection_Free(&o->con);
211-
fail0:
212-
report_error(o, BSOCKSCLIENT_EVENT_ERROR);
240+
213241
return;
214-
}
215242

216-
void connection_handler (BSocksClient* o, int event)
217-
{
218-
DebugObject_Access(&o->d_obj);
219-
ASSERT(o->state != STATE_CONNECTING)
220-
221-
if (o->state == STATE_UP && event == BCONNECTION_EVENT_RECVCLOSED) {
222-
report_error(o, BSOCKSCLIENT_EVENT_ERROR_CLOSED);
223-
return;
224-
}
225-
243+
fail0:
226244
report_error(o, BSOCKSCLIENT_EVENT_ERROR);
227245
return;
228246
}
@@ -491,8 +509,16 @@ void auth_finished (BSocksClient *o)
491509
// allocate request buffer
492510
bsize_t size = bsize_fromsize(sizeof(struct socks_request_header));
493511
switch (o->dest_addr.type) {
494-
case BADDR_TYPE_IPV4: size = bsize_add(size, bsize_fromsize(sizeof(struct socks_addr_ipv4))); break;
495-
case BADDR_TYPE_IPV6: size = bsize_add(size, bsize_fromsize(sizeof(struct socks_addr_ipv6))); break;
512+
case BADDR_TYPE_IPV4:
513+
size = bsize_add(size, bsize_fromsize(sizeof(struct socks_addr_ipv4)));
514+
break;
515+
case BADDR_TYPE_IPV6:
516+
size = bsize_add(size, bsize_fromsize(sizeof(struct socks_addr_ipv6)));
517+
break;
518+
default:
519+
BLog(BLOG_ERROR, "Invalid dest_addr address type.");
520+
report_error(o, BSOCKSCLIENT_EVENT_ERROR);
521+
return;
496522
}
497523
if (!reserve_buffer(o, size)) {
498524
report_error(o, BSOCKSCLIENT_EVENT_ERROR);
@@ -549,12 +575,11 @@ struct BSocksClient_auth_info BSocksClient_auth_password (const char *username,
549575
return info;
550576
}
551577

552-
int BSocksClient_Init (BSocksClient *o,
553-
BAddr server_addr, const struct BSocksClient_auth_info *auth_info, size_t num_auth_info,
554-
BAddr dest_addr, bool udp, BSocksClient_handler handler, void *user, BReactor *reactor)
578+
int BSocksClient_Init (BSocksClient *o, BAddr server_addr,
579+
const struct BSocksClient_auth_info *auth_info, size_t num_auth_info, BAddr dest_addr,
580+
bool udp, BSocksClient_handler handler, void *user, BReactor *reactor)
555581
{
556582
ASSERT(!BAddr_IsInvalid(&server_addr))
557-
ASSERT(dest_addr.type == BADDR_TYPE_IPV4 || dest_addr.type == BADDR_TYPE_IPV6)
558583
#ifndef NDEBUG
559584
for (size_t i = 0; i < num_auth_info; i++) {
560585
ASSERT(auth_info[i].auth_type == SOCKS_METHOD_NO_AUTHENTICATION_REQUIRED ||
@@ -573,6 +598,10 @@ int BSocksClient_Init (BSocksClient *o,
573598

574599
// set no buffer
575600
o->buffer = NULL;
601+
602+
// init continue_job
603+
BPending_Init(&o->continue_job, BReactor_PendingGroup(o->reactor),
604+
(BPending_handler)continue_job_handler, o);
576605

577606
// init connector
578607
if (!BConnector_Init(&o->connector, server_addr, o->reactor, o, (BConnector_handler)connector_handler)) {
@@ -588,6 +617,7 @@ int BSocksClient_Init (BSocksClient *o,
588617
return 1;
589618

590619
fail0:
620+
BPending_Free(&o->continue_job);
591621
return 0;
592622
}
593623

@@ -612,12 +642,31 @@ void BSocksClient_Free (BSocksClient *o)
612642
// free connector
613643
BConnector_Free(&o->connector);
614644

645+
// free continue job
646+
BPending_Free(&o->continue_job);
647+
615648
// free buffer
616649
if (o->buffer) {
617650
BFree(o->buffer);
618651
}
619652
}
620653

654+
int BSocksClient_GetLocalAddr (BSocksClient *o, BAddr *local_addr)
655+
{
656+
ASSERT(o->state != STATE_CONNECTING)
657+
DebugObject_Access(&o->d_obj);
658+
659+
return BConnection_GetLocalAddress(&o->con, local_addr);
660+
}
661+
662+
void BSocksClient_SetDestAddr (BSocksClient *o, BAddr dest_addr)
663+
{
664+
ASSERT(o->state == STATE_CONNECTING || o->state == STATE_CONNECTED_HANDLER)
665+
DebugObject_Access(&o->d_obj);
666+
667+
o->dest_addr = dest_addr;
668+
}
669+
621670
BAddr BSocksClient_GetBindAddr (BSocksClient *o)
622671
{
623672
ASSERT(o->state == STATE_UP)

0 commit comments

Comments
 (0)