OpenVPN
socks.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2026 OpenVPN Inc <sales@openvpn.net>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2
12 * as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, see <https://www.gnu.org/licenses/>.
21 */
22
23/*
24 * 2004-01-30: Added Socks5 proxy support, see RFC 1928
25 * (Christof Meerwald, https://cmeerw.org)
26 *
27 * 2010-10-10: Added Socks5 plain text authentication support (RFC 1929)
28 * (Pierre Bourdon <delroth@gmail.com>)
29 */
30
31#ifdef HAVE_CONFIG_H
32#include "config.h"
33#endif
34
35#include "syshead.h"
36
37#include "common.h"
38#include "misc.h"
39#include "win32.h"
40#include "socket.h"
41#include "fdmisc.h"
42#include "misc.h"
43#include "proxy.h"
44#include "forward.h"
45
46#include "memdbg.h"
47
48#define UP_TYPE_SOCKS "SOCKS Proxy"
49
50struct socks_proxy_info *
51socks_proxy_new(const char *server, const char *port, const char *authfile)
52{
53 struct socks_proxy_info *p;
54
56
58 ASSERT(port);
59
60 strncpynt(p->server, server, sizeof(p->server));
61 p->port = port;
62
63 if (authfile)
64 {
65 strncpynt(p->authfile, authfile, sizeof(p->authfile));
66 }
67 else
68 {
69 p->authfile[0] = 0;
70 }
71
72 p->defined = true;
73
74 return p;
75}
76
77void
79{
80 free(sp);
81}
82
83static bool
84socks_proxy_recv_char(uint8_t *c, const char *name, socket_descriptor_t sd,
85 struct event_timeout *server_poll_timeout,
86 volatile int *signal_received)
87{
88 fd_set reads;
89 FD_ZERO(&reads);
90 openvpn_fd_set(sd, &reads);
91
92 struct timeval tv;
93 tv.tv_sec = get_server_poll_remaining_time(server_poll_timeout);
94 tv.tv_usec = 0;
95
96 return proxy_recv_char(c, name, sd, &tv, signal_received);
97}
98
99static bool
101 struct event_timeout *server_poll_timeout,
102 volatile int *signal_received)
103{
104 char to_send[516];
105 struct user_pass creds;
106 bool ret = false;
107
108 CLEAR(creds);
110 {
111 msg(M_NONFATAL, "SOCKS failed to get username/password.");
112 goto cleanup;
113 }
114
115 if ((strlen(creds.username) > 255) || (strlen(creds.password) > 255))
116 {
117 msg(M_NONFATAL, "SOCKS username and/or password exceeds 255 characters. "
118 "Authentication not possible.");
119 goto cleanup;
120 }
121
122 ASSERT(checked_snprintf(to_send, sizeof(to_send), "\x01%c%s%c%s",
123 (int)strlen(creds.username), creds.username,
124 (int)strlen(creds.password), creds.password));
125 if (!proxy_send(sd, to_send, strlen(to_send)))
126 {
127 goto cleanup;
128 }
129
130 int len = 0;
131 uint8_t buf[2];
132 while (len < 2)
133 {
134 uint8_t c;
135
136 if (!socks_proxy_recv_char(&c, __func__, sd, server_poll_timeout, signal_received))
137 {
138 goto cleanup;
139 }
140 /* store char in buffer */
141 buf[len++] = c;
142 }
143
144 /* VER = 5, SUCCESS = 0 --> auth success */
145 if (buf[0] != 5 || buf[1] != 0)
146 {
147 msg(D_LINK_ERRORS, "socks_username_password_auth: server refused the authentication");
148 goto cleanup;
149 }
150
151 ret = true;
152cleanup:
153 secure_memzero(&creds, sizeof(creds));
154 secure_memzero(to_send, sizeof(to_send));
155 return ret;
156}
157
158static bool
160 struct event_timeout *server_poll_timeout, volatile int *signal_received)
161{
162 uint8_t buf[2];
163 int len = 0;
164
165 /* VER = 5, NMETHODS = 1, METHODS = [0 (no auth)] */
166 uint8_t method_sel[3] = { 0x05, 0x01, 0x00 };
167 if (p->authfile[0])
168 {
169 method_sel[2] = 0x02; /* METHODS = [2 (plain login)] */
170 }
171 if (!proxy_send(sd, method_sel, sizeof(method_sel)))
172 {
173 return false;
174 }
175
176 while (len < 2)
177 {
178 uint8_t c;
179
180 if (!socks_proxy_recv_char(&c, __func__, sd, server_poll_timeout, signal_received))
181 {
182 return false;
183 }
184 /* store char in buffer */
185 buf[len++] = c;
186 }
187
188 /* VER == 5 */
189 if (buf[0] != 5)
190 {
191 msg(D_LINK_ERRORS, "socks_handshake: Socks proxy returned bad status");
192 return false;
193 }
194
195 /* validate that the auth method returned is the one sent */
196 if (buf[1] != method_sel[2])
197 {
198 msg(D_LINK_ERRORS, "socks_handshake: Socks proxy returned unexpected auth");
199 return false;
200 }
201
202 /* select the appropriate authentication method */
203 switch (buf[1])
204 {
205 case 0: /* no authentication */
206 break;
207
208 case 2: /* login/password */
209 if (!p->authfile[0])
210 {
212 "socks_handshake: server asked for username/login auth but we were "
213 "not provided any credentials");
214 return false;
215 }
216
217 if (!socks_username_password_auth(p, sd, server_poll_timeout, signal_received))
218 {
219 return false;
220 }
221
222 break;
223
224 default: /* unknown auth method */
225 msg(D_LINK_ERRORS, "socks_handshake: unknown SOCKS auth method");
226 return false;
227 }
228
229 return true;
230}
231
232static bool
234 struct event_timeout *server_poll_timeout, volatile int *signal_received)
235{
236 uint8_t atyp = 0;
237 int alen = 0;
238 int len = 0;
239 char buf[270]; /* 4 + alen(max 256) + 2 */
240
241 if (addr != NULL)
242 {
243 addr->addr.in4.sin_family = AF_INET;
244 addr->addr.in4.sin_addr.s_addr = htonl(INADDR_ANY);
245 addr->addr.in4.sin_port = htons(0);
246 }
247
248 while (len < 4 + alen + 2)
249 {
250 uint8_t c;
251
252 if (!socks_proxy_recv_char(&c, __func__, sd, server_poll_timeout, signal_received))
253 {
254 return false;
255 }
256
257 if (len == 3)
258 {
259 atyp = c;
260 }
261
262 if (len == 4)
263 {
264 switch (atyp)
265 {
266 case 1: /* IP V4 */
267 alen = 4;
268 break;
269
270 case 3: /* DOMAINNAME */
271 /* RFC 1928, section 5: 1 byte length, <n> bytes name,
272 * so the total "address length" is (length+1)
273 */
274 alen = c + 1;
275 break;
276
277 case 4: /* IP V6 */
278 alen = 16;
279 break;
280
281 default:
282 msg(D_LINK_ERRORS, "recv_socks_reply: Socks proxy returned bad address type");
283 return false;
284 }
285 }
286
287 /* store char in buffer */
288 if (len < (int)sizeof(buf))
289 {
290 buf[len] = c;
291 }
292 ++len;
293 }
294
295 /* VER == 5 && REP == 0 (succeeded) */
296 if (buf[0] != 5 || buf[1] != 0)
297 {
298 msg(D_LINK_ERRORS, "recv_socks_reply: Socks proxy returned bad reply");
299 return false;
300 }
301
302 /* ATYP == 1 (IP V4 address) */
303 if (atyp == 1 && addr != NULL)
304 {
305 memcpy(&addr->addr.in4.sin_addr, buf + 4, sizeof(addr->addr.in4.sin_addr));
306 memcpy(&addr->addr.in4.sin_port, buf + 8, sizeof(addr->addr.in4.sin_port));
307 struct gc_arena gc = gc_new();
308 msg(M_INFO, "SOCKS proxy wants us to send UDP to %s", print_openvpn_sockaddr(addr, &gc));
309 gc_free(&gc);
310 }
311
312
313 return true;
314}
315
316static int
317port_from_servname(const char *servname)
318{
319 int port = 0;
320 port = atoi(servname);
321 if (port > 0 && port < 65536)
322 {
323 return port;
324 }
325
326 struct servent *service;
327 service = getservbyname(servname, NULL);
328 if (service)
329 {
330 return service->s_port;
331 }
332
333 return 0;
334}
335
336void
338 socket_descriptor_t sd, /* already open to proxy */
339 const char *host, /* openvpn server remote */
340 const char *servname, /* openvpn server port */
341 struct event_timeout *server_poll_timeout,
342 struct signal_info *sig_info)
343{
344 char buf[270];
345 size_t len;
346
347 if (!socks_handshake(p, sd, server_poll_timeout, &sig_info->signal_received))
348 {
349 goto error;
350 }
351
352 /* format Socks CONNECT message */
353 buf[0] = '\x05'; /* VER = 5 */
354 buf[1] = '\x01'; /* CMD = 1 (CONNECT) */
355 buf[2] = '\x00'; /* RSV */
356 buf[3] = '\x03'; /* ATYP = 3 (DOMAINNAME) */
357
358 len = strlen(host);
359 len = (5 + len + 2 > sizeof(buf)) ? (sizeof(buf) - 5 - 2) : len;
360
361 buf[4] = (char)len;
362 memcpy(buf + 5, host, len);
363
364 int port = port_from_servname(servname);
365 if (port == 0)
366 {
367 msg(D_LINK_ERRORS, "establish_socks_proxy_passthrough: Cannot convert %s to port number",
368 servname);
369 goto error;
370 }
371
372 buf[5 + len] = (char)(port >> 8);
373 buf[5 + len + 1] = (char)(port & 0xff);
374
375 if (!proxy_send(sd, buf, 5 + len + 2))
376 {
377 goto error;
378 }
379
380 /* receive reply from Socks proxy and discard */
381 if (!recv_socks_reply(sd, NULL, server_poll_timeout, &sig_info->signal_received))
382 {
383 goto error;
384 }
385
386 return;
387
388error:
389 /* SOFT-SIGUSR1 -- socks error */
390 register_signal(sig_info, SIGUSR1, "socks-error");
391 return;
392}
393
394void
396 socket_descriptor_t ctrl_sd, /* already open to proxy */
397 struct openvpn_sockaddr *relay_addr,
398 struct event_timeout *server_poll_timeout,
399 struct signal_info *sig_info)
400{
401 if (!socks_handshake(p, ctrl_sd, server_poll_timeout, &sig_info->signal_received))
402 {
403 goto error;
404 }
405
406 {
407 /* send Socks UDP ASSOCIATE message */
408 /* VER = 5, CMD = 3 (UDP ASSOCIATE), RSV = 0, ATYP = 1 (IP V4),
409 * BND.ADDR = 0, BND.PORT = 0 */
410 const ssize_t size =
411 send(ctrl_sd, "\x05\x03\x00\x01\x00\x00\x00\x00\x00\x00", 10, MSG_NOSIGNAL);
412 if (size != 10)
413 {
414 msg(D_LINK_ERRORS | M_ERRNO, "%s: TCP port write failed on send()", __func__);
415 goto error;
416 }
417 }
418
419 /* receive reply from Socks proxy */
420 CLEAR(*relay_addr);
421 if (!recv_socks_reply(ctrl_sd, relay_addr, server_poll_timeout, &sig_info->signal_received))
422 {
423 goto error;
424 }
425 if (!relay_addr->addr.in4.sin_addr.s_addr)
426 {
427 msg(D_LINK_ERRORS, "%s: Socks proxy did not answer with IPv4 address", __func__);
428 goto error;
429 }
430
431 return;
432
433error:
434 /* SOFT-SIGUSR1 -- socks error */
435 register_signal(sig_info, SIGUSR1, "socks-error");
436 return;
437}
438
439/*
440 * Remove the socks5 header from an incoming
441 * UDP packet, setting *from to the source address.
442 *
443 * Run after UDP read.
444 */
445void
447{
448 int atyp;
449
450 if (BLEN(buf) < SOCKS_UDPv4_HEADROOM)
451 {
452 goto error;
453 }
454
455 buf_read_u16(buf);
456 if (buf_read_u8(buf) != 0)
457 {
458 goto error;
459 }
460
461 atyp = buf_read_u8(buf);
462 if (atyp != 1) /* ATYP == 1 (IP V4) */
463 {
464 goto error;
465 }
466
467 buf_read(buf, &from->dest.addr.in4.sin_addr, sizeof(from->dest.addr.in4.sin_addr));
468 buf_read(buf, &from->dest.addr.in4.sin_port, sizeof(from->dest.addr.in4.sin_port));
469
470 return;
471
472error:
473 buf->len = 0;
474}
475
476/*
477 * Add a socks header prior to UDP write.
478 * *to is the destination address.
479 *
480 * Run before UDP write.
481 * Returns the size of the header.
482 */
483int
485{
486 /*
487 * Get a subset buffer prepended to buf --
488 * we expect these bytes will be here because
489 * we always allocate space for these bytes
490 */
491 struct buffer head = buf_sub(buf, SOCKS_UDPv4_HEADROOM, true);
492
493 /* crash if not enough headroom in buf */
494 ASSERT(buf_defined(&head));
495
496 buf_write_u16(&head, 0); /* RSV = 0 */
497 buf_write_u8(&head, 0); /* FRAG = 0 */
498 buf_write_u8(&head, '\x01'); /* ATYP = 1 (IP V4) */
499 buf_write(&head, &to->dest.addr.in4.sin_addr, sizeof(to->dest.addr.in4.sin_addr));
500 buf_write(&head, &to->dest.addr.in4.sin_port, sizeof(to->dest.addr.in4.sin_port));
501
503}
struct buffer buf_sub(struct buffer *buf, int size, bool prepend)
Definition buffer.c:222
bool checked_snprintf(char *str, size_t size, const char *format,...)
Like snprintf() but returns an boolean.
Definition buffer.c:1143
static bool buf_write_u16(struct buffer *dest, uint16_t data)
Definition buffer.h:691
static int buf_read_u16(struct buffer *buf)
Definition buffer.h:798
static bool buf_read(struct buffer *src, void *dest, int size)
Definition buffer.h:763
static void secure_memzero(void *data, size_t len)
Securely zeroise memory.
Definition buffer.h:415
static bool buf_write(struct buffer *dest, const void *src, size_t size)
Definition buffer.h:661
static bool buf_write_u8(struct buffer *dest, uint8_t data)
Definition buffer.h:685
static int buf_read_u8(struct buffer *buf)
Definition buffer.h:787
#define BLEN(buf)
Definition buffer.h:126
static void strncpynt(char *dest, const char *src, size_t maxlen)
Definition buffer.h:362
static void gc_free(struct gc_arena *a)
Definition buffer.h:1049
#define ALLOC_OBJ_CLEAR(dptr, type)
Definition buffer.h:1088
static bool buf_defined(const struct buffer *buf)
Definition buffer.h:229
static struct gc_arena gc_new(void)
Definition buffer.h:1041
#define M_INFO
Definition errlevel.h:54
#define D_LINK_ERRORS
Definition errlevel.h:56
static void openvpn_fd_set(socket_descriptor_t fd, fd_set *setp)
Definition fdmisc.h:39
int get_server_poll_remaining_time(struct event_timeout *server_poll_timeout)
Definition forward.c:504
Interface functions to the internal and external multiplexers.
static SERVICE_STATUS_HANDLE service
Definition interactive.c:50
#define GET_USER_PASS_MANAGEMENT
Definition misc.h:110
static bool get_user_pass(struct user_pass *up, const char *auth_file, const char *prefix, const unsigned int flags)
Retrieves the user credentials from various sources depending on the flags.
Definition misc.h:150
#define SOCKS_UDPv4_HEADROOM
Definition mtu.h:101
#define CLEAR(x)
Definition basic.h:32
#define M_NONFATAL
Definition error.h:91
#define msg(flags,...)
Definition error.h:152
#define ASSERT(x)
Definition error.h:219
#define M_ERRNO
Definition error.h:95
bool proxy_send(socket_descriptor_t sd, const void *buf, size_t buf_len)
Definition proxy.c:187
bool proxy_recv_char(uint8_t *c, const char *name, socket_descriptor_t sd, struct timeval *timeout, volatile int *signal_received)
Definition proxy.c:60
void register_signal(struct signal_info *si, int signum, const char *signal_text)
Register a soft signal in the signal_info struct si respecting priority.
Definition sig.c:228
#define MSG_NOSIGNAL
Definition socket.h:261
static const char * print_openvpn_sockaddr(const struct openvpn_sockaddr *addr, struct gc_arena *gc)
Definition socket_util.h:71
static int port_from_servname(const char *servname)
Definition socks.c:317
void establish_socks_proxy_passthru(struct socks_proxy_info *p, socket_descriptor_t sd, const char *host, const char *servname, struct event_timeout *server_poll_timeout, struct signal_info *sig_info)
Definition socks.c:337
static bool socks_handshake(struct socks_proxy_info *p, socket_descriptor_t sd, struct event_timeout *server_poll_timeout, volatile int *signal_received)
Definition socks.c:159
int socks_process_outgoing_udp(struct buffer *buf, const struct link_socket_actual *to)
Definition socks.c:484
static bool socks_username_password_auth(struct socks_proxy_info *p, socket_descriptor_t sd, struct event_timeout *server_poll_timeout, volatile int *signal_received)
Definition socks.c:100
#define UP_TYPE_SOCKS
Definition socks.c:48
void socks_process_incoming_udp(struct buffer *buf, struct link_socket_actual *from)
Definition socks.c:446
static bool recv_socks_reply(socket_descriptor_t sd, struct openvpn_sockaddr *addr, struct event_timeout *server_poll_timeout, volatile int *signal_received)
Definition socks.c:233
struct socks_proxy_info * socks_proxy_new(const char *server, const char *port, const char *authfile)
Definition socks.c:51
void establish_socks_proxy_udpassoc(struct socks_proxy_info *p, socket_descriptor_t ctrl_sd, struct openvpn_sockaddr *relay_addr, struct event_timeout *server_poll_timeout, struct signal_info *sig_info)
Definition socks.c:395
static bool socks_proxy_recv_char(uint8_t *c, const char *name, socket_descriptor_t sd, struct event_timeout *server_poll_timeout, volatile int *signal_received)
Definition socks.c:84
void socks_proxy_close(struct socks_proxy_info *sp)
Definition socks.c:78
Wrapper structure for dynamically allocated memory.
Definition buffer.h:60
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:65
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:116
union openvpn_sockaddr::@27 addr
struct sockaddr_in in4
Definition socket_util.h:43
volatile int signal_received
Definition sig.h:42
char authfile[256]
Definition socks.h:42
char server[128]
Definition socks.h:40
const char * port
Definition socks.h:41
char password[USER_PASS_LEN]
Definition misc.h:68
char username[USER_PASS_LEN]
Definition misc.h:67
SOCKET socket_descriptor_t
Definition syshead.h:445
#define SIGUSR1
Definition syshead.h:57
static int cleanup(void **state)
struct gc_arena gc
Definition test_ssl.c:131