mirror of
https://github.com/bol-van/zapret.git
synced 2025-05-24 22:32:58 +03:00
tpws: --tlsrec
This commit is contained in:
@@ -31,6 +31,11 @@ bool set_hl(int fd, int hl);
|
||||
bool set_ttl_hl(int fd, int ttl);
|
||||
int get_so_error(int fd);
|
||||
|
||||
// alignment-safe functions
|
||||
static inline uint16_t pntoh16(const uint8_t *p) {
|
||||
return ((uint16_t)p[0] << 8) | (uint16_t)p[1];
|
||||
}
|
||||
static inline void phton16(uint8_t *p, uint16_t v) {
|
||||
p[0] = (uint8_t)(v>>8);
|
||||
p[1] = (uint8_t)v;
|
||||
}
|
||||
|
@@ -8,6 +8,7 @@
|
||||
#include "strpool.h"
|
||||
|
||||
enum splithttpreq { split_none = 0, split_method, split_host };
|
||||
enum tlsrec { tlsrec_none = 0, tlsrec_sni, tlsrec_pos };
|
||||
enum bindll { unwanted=0, no, prefer, force };
|
||||
|
||||
#define MAX_BINDS 32
|
||||
@@ -41,6 +42,8 @@ struct params_s
|
||||
int hostpad;
|
||||
char hostspell[4];
|
||||
enum splithttpreq split_http_req;
|
||||
enum tlsrec tlsrec;
|
||||
int tlsrec_pos;
|
||||
bool split_any_protocol;
|
||||
int split_pos;
|
||||
bool disorder;
|
||||
|
@@ -4,11 +4,12 @@
|
||||
#include "params.h"
|
||||
#include "hostlist.h"
|
||||
#include "protocol.h"
|
||||
#include "helpers.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
// pHost points to "Host: ..."
|
||||
bool find_host(char **pHost,char *buf,size_t bs)
|
||||
bool find_host(uint8_t **pHost,uint8_t *buf,size_t bs)
|
||||
{
|
||||
if (!*pHost)
|
||||
{
|
||||
@@ -23,14 +24,15 @@ bool find_host(char **pHost,char *buf,size_t bs)
|
||||
}
|
||||
|
||||
static const char *http_methods[] = { "GET /","POST /","HEAD /","OPTIONS /","PUT /","DELETE /","CONNECT /","TRACE /",NULL };
|
||||
void modify_tcp_segment(char *segment,size_t segment_buffer_size,size_t *size,size_t *split_pos)
|
||||
// segment buffer has at least 5 extra bytes to extend data block
|
||||
void modify_tcp_segment(uint8_t *segment,size_t segment_buffer_size,size_t *size,size_t *split_pos)
|
||||
{
|
||||
char *p, *pp, *pHost = NULL;
|
||||
uint8_t *p, *pp, *pHost = NULL;
|
||||
size_t method_len = 0, pos;
|
||||
const char **method;
|
||||
bool bIsHttp = false, bBypass = false;
|
||||
char bRemovedHostSpace = 0;
|
||||
char Host[128];
|
||||
char *pc, Host[128];
|
||||
|
||||
*split_pos=0;
|
||||
|
||||
@@ -57,7 +59,7 @@ void modify_tcp_segment(char *segment,size_t segment_buffer_size,size_t *size,si
|
||||
memcpy(Host, p, pp - p);
|
||||
Host[pp - p] = '\0';
|
||||
VPRINT("Requested Host is : %s", Host)
|
||||
for(p = Host; *p; p++) *p=tolower(*p);
|
||||
for(pc = Host; *pc; pc++) *pc=tolower(*pc);
|
||||
bBypass = !HostlistCheck(params.hostlist, params.hostlist_exclude, Host);
|
||||
}
|
||||
if (!bBypass)
|
||||
@@ -208,28 +210,62 @@ void modify_tcp_segment(char *segment,size_t segment_buffer_size,size_t *size,si
|
||||
{
|
||||
VPRINT("Not acting on this request")
|
||||
}
|
||||
return;
|
||||
}
|
||||
else if (params.split_pos && params.split_pos < *size)
|
||||
|
||||
if (IsTLSClientHello(segment,*size))
|
||||
{
|
||||
// split-pos is the only parameter applicable to non-http block (may be https ?)
|
||||
if (IsTLSClientHello((uint8_t*)segment,*size))
|
||||
{
|
||||
char host[256];
|
||||
char host[256];
|
||||
size_t tpos=0,elen;
|
||||
const uint8_t *ext;
|
||||
|
||||
VPRINT("packet contains TLS ClientHello")
|
||||
// we need host only if hostlist is present
|
||||
if ((params.hostlist || params.hostlist_exclude) && TLSHelloExtractHost((uint8_t*)segment,*size,host,sizeof(host)))
|
||||
VPRINT("packet contains TLS ClientHello")
|
||||
// we need host only if hostlist is present
|
||||
if ((params.hostlist || params.hostlist_exclude) && TLSHelloExtractHost((uint8_t*)segment,*size,host,sizeof(host)))
|
||||
{
|
||||
VPRINT("hostname: %s",host)
|
||||
if (!HostlistCheck(params.hostlist, params.hostlist_exclude, host))
|
||||
{
|
||||
VPRINT("hostname: %s",host)
|
||||
if (!HostlistCheck(params.hostlist, params.hostlist_exclude, host))
|
||||
{
|
||||
VPRINT("Not acting on this request")
|
||||
return;
|
||||
}
|
||||
VPRINT("Not acting on this request")
|
||||
return;
|
||||
}
|
||||
*split_pos = params.split_pos;
|
||||
}
|
||||
else if (params.split_any_protocol)
|
||||
switch(params.tlsrec)
|
||||
{
|
||||
case tlsrec_sni:
|
||||
if (TLSFindExt(segment,*size,0,&ext,&elen))
|
||||
tpos = ext-segment+1; // between typical 1st and 2nd char of hostname
|
||||
break;
|
||||
case tlsrec_pos:
|
||||
tpos = params.tlsrec_pos;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (tpos)
|
||||
{
|
||||
// construct 2 TLS records from one
|
||||
uint16_t l = pntoh16(segment+3); // length
|
||||
if (l>=2)
|
||||
{
|
||||
// length is checked in IsTLSClientHello and cannot exceed buffer size
|
||||
if (tpos>=l) tpos=1;
|
||||
VPRINT("making 2 TLS records at pos %zu",tpos)
|
||||
memmove(segment+5+tpos+5,segment+5+tpos,l-tpos);
|
||||
segment[5+tpos] = segment[0];
|
||||
segment[5+tpos+1] = segment[1];
|
||||
segment[5+tpos+2] = segment[2];
|
||||
phton16(segment+5+tpos+3,l-tpos);
|
||||
phton16(segment+3,tpos);
|
||||
*size += 5;
|
||||
}
|
||||
}
|
||||
|
||||
if (params.split_pos < *size)
|
||||
*split_pos = params.split_pos;
|
||||
return;
|
||||
}
|
||||
|
||||
if (params.split_any_protocol && params.split_pos < *size)
|
||||
*split_pos = params.split_pos;
|
||||
}
|
||||
|
@@ -1,7 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
bool find_host(char **pHost,char *buf,size_t bs);
|
||||
void modify_tcp_segment(char *segment,size_t segment_buffer_size,size_t *size,size_t *split_pos);
|
||||
bool find_host(uint8_t **pHost,uint8_t *buf,size_t bs);
|
||||
void modify_tcp_segment(uint8_t *segment,size_t segment_buffer_size,size_t *size,size_t *split_pos);
|
||||
|
74
tpws/tpws.c
74
tpws/tpws.c
@@ -174,6 +174,8 @@ static void exithelp()
|
||||
" --methodspace\t\t\t; add extra space after method\n"
|
||||
" --methodeol\t\t\t; add end-of-line before method\n"
|
||||
" --unixeol\t\t\t; replace 0D0A to 0A\n"
|
||||
" --tlsrec=sni\t\t\t; make 2 TLS records. split at SNI. don't split if SNI is not present\n"
|
||||
" --tlsrec-pos=<pos>\t\t; make 2 TLS records. split at specified pos\n"
|
||||
);
|
||||
exit(1);
|
||||
}
|
||||
@@ -288,19 +290,21 @@ void parse_params(int argc, char *argv[])
|
||||
{ "methodeol",no_argument,0,0 },// optidx=28
|
||||
{ "hosttab",no_argument,0,0 },// optidx=29
|
||||
{ "unixeol",no_argument,0,0 },// optidx=30
|
||||
{ "hostlist",required_argument,0,0 },// optidx=31
|
||||
{ "hostlist-exclude",required_argument,0,0 },// optidx=32
|
||||
{ "pidfile",required_argument,0,0 },// optidx=33
|
||||
{ "debug",optional_argument,0,0 },// optidx=34
|
||||
{ "local-rcvbuf",required_argument,0,0 },// optidx=35
|
||||
{ "local-sndbuf",required_argument,0,0 },// optidx=36
|
||||
{ "remote-rcvbuf",required_argument,0,0 },// optidx=37
|
||||
{ "remote-sndbuf",required_argument,0,0 },// optidx=38
|
||||
{ "socks",no_argument,0,0 },// optidx=39
|
||||
{ "no-resolve",no_argument,0,0 },// optidx=40
|
||||
{ "skip-nodelay",no_argument,0,0 },// optidx=41
|
||||
{ "tlsrec",required_argument,0,0 },// optidx=31
|
||||
{ "tlsrec-pos",required_argument,0,0 },// optidx=32
|
||||
{ "hostlist",required_argument,0,0 },// optidx=33
|
||||
{ "hostlist-exclude",required_argument,0,0 },// optidx=34
|
||||
{ "pidfile",required_argument,0,0 },// optidx=35
|
||||
{ "debug",optional_argument,0,0 },// optidx=36
|
||||
{ "local-rcvbuf",required_argument,0,0 },// optidx=37
|
||||
{ "local-sndbuf",required_argument,0,0 },// optidx=38
|
||||
{ "remote-rcvbuf",required_argument,0,0 },// optidx=39
|
||||
{ "remote-sndbuf",required_argument,0,0 },// optidx=40
|
||||
{ "socks",no_argument,0,0 },// optidx=41
|
||||
{ "no-resolve",no_argument,0,0 },// optidx=42
|
||||
{ "skip-nodelay",no_argument,0,0 },// optidx=43
|
||||
#if defined(BSD) && !defined(__OpenBSD__) && !defined(__APPLE__)
|
||||
{ "enable-pf",no_argument,0,0 },// optidx=42
|
||||
{ "enable-pf",no_argument,0,0 },// optidx=44
|
||||
#endif
|
||||
{ NULL,0,NULL,0 }
|
||||
};
|
||||
@@ -472,7 +476,7 @@ void parse_params(int argc, char *argv[])
|
||||
break;
|
||||
case 24: /* split-pos */
|
||||
i = atoi(optarg);
|
||||
if (i)
|
||||
if (i>0)
|
||||
params.split_pos = i;
|
||||
else
|
||||
{
|
||||
@@ -504,7 +508,27 @@ void parse_params(int argc, char *argv[])
|
||||
params.unixeol = true;
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 31: /* hostlist */
|
||||
case 31: /* tlsrec */
|
||||
if (!strcmp(optarg, "sni"))
|
||||
params.tlsrec = tlsrec_sni;
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Invalid argument for tlsrec\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 32: /* tlsrec-pos */
|
||||
if ((params.tlsrec_pos = atoi(optarg))>0)
|
||||
params.tlsrec = tlsrec_pos;
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Invalid argument for tlsrec-pos\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 33: /* hostlist */
|
||||
if (!strlist_add(¶ms.hostlist_files, optarg))
|
||||
{
|
||||
fprintf(stderr, "strlist_add failed\n");
|
||||
@@ -512,7 +536,7 @@ void parse_params(int argc, char *argv[])
|
||||
}
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 32: /* hostlist-exclude */
|
||||
case 34: /* hostlist-exclude */
|
||||
if (!strlist_add(¶ms.hostlist_exclude_files, optarg))
|
||||
{
|
||||
fprintf(stderr, "strlist_add failed\n");
|
||||
@@ -520,36 +544,36 @@ void parse_params(int argc, char *argv[])
|
||||
}
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 33: /* pidfile */
|
||||
case 35: /* pidfile */
|
||||
strncpy(params.pidfile,optarg,sizeof(params.pidfile));
|
||||
params.pidfile[sizeof(params.pidfile)-1]='\0';
|
||||
break;
|
||||
case 34:
|
||||
case 36:
|
||||
params.debug = optarg ? atoi(optarg) : 1;
|
||||
break;
|
||||
case 35: /* local-rcvbuf */
|
||||
case 37: /* local-rcvbuf */
|
||||
params.local_rcvbuf = atoi(optarg)/2;
|
||||
break;
|
||||
case 36: /* local-sndbuf */
|
||||
case 38: /* local-sndbuf */
|
||||
params.local_sndbuf = atoi(optarg)/2;
|
||||
break;
|
||||
case 37: /* remote-rcvbuf */
|
||||
case 39: /* remote-rcvbuf */
|
||||
params.remote_rcvbuf = atoi(optarg)/2;
|
||||
break;
|
||||
case 38: /* remote-sndbuf */
|
||||
case 40: /* remote-sndbuf */
|
||||
params.remote_sndbuf = atoi(optarg)/2;
|
||||
break;
|
||||
case 39: /* socks */
|
||||
case 41: /* socks */
|
||||
params.proxy_type = CONN_TYPE_SOCKS;
|
||||
break;
|
||||
case 40: /* no-resolve */
|
||||
case 42: /* no-resolve */
|
||||
params.no_resolve = true;
|
||||
break;
|
||||
case 41: /* skip-nodelay */
|
||||
case 43: /* skip-nodelay */
|
||||
params.skip_nodelay = true;
|
||||
break;
|
||||
#if defined(BSD) && !defined(__OpenBSD__) && !defined(__APPLE__)
|
||||
case 42: /* enable-pf */
|
||||
case 44: /* enable-pf */
|
||||
params.pf_enable = true;
|
||||
break;
|
||||
#endif
|
||||
|
@@ -133,7 +133,7 @@ ssize_t send_with_ttl(int fd, const void *buf, size_t len, int flags, int ttl)
|
||||
}
|
||||
|
||||
|
||||
static bool send_buffer_create(send_buffer_t *sb, char *data, size_t len, int ttl)
|
||||
static bool send_buffer_create(send_buffer_t *sb, const void *data, size_t len, int ttl)
|
||||
{
|
||||
if (sb->data)
|
||||
{
|
||||
@@ -258,7 +258,7 @@ static bool conn_has_unsent_pair(tproxy_conn_t *conn)
|
||||
}
|
||||
|
||||
|
||||
static ssize_t send_or_buffer(send_buffer_t *sb, int fd, char *buf, size_t len, int ttl)
|
||||
static ssize_t send_or_buffer(send_buffer_t *sb, int fd, const void *buf, size_t len, int ttl)
|
||||
{
|
||||
ssize_t wr=0;
|
||||
if (len)
|
||||
@@ -919,7 +919,7 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32
|
||||
if (!conn_partner_alive(conn))
|
||||
{
|
||||
// throw it to a black hole
|
||||
char waste[65070];
|
||||
uint8_t waste[65070];
|
||||
ssize_t trd=0;
|
||||
|
||||
while((rd=recv(conn->fd, waste, sizeof(waste), MSG_DONTWAIT))>0 && trd<MAX_WASTE)
|
||||
@@ -969,7 +969,7 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32
|
||||
#endif
|
||||
{
|
||||
// incoming data from local leg
|
||||
char buf[RD_BLOCK_SIZE + 4];
|
||||
uint8_t buf[RD_BLOCK_SIZE + 5];
|
||||
|
||||
rd = recv(conn->fd, buf, RD_BLOCK_SIZE, MSG_DONTWAIT);
|
||||
DBGPRINT("recv fd=%d rd=%zd err=%d",conn->fd, rd,errno)
|
||||
|
Reference in New Issue
Block a user