mirror of
https://github.com/bol-van/zapret.git
synced 2025-01-06 08:20:34 +05:00
tpws: unify http and tls position finders
This commit is contained in:
parent
fd4dc89360
commit
d43d88b9d0
@ -9,12 +9,11 @@
|
|||||||
#include "tpws.h"
|
#include "tpws.h"
|
||||||
#include "pools.h"
|
#include "pools.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
|
#include "protocol.h"
|
||||||
|
|
||||||
#define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3
|
#define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3
|
||||||
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
|
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
|
||||||
|
|
||||||
enum httpreqpos { httpreqpos_none = 0, httpreqpos_method, httpreqpos_host };
|
|
||||||
enum tlspos { tlspos_none = 0, tlspos_sni, tlspos_sniext, tlspos_pos };
|
|
||||||
enum bindll { unwanted=0, no, prefer, force };
|
enum bindll { unwanted=0, no, prefer, force };
|
||||||
|
|
||||||
#define MAX_BINDS 32
|
#define MAX_BINDS 32
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
|
|
||||||
|
|
||||||
const char *http_methods[] = { "GET /","POST /","HEAD /","OPTIONS /","PUT /","DELETE /","CONNECT /","TRACE /",NULL };
|
const char *http_methods[] = { "GET /","POST /","HEAD /","OPTIONS /","PUT /","DELETE /","CONNECT /","TRACE /",NULL };
|
||||||
bool IsHttp(const uint8_t *data, size_t len)
|
const char *HttpMethod(const uint8_t *data, size_t len)
|
||||||
{
|
{
|
||||||
const char **method;
|
const char **method;
|
||||||
size_t method_len;
|
size_t method_len;
|
||||||
@ -17,9 +17,32 @@ bool IsHttp(const uint8_t *data, size_t len)
|
|||||||
{
|
{
|
||||||
method_len = strlen(*method);
|
method_len = strlen(*method);
|
||||||
if (method_len <= len && !memcmp(data, *method, method_len))
|
if (method_len <= len && !memcmp(data, *method, method_len))
|
||||||
return true;
|
return *method;
|
||||||
}
|
}
|
||||||
return false;
|
return NULL;
|
||||||
|
}
|
||||||
|
bool IsHttp(const uint8_t *data, size_t len)
|
||||||
|
{
|
||||||
|
return !!HttpMethod(data,len);
|
||||||
|
}
|
||||||
|
// pHost points to "Host: ..."
|
||||||
|
bool HttpFindHost(uint8_t **pHost,uint8_t *buf,size_t bs)
|
||||||
|
{
|
||||||
|
if (!*pHost)
|
||||||
|
{
|
||||||
|
*pHost = memmem(buf, bs, "\nHost:", 6);
|
||||||
|
if (*pHost) (*pHost)++;
|
||||||
|
}
|
||||||
|
return !!*pHost;
|
||||||
|
}
|
||||||
|
bool HttpFindHostConst(const uint8_t **pHost,const uint8_t *buf,size_t bs)
|
||||||
|
{
|
||||||
|
if (!*pHost)
|
||||||
|
{
|
||||||
|
*pHost = memmem(buf, bs, "\nHost:", 6);
|
||||||
|
if (*pHost) (*pHost)++;
|
||||||
|
}
|
||||||
|
return !!*pHost;
|
||||||
}
|
}
|
||||||
bool IsHttpReply(const uint8_t *data, size_t len)
|
bool IsHttpReply(const uint8_t *data, size_t len)
|
||||||
{
|
{
|
||||||
@ -107,6 +130,37 @@ bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *
|
|||||||
|
|
||||||
return strcasecmp(dhost, drhost)!=0;
|
return strcasecmp(dhost, drhost)!=0;
|
||||||
}
|
}
|
||||||
|
size_t HttpPos(enum httpreqpos tpos_type, size_t hpos_pos, const uint8_t *http, size_t sz)
|
||||||
|
{
|
||||||
|
const uint8_t *method, *host;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
switch(tpos_type)
|
||||||
|
{
|
||||||
|
case httpreqpos_method:
|
||||||
|
// recognize some tpws pre-applied hacks
|
||||||
|
method=http;
|
||||||
|
if (sz<10) break;
|
||||||
|
if (*method=='\n' || *method=='\r') method++;
|
||||||
|
if (*method=='\n' || *method=='\r') method++;
|
||||||
|
for (i=0;i<7;i++) if (*method>='A' && *method<='Z') method++;
|
||||||
|
if (i<3 || *method!=' ') break;
|
||||||
|
return method-http-1;
|
||||||
|
case httpreqpos_host:
|
||||||
|
if (HttpFindHostConst(&host,http,sz) && (host-http+7)<sz)
|
||||||
|
{
|
||||||
|
host+=5;
|
||||||
|
if (*host==' ') host++;
|
||||||
|
return host-http;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case httpreqpos_pos:
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return hpos_pos<sz ? hpos_pos : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -241,3 +295,20 @@ bool TLSHelloExtractHostFromHandshake(const uint8_t *data, size_t len, char *hos
|
|||||||
if (!TLSFindExtInHandshake(data, len, 0, &ext, &elen, bPartialIsOK)) return false;
|
if (!TLSFindExtInHandshake(data, len, 0, &ext, &elen, bPartialIsOK)) return false;
|
||||||
return TLSExtractHostFromExt(ext, elen, host, len_host);
|
return TLSExtractHostFromExt(ext, elen, host, len_host);
|
||||||
}
|
}
|
||||||
|
size_t TLSPos(enum tlspos tpos_type, size_t tpos_pos, const uint8_t *tls, size_t sz, uint8_t type)
|
||||||
|
{
|
||||||
|
size_t elen;
|
||||||
|
const uint8_t *ext;
|
||||||
|
switch(tpos_type)
|
||||||
|
{
|
||||||
|
case tlspos_sni:
|
||||||
|
case tlspos_sniext:
|
||||||
|
if (TLSFindExt(tls,sz,0,&ext,&elen,false))
|
||||||
|
return (tpos_type==tlspos_sni) ? ext-tls+6 : ext-tls+1;
|
||||||
|
// fall through
|
||||||
|
case tlspos_pos:
|
||||||
|
return tpos_pos<sz ? tpos_pos : 0;
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -4,7 +4,11 @@
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
extern const char *http_methods[9];
|
||||||
|
const char *HttpMethod(const uint8_t *data, size_t len);
|
||||||
bool IsHttp(const uint8_t *data, size_t len);
|
bool IsHttp(const uint8_t *data, size_t len);
|
||||||
|
bool HttpFindHost(uint8_t **pHost,uint8_t *buf,size_t bs);
|
||||||
|
bool HttpFindHostConst(const uint8_t **pHost,const uint8_t *buf,size_t bs);
|
||||||
// header must be passed like this : "\nHost:"
|
// header must be passed like this : "\nHost:"
|
||||||
bool HttpExtractHeader(const uint8_t *data, size_t len, const char *header, char *buf, size_t len_buf);
|
bool HttpExtractHeader(const uint8_t *data, size_t len, const char *header, char *buf, size_t len_buf);
|
||||||
bool HttpExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host);
|
bool HttpExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host);
|
||||||
@ -14,6 +18,8 @@ const char *HttpFind2ndLevelDomain(const char *host);
|
|||||||
int HttpReplyCode(const uint8_t *data, size_t len);
|
int HttpReplyCode(const uint8_t *data, size_t len);
|
||||||
// must be pre-checked by IsHttpReply
|
// must be pre-checked by IsHttpReply
|
||||||
bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *host);
|
bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *host);
|
||||||
|
enum httpreqpos { httpreqpos_none = 0, httpreqpos_method, httpreqpos_host, httpreqpos_pos };
|
||||||
|
size_t HttpPos(enum httpreqpos tpos_type, size_t hpos_pos, const uint8_t *http, size_t sz);
|
||||||
|
|
||||||
uint16_t TLSRecordDataLen(const uint8_t *data);
|
uint16_t TLSRecordDataLen(const uint8_t *data);
|
||||||
size_t TLSRecordLen(const uint8_t *data);
|
size_t TLSRecordLen(const uint8_t *data);
|
||||||
@ -23,3 +29,5 @@ bool TLSFindExt(const uint8_t *data, size_t len, uint16_t type, const uint8_t **
|
|||||||
bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK);
|
bool TLSFindExtInHandshake(const uint8_t *data, size_t len, uint16_t type, const uint8_t **ext, size_t *len_ext, bool bPartialIsOK);
|
||||||
bool TLSHelloExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK);
|
bool TLSHelloExtractHost(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK);
|
||||||
bool TLSHelloExtractHostFromHandshake(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK);
|
bool TLSHelloExtractHostFromHandshake(const uint8_t *data, size_t len, char *host, size_t len_host, bool bPartialIsOK);
|
||||||
|
enum tlspos { tlspos_none = 0, tlspos_sni, tlspos_sniext, tlspos_pos };
|
||||||
|
size_t TLSPos(enum tlspos tpos_type, size_t tpos_pos, const uint8_t *tls, size_t sz, uint8_t type);
|
||||||
|
@ -8,48 +8,13 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
// pHost points to "Host: ..."
|
|
||||||
static bool find_host(uint8_t **pHost,uint8_t *buf,size_t bs)
|
|
||||||
{
|
|
||||||
if (!*pHost)
|
|
||||||
{
|
|
||||||
*pHost = memmem(buf, bs, "\nHost:", 6);
|
|
||||||
if (*pHost)
|
|
||||||
{
|
|
||||||
(*pHost)++;
|
|
||||||
VPRINT("Found Host: at pos %td",*pHost - buf)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return !!*pHost;
|
|
||||||
}
|
|
||||||
|
|
||||||
static size_t tls_pos(enum tlspos tpos_type, size_t tpos_pos, const uint8_t *tls, size_t sz, uint8_t type)
|
|
||||||
{
|
|
||||||
size_t elen;
|
|
||||||
const uint8_t *ext;
|
|
||||||
switch(tpos_type)
|
|
||||||
{
|
|
||||||
case tlspos_sni:
|
|
||||||
case tlspos_sniext:
|
|
||||||
if (TLSFindExt(tls,sz,0,&ext,&elen,false))
|
|
||||||
return (tpos_type==tlspos_sni) ? ext-tls+6 : ext-tls+1;
|
|
||||||
// fall through
|
|
||||||
case tlspos_pos:
|
|
||||||
return tpos_pos;
|
|
||||||
default:
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static const char *http_methods[] = { "GET /","POST /","HEAD /","OPTIONS /","PUT /","DELETE /","CONNECT /","TRACE /",NULL };
|
|
||||||
// segment buffer has at least 5 extra bytes to extend data block
|
// segment buffer has at least 5 extra bytes to extend data block
|
||||||
void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,size_t *size, size_t *split_pos, uint8_t *split_flags)
|
void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,size_t *size, size_t *split_pos, uint8_t *split_flags)
|
||||||
{
|
{
|
||||||
uint8_t *p, *pp, *pHost = NULL;
|
uint8_t *p, *pp, *pHost = NULL;
|
||||||
size_t method_len = 0, pos;
|
size_t method_len = 0, pos;
|
||||||
const char **method;
|
const char *method;
|
||||||
bool bIsHttp = false, bBypass = false, bHaveHost = false, bHostExcluded = false;
|
bool bBypass = false, bHaveHost = false, bHostExcluded = false;
|
||||||
char bRemovedHostSpace = 0;
|
char bRemovedHostSpace = 0;
|
||||||
char *pc, Host[256];
|
char *pc, Host[256];
|
||||||
|
|
||||||
@ -58,22 +23,13 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
|
|||||||
*split_pos=0;
|
*split_pos=0;
|
||||||
*split_flags=0;
|
*split_flags=0;
|
||||||
|
|
||||||
for (method = http_methods; *method; method++)
|
if ((method = HttpMethod(segment,*size)))
|
||||||
{
|
{
|
||||||
method_len = strlen(*method);
|
method_len = strlen(method)-2;
|
||||||
if (method_len <= *size && !memcmp(segment, *method, method_len))
|
VPRINT("Data block looks like http request start : %s", method)
|
||||||
{
|
|
||||||
bIsHttp = true;
|
|
||||||
method_len -= 2; // "GET /" => "GET"
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (bIsHttp)
|
|
||||||
{
|
|
||||||
VPRINT("Data block looks like http request start : %s", *method)
|
|
||||||
if (!ctrack->l7proto) ctrack->l7proto=HTTP;
|
if (!ctrack->l7proto) ctrack->l7proto=HTTP;
|
||||||
// cpu saving : we search host only if and when required. we do not research host every time we need its position
|
// cpu saving : we search host only if and when required. we do not research host every time we need its position
|
||||||
if ((params.hostlist || params.hostlist_exclude) && find_host(&pHost,segment,*size))
|
if ((params.hostlist || params.hostlist_exclude) && HttpFindHost(&pHost,segment,*size))
|
||||||
{
|
{
|
||||||
p = pHost + 5;
|
p = pHost + 5;
|
||||||
while (p < (segment + *size) && (*p == ' ' || *p == '\t')) p++;
|
while (p < (segment + *size) && (*p == ' ' || *p == '\t')) p++;
|
||||||
@ -135,7 +91,7 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
|
|||||||
(*size)++; // block will grow by 1 byte
|
(*size)++; // block will grow by 1 byte
|
||||||
if (pHost) pHost++; // Host: position will move by 1 byte
|
if (pHost) pHost++; // Host: position will move by 1 byte
|
||||||
}
|
}
|
||||||
if ((params.hostdot || params.hosttab) && *size<segment_buffer_size && find_host(&pHost,segment,*size))
|
if ((params.hostdot || params.hosttab) && *size<segment_buffer_size && HttpFindHost(&pHost,segment,*size))
|
||||||
{
|
{
|
||||||
p = pHost + 5;
|
p = pHost + 5;
|
||||||
while (p < (segment + *size) && *p != '\r' && *p != '\n') p++;
|
while (p < (segment + *size) && *p != '\r' && *p != '\n') p++;
|
||||||
@ -148,7 +104,7 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
|
|||||||
(*size)++; // block will grow by 1 byte
|
(*size)++; // block will grow by 1 byte
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (params.domcase && find_host(&pHost,segment,*size))
|
if (params.domcase && HttpFindHost(&pHost,segment,*size))
|
||||||
{
|
{
|
||||||
p = pHost + 5;
|
p = pHost + 5;
|
||||||
pos = p - segment;
|
pos = p - segment;
|
||||||
@ -156,7 +112,7 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
|
|||||||
for (; p < (segment + *size) && *p != '\r' && *p != '\n'; p++)
|
for (; p < (segment + *size) && *p != '\r' && *p != '\n'; p++)
|
||||||
*p = (((size_t)p) & 1) ? tolower(*p) : toupper(*p);
|
*p = (((size_t)p) & 1) ? tolower(*p) : toupper(*p);
|
||||||
}
|
}
|
||||||
if (params.hostnospace && find_host(&pHost,segment,*size) && (pHost+5)<(segment+*size) && pHost[5] == ' ')
|
if (params.hostnospace && HttpFindHost(&pHost,segment,*size) && (pHost+5)<(segment+*size) && pHost[5] == ' ')
|
||||||
{
|
{
|
||||||
p = pHost + 6;
|
p = pHost + 6;
|
||||||
pos = p - segment;
|
pos = p - segment;
|
||||||
@ -165,12 +121,12 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
|
|||||||
(*size)--; // block will shrink by 1 byte
|
(*size)--; // block will shrink by 1 byte
|
||||||
bRemovedHostSpace = 1;
|
bRemovedHostSpace = 1;
|
||||||
}
|
}
|
||||||
if (params.hostcase && find_host(&pHost,segment,*size))
|
if (params.hostcase && HttpFindHost(&pHost,segment,*size))
|
||||||
{
|
{
|
||||||
VPRINT("Changing 'Host:' => '%c%c%c%c:' at pos %td", params.hostspell[0], params.hostspell[1], params.hostspell[2], params.hostspell[3], pHost - segment)
|
VPRINT("Changing 'Host:' => '%c%c%c%c:' at pos %td", params.hostspell[0], params.hostspell[1], params.hostspell[2], params.hostspell[3], pHost - segment)
|
||||||
memcpy(pHost, params.hostspell, 4);
|
memcpy(pHost, params.hostspell, 4);
|
||||||
}
|
}
|
||||||
if (params.hostpad && find_host(&pHost,segment,*size))
|
if (params.hostpad && HttpFindHost(&pHost,segment,*size))
|
||||||
{
|
{
|
||||||
// add : XXXXX: <padding?[\r\n|\n]
|
// add : XXXXX: <padding?[\r\n|\n]
|
||||||
char s[8];
|
char s[8];
|
||||||
@ -217,18 +173,7 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
|
|||||||
pHost = NULL; // invalidate
|
pHost = NULL; // invalidate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch (params.split_http_req)
|
*split_pos = HttpPos(params.split_http_req, params.split_pos, segment, *size);
|
||||||
{
|
|
||||||
case httpreqpos_method:
|
|
||||||
*split_pos = method_len - 1 + params.methodeol + (params.methodeol && !params.unixeol);
|
|
||||||
break;
|
|
||||||
case httpreqpos_host:
|
|
||||||
if (find_host(&pHost,segment,*size))
|
|
||||||
*split_pos = pHost + 6 - bRemovedHostSpace - segment;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
if (params.split_pos < *size) *split_pos = params.split_pos;
|
|
||||||
}
|
|
||||||
if (params.disorder_http) *split_flags |= SPLIT_FLAG_DISORDER;
|
if (params.disorder_http) *split_flags |= SPLIT_FLAG_DISORDER;
|
||||||
if (params.oob_http) *split_flags |= SPLIT_FLAG_OOB;
|
if (params.oob_http) *split_flags |= SPLIT_FLAG_OOB;
|
||||||
}
|
}
|
||||||
@ -258,11 +203,11 @@ void tamper_out(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,si
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
spos = tls_pos(params.split_tls, params.split_pos, segment, *size, 0);
|
spos = TLSPos(params.split_tls, params.split_pos, segment, *size, 0);
|
||||||
|
|
||||||
if ((5+*size)<=segment_buffer_size)
|
if ((5+*size)<=segment_buffer_size)
|
||||||
{
|
{
|
||||||
tpos = tls_pos(params.tlsrec, params.tlsrec_pos+5, segment, *size, 0);
|
tpos = TLSPos(params.tlsrec, params.tlsrec_pos+5, segment, *size, 0);
|
||||||
if (tpos>5)
|
if (tpos>5)
|
||||||
{
|
{
|
||||||
// construct 2 TLS records from one
|
// construct 2 TLS records from one
|
||||||
|
@ -829,6 +829,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
if (!params.resolver_threads) params.resolver_threads = 5 + params.maxconn/50;
|
if (!params.resolver_threads) params.resolver_threads = 5 + params.maxconn/50;
|
||||||
if (params.split_tls==tlspos_none && params.split_pos) params.split_tls=tlspos_pos;
|
if (params.split_tls==tlspos_none && params.split_pos) params.split_tls=tlspos_pos;
|
||||||
|
if (params.split_http_req==httpreqpos_none && params.split_pos) params.split_http_req=httpreqpos_pos;
|
||||||
|
|
||||||
if (*params.hostlist_auto_filename) params.hostlist_auto_mod_time = file_mod_time(params.hostlist_auto_filename);
|
if (*params.hostlist_auto_filename) params.hostlist_auto_mod_time = file_mod_time(params.hostlist_auto_filename);
|
||||||
if (!LoadIncludeHostLists())
|
if (!LoadIncludeHostLists())
|
||||||
|
Loading…
Reference in New Issue
Block a user