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
8 * Copyright (C) 2002-2005 OpenVPN Solutions LLC <info@openvpn.net>
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.
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.
19 * You should have received a copy of the GNU General Public License
20 * along with this program (see the file COPYING included with this
21 * distribution); if not, write to the Free Software Foundation, Inc.,
22 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
26 * 2004-01-30: Added Socks5 proxy support
27 * (Christof Meerwald, http://cmeerw.org)
29 * see RFC 1928, only supports "no authentication"
33 #include "config-win32.h"
53 socks_adjust_frame_parameters (struct frame
*frame
, int proto
)
55 if (proto
== PROTO_UDPv4
)
56 frame_add_to_extra_link (frame
, 10);
59 struct socks_proxy_info
*
60 new_socks_proxy (const char *server
,
65 struct socks_proxy_info
*p
;
66 ALLOC_OBJ_CLEAR_GC (p
, struct socks_proxy_info
, gc
);
68 ASSERT (legal_ipv4_port (port
));
70 strncpynt (p
->server
, server
, sizeof (p
->server
));
79 socks_handshake (socket_descriptor_t sd
, volatile int *signal_received
)
83 const int timeout_sec
= 5;
85 /* VER = 5, NMETHODS = 1, METHODS = [0] */
86 const ssize_t size
= send (sd
, "\x05\x01\x00", 3, MSG_NOSIGNAL
);
89 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "socks_handshake: TCP port write failed on send()");
103 tv
.tv_sec
= timeout_sec
;
106 status
= select (sd
+ 1, &reads
, NULL
, NULL
, &tv
);
108 get_signal (signal_received
);
109 if (*signal_received
)
115 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "socks_handshake: TCP port read timeout expired");
122 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "socks_handshake: TCP port read failed on select()");
126 /* read single char */
127 size
= recv(sd
, &c
, 1, MSG_NOSIGNAL
);
132 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "socks_handshake: TCP port read failed on recv()");
136 /* store char in buffer */
140 /* VER == 5 && METHOD == 0 */
141 if (buf
[0] != '\x05' || buf
[1] != '\x00')
143 msg (D_LINK_ERRORS
, "socks_handshake: Socks proxy returned bad status");
151 recv_socks_reply (socket_descriptor_t sd
, struct sockaddr_in
*addr
,
152 volatile int *signal_received
)
158 const int timeout_sec
= 5;
162 addr
->sin_family
= AF_INET
;
163 addr
->sin_addr
.s_addr
= htonl (INADDR_ANY
);
164 addr
->sin_port
= htons (0);
167 while (len
< 4 + alen
+ 2)
177 tv
.tv_sec
= timeout_sec
;
180 status
= select (sd
+ 1, &reads
, NULL
, NULL
, &tv
);
182 get_signal (signal_received
);
183 if (*signal_received
)
189 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "recv_socks_reply: TCP port read timeout expired");
196 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "recv_socks_reply: TCP port read failed on select()");
200 /* read single char */
201 size
= recv(sd
, &c
, 1, MSG_NOSIGNAL
);
206 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "recv_socks_reply: TCP port read failed on recv()");
217 case '\x01': /* IP V4 */
221 case '\x03': /* DOMAINNAME */
222 alen
= (unsigned char) c
;
225 case '\x04': /* IP V6 */
230 msg (D_LINK_ERRORS
, "recv_socks_reply: Socks proxy returned bad address type");
235 /* store char in buffer */
236 if (len
< (int)sizeof(buf
))
241 /* VER == 5 && REP == 0 (succeeded) */
242 if (buf
[0] != '\x05' || buf
[1] != '\x00')
244 msg (D_LINK_ERRORS
, "recv_socks_reply: Socks proxy returned bad reply");
248 /* ATYP == 1 (IP V4 address) */
249 if (atyp
== '\x01' && addr
!= NULL
)
251 memcpy (&addr
->sin_addr
, buf
+ 4, sizeof (addr
->sin_addr
));
252 memcpy (&addr
->sin_port
, buf
+ 8, sizeof (addr
->sin_port
));
260 establish_socks_proxy_passthru (struct socks_proxy_info
*p
,
261 socket_descriptor_t sd
, /* already open to proxy */
262 const char *host
, /* openvpn server remote */
263 const int port
, /* openvpn server port */
264 volatile int *signal_received
)
269 if (!socks_handshake (sd
, signal_received
))
272 /* format Socks CONNECT message */
273 buf
[0] = '\x05'; /* VER = 5 */
274 buf
[1] = '\x01'; /* CMD = 1 (CONNECT) */
275 buf
[2] = '\x00'; /* RSV */
276 buf
[3] = '\x03'; /* ATYP = 3 (DOMAINNAME) */
279 len
= (5 + len
+ 2 > sizeof(buf
)) ? (sizeof(buf
) - 5 - 2) : len
;
282 memcpy(buf
+ 5, host
, len
);
284 buf
[5 + len
] = (char) (port
>> 8);
285 buf
[5 + len
+ 1] = (char) (port
& 0xff);
288 const ssize_t size
= send (sd
, buf
, 5 + len
+ 2, MSG_NOSIGNAL
);
289 if ((int)size
!= 5 + (int)len
+ 2)
291 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "establish_socks_proxy_passthru: TCP port write failed on send()");
296 /* receive reply from Socks proxy and discard */
297 if (!recv_socks_reply (sd
, NULL
, signal_received
))
303 /* on error, should we exit or restart? */
304 if (!*signal_received
)
305 *signal_received
= (p
->retry
? SIGUSR1
: SIGTERM
); /* SOFT-SIGUSR1 -- socks error */
310 establish_socks_proxy_udpassoc (struct socks_proxy_info
*p
,
311 socket_descriptor_t ctrl_sd
, /* already open to proxy */
312 socket_descriptor_t udp_sd
,
313 struct sockaddr_in
*relay_addr
,
314 volatile int *signal_received
)
316 if (!socks_handshake (ctrl_sd
, signal_received
))
320 /* send Socks UDP ASSOCIATE message */
321 /* VER = 5, CMD = 3 (UDP ASSOCIATE), RSV = 0, ATYP = 1 (IP V4),
322 BND.ADDR = 0, BND.PORT = 0 */
323 const ssize_t size
= send (ctrl_sd
,
324 "\x05\x03\x00\x01\x00\x00\x00\x00\x00\x00",
328 msg (D_LINK_ERRORS
| M_ERRNO_SOCK
, "establish_socks_proxy_passthru: TCP port write failed on send()");
333 /* receive reply from Socks proxy */
335 if (!recv_socks_reply (ctrl_sd
, relay_addr
, signal_received
))
341 /* on error, should we exit or restart? */
342 if (!*signal_received
)
343 *signal_received
= (p
->retry
? SIGUSR1
: SIGTERM
); /* SOFT-SIGUSR1 -- socks error */
348 * Remove the 10 byte socks5 header from an incoming
349 * UDP packet, setting *from to the source address.
351 * Run after UDP read.
354 socks_process_incoming_udp (struct buffer
*buf
,
355 struct sockaddr_in
*from
)
363 if (buf_read_u8 (buf
) != 0)
366 atyp
= buf_read_u8 (buf
);
367 if (atyp
!= 1) /* ATYP == 1 (IP V4) */
370 buf_read (buf
, &from
->sin_addr
, sizeof (from
->sin_addr
));
371 buf_read (buf
, &from
->sin_port
, sizeof (from
->sin_port
));
380 * Add a 10 byte socks header prior to UDP write.
381 * *to is the destination address.
383 * Run before UDP write.
384 * Returns the size of the header.
387 socks_process_outgoing_udp (struct buffer
*buf
,
388 struct sockaddr_in
*to
)
391 * Get a 10 byte subset buffer prepended to buf --
392 * we expect these bytes will be here because
393 * we allocated frame space in socks_adjust_frame_parameters.
395 struct buffer head
= buf_sub (buf
, 10, true);
397 /* crash if not enough headroom in buf */
398 ASSERT (buf_defined (&head
));
400 buf_write_u16 (&head
, 0); /* RSV = 0 */
401 buf_write_u8 (&head
, 0); /* FRAG = 0 */
402 buf_write_u8 (&head
, '\x01'); /* ATYP = 1 (IP V4) */
403 buf_write (&head
, &to
->sin_addr
, sizeof (to
->sin_addr
));
404 buf_write (&head
, &to
->sin_port
, sizeof (to
->sin_port
));
410 static void dummy(void) {}
411 #endif /* ENABLE_SOCKS */