Skip to content

Instantly share code, notes, and snippets.

@warriorpaw
Forked from greensea/OpenVPN-2.2.2-obfs.patch
Last active December 16, 2015 03:39
Show Gist options
  • Save warriorpaw/5371951 to your computer and use it in GitHub Desktop.
Save warriorpaw/5371951 to your computer and use it in GitHub Desktop.
--- 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"
+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,20 @@
options->persist_mode = 1;
}
#endif
+ else if (streq (p[0], "obfs-salt") && p[1])
+ {
+ VERIFY_PERMISSION (OPT_P_GENERAL);
+ srand((unsigned)time(NULL));
+ _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)
--- 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:44:57.707131191 +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,50 @@
IPv4_TCP_HEADER_SIZE
};
+/**
+ * @return int The length of the random string that should be padding to the packet
+ */
+int obfs_padlen(const void* rand) {
+ int pad_len;
+ unsigned char md[MD5_DIGEST_LENGTH];
+ unsigned char iv[4 + _socket_obfs_salt_len];
+ memcpy(iv, rand, 4);
+ memcpy(iv + 4, _socket_obfs_salt, _socket_obfs_salt_len);
+ MD5(iv, 4 + _socket_obfs_salt_len, md);
+ if (_socket_obfs_padlen <= 0)
+ pad_len = 0;
+ else
+ pad_len = md[9] % _socket_obfs_padlen;
+ pad_len++;
+ return pad_len;
+}
+
+void obfs_buffer(const struct buffer* buf, const void* rand) {
+ unsigned char md[SHA_DIGEST_LENGTH];
+ unsigned char iv[4 + _socket_obfs_salt_len + SHA_DIGEST_LENGTH];
+ unsigned char *c;
+ int i, len;
+
+ memcpy(iv, rand, 4);
+ memcpy(iv + 4, _socket_obfs_salt, _socket_obfs_salt_len);
+
+ SHA1(iv, 4 + _socket_obfs_salt_len, md);
+
+ /* Obsfucation data */
+ len = BLEN(buf);
+
+ for (i = 0, c = BPTR(buf); i < len; i++, c++)
+ {
+ *c ^= md[i % SHA_DIGEST_LENGTH];
+
+ if (i % SHA_DIGEST_LENGTH == SHA_DIGEST_LENGTH - 1)
+ {
+ memcpy(iv, md, SHA_DIGEST_LENGTH);
+ SHA1(iv, SHA_DIGEST_LENGTH, md);
+ }
+ }
+}
+
/*
* 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 2013-01-24 10:48:37.559033278 +0800
@@ -36,6 +36,11 @@
#include "socks.h"
#include "misc.h"
+extern int _socket_obfs_salt_len;
+extern int _socket_obfs_padlen;
+
+void obfs_buffer(const struct buffer* buf, const void* rand);
+int obfs_padlen(const void* rand);
/*
* OpenVPN's default port number as assigned by IANA.
*/
@@ -740,28 +745,60 @@
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)+BLEN(buf)-4, 4);
+ r ^= 0x5f3759df;
+ msg(M_DEBUG, "1, read buflen=%d rand=%d", BLEN(buf),r);
+
+ pad_len = obfs_padlen(&r);
+ tbuf = alloc_buf(BLEN(buf) - 4);
+ buf_copy_range(&tbuf, 0, buf, 0, BLEN(buf) - 4);
+ obfs_buffer(&tbuf, &r);
+ /* Remove padding random string */
+ buf_clear(buf);
+ buf_prepend(buf, BLEN(&tbuf) - pad_len);
+ buf_copy_range(buf, 0, &tbuf, pad_len, 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;
}
/*
@@ -846,6 +883,37 @@
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(),tmp;
+
+ msg(M_DEBUG, "1, write buflen=%d rand=%d", BLEN(buf),r);
+ pad_len = obfs_padlen(&r);
+
+ tbuf = alloc_buf(BLEN(buf) + 4 + pad_len);
+ for (i = 0; i < pad_len; i++)
+ {
+ if (unlikely(i % 4 == 0))
+ tmp = rand();
+
+ buf_write(&tbuf, (void*)&tmp + i % 4, 1);
+ }
+ buf_copy_range(&tbuf, pad_len, buf, 0, BLEN(buf));
+ obfs_buffer(&tbuf, &r);
+ r ^= 0x5f3759df;
+ buf_write(&tbuf, (void*)&r, 4);
+ buf_copy_range(buf, 0, &tbuf, 0, BLEN(&tbuf));
+
+ msg(M_DEBUG, "2, write buflen=%d padlen=%d", BLEN(buf),pad_len);
+
+ free_buf(&tbuf);
+ }
+
+
if (sock->info.proto == PROTO_UDPv4)
{
return link_socket_write_udp (sock, buf, to);
@cloudslsw
Copy link

您好,我试了您这个,但是UDP模式下连接还是会断流,断一会又恢复了,恢复完又断流了,有什么解决办法么?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment