Skip to content

Commit

Permalink
Use websocket obfuscating
Browse files Browse the repository at this point in the history
  • Loading branch information
madeye committed Dec 14, 2016
1 parent 4c7e726 commit 6176903
Show file tree
Hide file tree
Showing 9 changed files with 274 additions and 25 deletions.
3 changes: 2 additions & 1 deletion src/Makefile.am
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ sni_src = http.c \
tls.c \
rule.c

obfs_src = obfs_http.c
obfs_src = obfs_http.c \
base64.c

ss_local_SOURCES = utils.c \
jconf.c \
Expand Down
98 changes: 86 additions & 12 deletions src/Makefile.in

Large diffs are not rendered by default.

106 changes: 106 additions & 0 deletions src/base64.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/*
* Copyright (c) 2006 Ryan Martell. ([email protected])
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

/**
* @file
* @brief Base64 encode/decode
* @author Ryan Martell <[email protected]> (with lots of Michael)
*/

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <limits.h>
#include <stddef.h>

#include "base64.h"

/* ---------------- private code */
static const uint8_t map2[] =
{
0x3e, 0xff, 0xff, 0xff, 0x3f, 0x34, 0x35, 0x36,
0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x01,
0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09,
0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x1a, 0x1b,
0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b,
0x2c, 0x2d, 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33
};

int base64_decode(uint8_t *out, const char *in, int out_size)
{
int i, v;
uint8_t *dst = out;

v = 0;
for (i = 0; in[i] && in[i] != '='; i++) {
unsigned int index= in[i]-43;
if (index >= sizeof(map2) || map2[index] == 0xff)
return -1;
v = (v << 6) + map2[index];
if (i & 3) {
if (dst - out < out_size) {
*dst++ = v >> (6 - 2 * (i & 3));
}
}
}

return dst - out;
}

/*****************************************************************************
* b64_encode: Stolen from VLC's http.c.
* Simplified by Michael.
* Fixed edge cases and made it work from data (vs. strings) by Ryan.
*****************************************************************************/

char *base64_encode(char *out, int out_size, const uint8_t *in, int in_size)
{
static const char b64[] =
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
char *ret, *dst;
unsigned i_bits = 0;
int i_shift = 0;
int bytes_remaining = in_size;

if (in_size >= UINT_MAX / 4 ||
out_size < BASE64_SIZE(in_size))
return NULL;
ret = dst = out;
while (bytes_remaining) {
i_bits = (i_bits << 8) + *in++;
bytes_remaining--;
i_shift += 8;

do {
*dst++ = b64[(i_bits << 6 >> i_shift) & 0x3f];
i_shift -= 6;
} while (i_shift > 6 || (bytes_remaining == 0 && i_shift > 0));
}
while ((dst - ret) & 3)
*dst++ = '=';
*dst = '\0';

return ret;
}
54 changes: 54 additions & 0 deletions src/base64.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
/*
* Copyright (c) 2006 Ryan Martell. ([email protected])
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/

#ifndef BASE64_H
#define BASE64_H

#include <stdint.h>

/**
* Decode a base64-encoded string.
*
* @param out buffer for decoded data
* @param in null-terminated input string
* @param out_size size in bytes of the out buffer, must be at
* least 3/4 of the length of in
* @return number of bytes written, or a negative value in case of
* invalid input
*/
int base64_decode(uint8_t *out, const char *in, int out_size);

/**
* Encode data to base64 and null-terminate.
*
* @param out buffer for encoded data
* @param out_size size in bytes of the output buffer, must be at
* least BASE64_SIZE(in_size)
* @param in_size size in bytes of the 'in' buffer
* @return 'out' or NULL in case of error
*/
char *base64_encode(char *out, int out_size, const uint8_t *in, int in_size);

/**
* Calculate the output size needed to base64-encode x bytes.
*/
#define BASE64_SIZE(x) (((x)+2) / 3 * 4 + 1)

#endif /* BASE64_H */
2 changes: 1 addition & 1 deletion src/encrypt.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ bytes_to_key(const cipher_t *cipher, const digest_type_t *md,
}

