Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

add obfuscate to openvpn connections ( very important for the users in china) #3

Open
wants to merge 3 commits into from

3 participants

sadan9 John Dyer Nicholas Hall
sadan9

Chinese Government use GFW ( Great FireWall Of China .about it please look this:http://en.wikipedia.org/wiki/Great_Firewall_of_China) to block lot of website ,like Facebook , Twitter ,Youtube....

some chinese people use PPTP , L2TP ,OPENVPN , stunnel to bypassing GFW.
but after Dec 2012, GFW can block the connections of Openvpn. it's over looks like over Layer 7 because GFW can block the connections with any ports of TCP or UDP protocols.
some people think openvpn have feature codes in TLS handshake.

this change add obfuscate for openvpn connections to against the GFW.
there are tow parameter add to openvpn config file:
obfs-salt [secret]
-------this parameter is secret for obfuscate .
obfs-padlen [num]
------- this parameter optional. num=1~255. openvpn will add random data in the end of packages

sadan9

add obfuscate to openvpn connections

sadan9

add obfuscate to openvpn connections

sadan9

add obfuscate to openvpn connections.
there are tow parameter to openvpn config file:
obfs-salt this parameter is secret for obfuscate
obfs-padlen this parameter optional. num=1~255. openvpn will add random data in the end of packages.

John Dyer

Any thoughts if this is going to be merged in ?

Nicholas Hall

I kind of have a feeling patches like this will not be merged due to the constant changing DPI techniques used by firewalls. It seems like a never ending battle.

Not that this patch isn't GREAT for users that need it, I'm just afraid it'll create a burden on OpenVPN developers if they're maintaining support for it.

I will bring it up at the next OpenVPN developer meeting to get more official input.

Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Apr 18, 2013
  1. sadan9

    Update options.c

    sadan9 authored
  2. sadan9

    Update socket.c

    sadan9 authored
  3. sadan9

    Update socket.h

    sadan9 authored
This page is out of date. Refresh to see the latest.
Showing with 128 additions and 4 deletions.
  1. +17 −0 src/openvpn/options.c
  2. +47 −0 src/openvpn/socket.c
  3. +64 −4 src/openvpn/socket.h
17 src/openvpn/options.c
View
@@ -62,6 +62,10 @@
#include "memdbg.h"
+extern char* _socket_obfs_salt;
+extern int _socket_obfs_salt_len;
+extern int _socket_obfs_padlen;
+
const char title_string[] =
PACKAGE_STRING
" " TARGET_ALIAS
@@ -6820,6 +6824,19 @@ add_option (struct options *options,
options->persist_mode = 1;
}
#endif
+ else if (streq (p[0], "obfs-salt") && p[1])
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ _socket_obfs_salt = p[1];
+ _socket_obfs_salt_len = strlen(_socket_obfs_salt);
+ }
+ else if (streq (p[0], "obfs-padlen") && p[1])
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ _socket_obfs_padlen = atoi(p[1]);
+ if (_socket_obfs_padlen < 0)
+ msg(M_ERR, "--obfs-padlen must be positive");
+ }
else
{
if (file)
47 src/openvpn/socket.c
View
@@ -41,6 +41,10 @@
#include "memdbg.h"
+const char* _socket_obfs_salt = NULL;
+int _socket_obfs_salt_len = 0;
+int _socket_obfs_padlen = 0;
+
const int proto_overhead[] = { /* indexed by PROTO_x */
0,
IPv4_UDP_HEADER_SIZE, /* IPv4 */
@@ -52,6 +56,49 @@ const int proto_overhead[] = { /* indexed by PROTO_x */
IPv6_TCP_HEADER_SIZE,
};
+/**
+ * @return int The length of the random string that should be padding to the packet
+ */
+int obfs_buffer(const struct buffer* buf, const void* rand, int randlen, int maxpadlen) {
+ unsigned char md[SHA_DIGEST_LENGTH];
+ unsigned char iv[randlen + _socket_obfs_salt_len + SHA_DIGEST_LENGTH];
+ unsigned char *c;
+ int i, len, pad_len = 0;
+
+ if (maxpadlen > 255)
+ maxpadlen = 255;
+
+ /* key_1 = SHA1(rand + obfs_salt) */
+ /* pad_len = Low _rand_pad_level_ bits of (unsigned char)MD5(rand + obfs_salt)[0] */
+ memcpy(iv, rand, randlen);
+ memcpy(iv + randlen, _socket_obfs_salt, _socket_obfs_salt_len);
+
+ /* Caculate length of padding string */
+ ASSERT(SHA_DIGEST_LENGTH >= MD5_DIGEST_LENGTH);
+ MD5(iv, randlen + _socket_obfs_salt_len, md); /* SHA_DIGEST_LENGTH is bigger than MD5_DIGEST_LENGTH, it's safe here */
+ if (maxpadlen <= 0)
+ pad_len = 0;
+ else
+ pad_len = md[0] % (maxpadlen + 1);
+
+ /* Obsfucation data */
+ len = BLEN(buf);
+ SHA1(iv, randlen + _socket_obfs_salt_len, md);
+ for (i = 0, c = BPTR(buf); i < len; i++, c++)
+ {
+ *c ^= md[i % SHA_DIGEST_LENGTH];
+
+ /* Regenerate obsfuction key: key_n+1 = SHA1(key_n) */
+ if (i % SHA_DIGEST_LENGTH == SHA_DIGEST_LENGTH - 1)
+ {
+ memcpy(iv, md, SHA_DIGEST_LENGTH);
+ SHA1(iv, SHA_DIGEST_LENGTH, md);
+ }
+ }
+
+ return pad_len;
+}
+
/*
* Convert sockflags/getaddr_flags into getaddr_flags
*/
68 src/openvpn/socket.h
View
@@ -36,6 +36,10 @@
#include "socks.h"
#include "misc.h"
+extern int _socket_obfs_salt_len;
+extern int _socket_obfs_padlen;
+int obfs_buffer(const struct buffer* buf, const void* rand, int randlen, int rand_pad_level);
+
/*
* OpenVPN's default port number as assigned by IANA.
*/
@@ -877,28 +881,56 @@ link_socket_read (struct link_socket *sock,
int maxsize,
struct link_socket_actual *from)
{
+ int res;
+ struct buffer tbuf;
if (proto_is_udp(sock->info.proto)) /* unified UDPv4 and UDPv6 */
{
- int res;
-
#ifdef WIN32
res = link_socket_read_udp_win32 (sock, buf, from);
#else
res = link_socket_read_udp_posix (sock, buf, maxsize, from);
#endif
- return res;
+
}
else if (proto_is_tcp(sock->info.proto)) /* unified TCPv4 and TCPv6 */
{
/* from address was returned by accept */
addr_copy_sa(&from->dest, &sock->info.lsa->actual.dest);
- return link_socket_read_tcp (sock, buf);
+ res = link_socket_read_tcp (sock, buf);
}
else
{
ASSERT (0);
return -1; /* NOTREACHED */
}
+ /* Decode obsfucated traffic */
+ if (_socket_obfs_salt_len > 0 && BLEN(buf) > 4)
+ {
+ int r;
+ int pad_len = 0;
+
+ memcpy((void*)&r, BPTR(buf), 4);
+
+ //msg(M_DEBUG, "1, read buflen=%d", BLEN(buf));
+
+ tbuf = alloc_buf(BLEN(buf) - 4);
+ buf_copy_range(&tbuf, 0, buf, 4, BLEN(buf) - 4);
+ pad_len = obfs_buffer(&tbuf, &r, 4, _socket_obfs_padlen);
+
+ /* Remove padding random string */
+ buf_clear(buf);
+ buf_prepend(buf, BLEN(&tbuf) - pad_len);
+ buf_copy_range(buf, 0, &tbuf, 0, BLEN(&tbuf) - pad_len);
+
+ //msg(M_DEBUG, "1, read buflen=%d, padlen=%d", BLEN(buf), pad_len);
+
+ free_buf(&tbuf);
+
+ res -= 4;
+ res -= pad_len;
+
+ }
+ return res;
}
/*
@@ -984,6 +1016,34 @@ link_socket_write (struct link_socket *sock,
struct buffer *buf,
struct link_socket_actual *to)
{
+ struct buffer tbuf;
+ /* Obsfucate traffic */
+ if (_socket_obfs_salt_len > 0)
+ {
+ int pad_len, i;
+ int r = rand();
+
+ //msg(M_DEBUG, "1, write buflen=%d", BLEN(buf));
+
+ pad_len = obfs_buffer(buf, &r, sizeof(r), _socket_obfs_padlen);
+
+ tbuf = alloc_buf(BLEN(buf) + 4 + pad_len);
+ buf_write(&tbuf, (void*)&r, 4);
+ buf_copy_range(&tbuf, 4, buf, 0, BLEN(buf));
+ for (i = 0; i < pad_len; i++)
+ {
+ if (unlikely(i % 4 == 0))
+ r = rand();
+
+ buf_write(&tbuf, (void*)&r + i % 4, 1);
+ }
+
+ buf_copy_range(buf, 0, &tbuf, 0, BLEN(&tbuf));
+
+ //msg(M_DEBUG, "2, write buflen=%d", BLEN(buf));
+
+ free_buf(&tbuf);
+ }
if (proto_is_udp(sock->info.proto)) /* unified UDPv4 and UDPv6 */
{
return link_socket_write_udp (sock, buf, to);
Something went wrong with that request. Please try again.