Skip to content

Instantly share code, notes, and snippets.

@greensea
Last active March 22, 2023 09:17

Revisions

  1. greensea revised this gist Jan 24, 2013. 1 changed file with 18 additions and 9 deletions.
    27 changes: 18 additions & 9 deletions OpenVPN-2.2.2-obfs.patch
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    --- openvpn-2.2.2.orig/options.c 2011-12-14 00:58:56.000000000 +0800
    +++ openvpn-2.2.2/options.c 2012-12-21 10:45:39.460326791 +0800
    --- openvpn-2.2.2.orig/options.c 2011-12-14 00:58:56.000000000 +0800
    +++ openvpn-2.2.2/options.c 2012-12-21 10:44:57.683130505 +0800
    @@ -54,6 +54,10 @@

    #include "memdbg.h"
    @@ -26,13 +26,13 @@
    + VERIFY_PERMISSION (OPT_P_GENERAL);
    + _socket_obfs_padlen = atoi(p[1]);
    + if (_socket_obfs_padlen < 0)
    + msg(M_ERR, "Options error: --obfs-padlen must be positive");
    + msg(M_ERR, "--obfs-padlen must be positive");
    + }
    else
    {
    if (file)
    --- openvpn-2.2.2.orig/socket.c 2011-12-14 00:58:56.000000000 +0800
    +++ openvpn-2.2.2/socket.c 2012-12-21 10:17:48.461242936 +0800
    +++ openvpn-2.2.2/socket.c 2012-12-21 10:44:57.707131191 +0800
    @@ -35,6 +35,10 @@

    #include "memdbg.h"
    @@ -95,7 +95,7 @@
    * Convert sockflags/getaddr_flags into getaddr_flags
    */
    --- openvpn-2.2.2.orig/socket.h 2011-12-14 00:58:56.000000000 +0800
    +++ openvpn-2.2.2/socket.h 2012-12-21 14:47:38.102212066 +0800
    +++ openvpn-2.2.2/socket.h 2013-01-24 10:48:37.559033278 +0800
    @@ -36,6 +36,11 @@
    #include "socks.h"
    #include "misc.h"
    @@ -108,12 +108,14 @@
    /*
    * OpenVPN's default port number as assigned by IANA.
    */
    @@ -740,28 +745,54 @@
    @@ -740,28 +745,60 @@
    int maxsize,
    struct link_socket_actual *from)
    {
    + int res;
    +
    + struct buffer tbuf;
    +
    +
    if (sock->info.proto == PROTO_UDPv4)
    {
    @@ -146,6 +148,8 @@
    + 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);
    @@ -156,6 +160,8 @@
    + 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;
    @@ -167,7 +173,7 @@
    }

    /*
    @@ -846,6 +877,34 @@
    @@ -846,6 +883,37 @@
    struct buffer *buf,
    struct link_socket_actual *to)
    {
    @@ -179,6 +185,8 @@
    + 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);
    @@ -192,8 +200,9 @@
    + buf_write(&tbuf, (void*)&r + i % 4, 1);
    + }
    +
    + buf_clear(buf);
    + buf_copy(buf, &tbuf);
    + buf_copy_range(buf, 0, &tbuf, 0, BLEN(&tbuf));
    +
    + msg(M_DEBUG, "2, write buflen=%d", BLEN(buf));
    +
    + free_buf(&tbuf);
    + }
  2. greensea created this gist Dec 25, 2012.
    204 changes: 204 additions & 0 deletions OpenVPN-2.2.2-obfs.patch
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,204 @@
    --- openvpn-2.2.2.orig/options.c 2011-12-14 00:58:56.000000000 +0800
    +++ openvpn-2.2.2/options.c 2012-12-21 10:45:39.460326791 +0800
    @@ -54,6 +54,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
    @@ -6008,6 +6012,19 @@
    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, "Options error: --obfs-padlen must be positive");
    + }
    else
    {
    if (file)
    --- openvpn-2.2.2.orig/socket.c 2011-12-14 00:58:56.000000000 +0800
    +++ openvpn-2.2.2/socket.c 2012-12-21 10:17:48.461242936 +0800
    @@ -35,6 +35,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 */
    IPv4_UDP_HEADER_SIZE,
    IPv4_TCP_HEADER_SIZE,
    @@ -42,6 +46,49 @@
    IPv4_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
    */
    --- openvpn-2.2.2.orig/socket.h 2011-12-14 00:58:56.000000000 +0800
    +++ openvpn-2.2.2/socket.h 2012-12-21 14:47:38.102212066 +0800
    @@ -36,6 +36,11 @@
    #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.
    */
    @@ -740,28 +745,54 @@
    int maxsize,
    struct link_socket_actual *from)
    {
    + int res;
    + struct buffer tbuf;
    +
    if (sock->info.proto == PROTO_UDPv4)
    {
    - 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 (sock->info.proto == PROTO_TCPv4_SERVER || sock->info.proto == PROTO_TCPv4_CLIENT)
    {
    /* from address was returned by accept */
    from->dest.sa = sock->info.lsa->actual.dest.sa;
    - 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);
    +
    + 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);
    +
    + free_buf(&tbuf);
    +
    + res -= 4;
    + res -= pad_len;
    +
    + }
    +
    + return res;
    }

    /*
    @@ -846,6 +877,34 @@
    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();
    +
    + 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_clear(buf);
    + buf_copy(buf, &tbuf);
    +
    + free_buf(&tbuf);
    + }
    +
    +
    if (sock->info.proto == PROTO_UDPv4)
    {
    return link_socket_write_udp (sock, buf, to);