int
rand_bytes(uint8_t *output, int len)
rand_bytes(void *output, int len)
{
randombytes_buf(output, len);
// always return success
Expand Down
2 changes: 2 additions & 0 deletions src/encrypt.h
Original file line number Diff line number Diff line change
Expand Up @@ -201,4 +201,6 @@ int balloc(buffer_t *ptr, size_t capacity);
int brealloc(buffer_t *ptr, size_t len, size_t capacity);
void bfree(buffer_t *ptr);

int rand_bytes(void *output, int len);

#endif // _ENCRYPT_H
30 changes: 20 additions & 10 deletions src/obfs_http.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,24 +25,24 @@
#endif

#include "obfs_http.h"
#include "base64.h"

static const char *http_request_template =
"GET / HTTP/1.1\r\n"
"Host: %s\r\n"
"User-Agent: curl/7.%d.%d\r\n"
"Accept: */*\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
"Sec-WebSocket-Key: %s\r\n"
"\r\n";

static const char *http_response_template =
"HTTP/1.1 200 OK\r\n"
"HTTP/1.1 101 Switching Protocols\r\n"
"Server: nginx/1.%d.%d\r\n"
"Date: %s\r\n"
"Content-Type: text/html\r\n"
"Content-Length: %d\r\n"
"Content-Encoding: gzip\r\n"
"Connection: keep-alive\r\n"
"Cache-Control: private, no-cache, no-store, proxy-revalidate, no-transform\r\n"
"Pragma: no-cache\r\n"
"Upgrade: websocket\r\n"
"Connection: Upgrade\r\n"
"Sec-WebSocket-Accept: %s\r\n"
"\r\n";

static int obfs_http_request(buffer_t *, size_t);
Expand Down Expand Up @@ -73,15 +73,20 @@ obfs_http_request(buffer_t *buf, size_t cap)

char host_port[256];
char http_header[512];
uint8_t key[16];
char b64[64];

if (obfs_http->port != 80)
snprintf(host_port, sizeof(host_port), "%s:%d", obfs_http->host, obfs_http->port);
else
snprintf(host_port, sizeof(host_port), "%s", obfs_http->host);

rand_bytes(key, 16);
base64_encode(b64, 64, key, 16);

size_t obfs_len =
snprintf(http_header, sizeof(http_header), http_request_template,
host_port, major_version, minor_version);
host_port, major_version, minor_version, b64);
size_t buf_len = buf->len;

brealloc(buf, obfs_len + buf_len, cap);
Expand All @@ -105,6 +110,8 @@ obfs_http_response(buffer_t *buf, size_t cap)

char http_header[512];
char datetime[64];
uint8_t key[16];
char b64[64];

time_t now;
struct tm *tm_now;
Expand All @@ -113,10 +120,13 @@ obfs_http_response(buffer_t *buf, size_t cap)
tm_now = localtime(&now);
strftime(datetime, 64, "%a, %d %b %Y %H:%M:%S GMT", tm_now);

rand_bytes(key, 16);
base64_encode(b64, 64, key, 16);

size_t buf_len = buf->len;
size_t obfs_len =
snprintf(http_header, sizeof(http_header), http_response_template,
major_version, minor_version, datetime, buf_len);
major_version, minor_version, datetime, b64);

brealloc(buf, obfs_len + buf_len, cap);

Expand Down
1 change: 1 addition & 0 deletions src/redir.c
Original file line number Diff line number Diff line change
Expand Up @@ -618,6 +618,7 @@ new_server(int fd, int method)
server->recv_ctx->connected = 0;
server->send_ctx->server = server;
server->send_ctx->connected = 0;
server->obfs = obfs;

server->hostname = NULL;
server->hostname_len = 0;
Expand Down
3 changes: 2 additions & 1 deletion src/tunnel.c
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ remote_send_cb(EV_P_ ev_io *w, int revents)
}

if (obfs) {
obfs_http->obfs_request(remote->buf, BUF_SIZE);
obfs_http->obfs_request(abuf, BUF_SIZE);
}

int s = send(remote->fd, abuf->data, abuf->len, 0);
Expand Down Expand Up @@ -589,6 +589,7 @@ new_server(int fd, int method)
server->recv_ctx->connected = 0;
server->send_ctx->server = server;
server->send_ctx->connected = 0;
server->obfs = obfs;

if (method) {
server->e_ctx = ss_malloc(sizeof(struct enc_ctx));
Expand Down

0 comments on commit 6176903

Please sign in to comment.