Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
--- src/openvpn/options.c.orig 2012-12-17 17:36:07.000000000 +0800
+++ src/openvpn/options.c 2013-03-07 23:21:26.230153027 +0800
@@ -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
@@ -6727,6 +6731,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, "--obfs-padlen must be positive");
+ }
else if (streq (p[0], "peer-id"))
{
VERIFY_PERMISSION (OPT_P_PEER_ID);
options->use_peer_id = true;
--- src/openvpn/socket.c.orig 2012-12-13 23:46:01.000000000 +0800
+++ src/openvpn/socket.c 2013-03-07 23:24:43.943121487 +0800
@@ -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 @@
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
*/
--- src/openvpn/socket.h.orig 2012-12-20 16:56:00.000000000 +0800
+++ src/openvpn/socket.h 2013-03-07 23:35:02.442141344 +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.
*/
@@ -877,28 +882,60 @@
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(D_LINK_RW_VERBOSE, "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(D_LINK_RW_VERBOSE, "1, read buflen=%d, padlen=%d", BLEN(buf), pad_len);
+
+ free_buf(&tbuf);
+
+ res -= 4;
+ res -= pad_len;
+
+ }
+
+ return res;
}
/*
@@ -941,6 +978,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();
+
+ msg(D_LINK_RW_VERBOSE, "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(D_LINK_RW_VERBOSE, "2, write buflen=%d", BLEN(buf));
+
+ free_buf(&tbuf);
+ }
+
+
#if ENABLE_IP_PKTINFO
int link_socket_write_udp_posix_sendmsg (struct link_socket *sock,
struct buffer *buf,
@vvtommy

This comment has been minimized.

Copy link

vvtommy commented Mar 25, 2013

very nice ,在Mac上2.2.2有莫名其妙的路由问题… 换用2.3.0就OK啦。非常爽~~~~

@reee

This comment has been minimized.

Copy link

reee commented Apr 10, 2013

我试了下本来以为2.3.1是小升级……不过这个补丁不适用于2.3.1呢……求升级

@reee

This comment has been minimized.

Copy link

reee commented Apr 10, 2013

半吊子表示需要先定义MD5_DIGEST_LENGTH 否则交叉编译不能成功……
我搜了个#define MD5_DIGEST_LENGTH 16添上。。。半吊子表示完全不知道啥意思不过就是编译通过了- -

@allenessy

This comment has been minimized.

Copy link

allenessy commented May 28, 2013

我也试试

@boypt

This comment has been minimized.

Copy link

boypt commented Jun 21, 2013

https://gist.github.com/pentie/b1d5d75cdbc47b53bf9b

修改了LOG Level. 补丁中的MSG信息属于链路层的调试信息,原来那样的输出会太多了。

@wzyboy

This comment has been minimized.

Copy link
Owner Author

wzyboy commented Aug 31, 2013

@pentie 赞改 log level。其实我自己编译的时候都是把 msg() 那行注释掉的 -_-

@AnthraX1

This comment has been minimized.

Copy link

AnthraX1 commented Jan 8, 2014

TLS ERROR when used with TCP mode.

Server log:

TLS ERROR: initial packet local/remote key_method mismatch, local key_method=2, op=P_CONTROL_HARD_RESET_CLIENT_V1
Fatal TLS error (check_tls_errors_co), restarting

Client side just TCP resetted everytime

Any fix?

@cloudslsw

This comment has been minimized.

Copy link

cloudslsw commented Feb 28, 2015

您好,UDP模式下连接还是会断流,请问有解决方法么?

@Itwastaken

This comment has been minimized.

Copy link

Itwastaken commented Jun 6, 2016

怎么安装呢?

@Itwastaken

This comment has been minimized.

Copy link

Itwastaken commented Jun 6, 2016

can I use it with the version 2.3.4?

@Itwastaken

This comment has been minimized.

Copy link

Itwastaken commented Jun 7, 2016

编译的时候报错:
can't find file to patch at input line 3
Perhaps you should have used the -p or --strip option?

The text leading up to this was:

|--- src/openvpn/options.c.orig 2012-12-17 17:36:07.000000000 +0800

|+++ src/openvpn/options.c 2013-03-07 23:21:26.230153027 +0800

怎么解决?

@dawei1

This comment has been minimized.

Copy link

dawei1 commented Sep 29, 2016

我针对2.3.12修改了
https://gist.github.com/dawei1/769379564917dca6af2dee45dc943e02
@Itwastaken
把patch文件放到openvpn-2.3.12/src/openvpn/ , 然后在openvpn-2.3.12/src/openvpn/目录下执行patch命令

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.