diff --git a/tpws/params.h b/tpws/params.h index 793c30c..292bf0d 100644 --- a/tpws/params.h +++ b/tpws/params.h @@ -9,12 +9,11 @@ #include "tpws.h" #include "pools.h" #include "helpers.h" +#include "protocol.h" #define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3 #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 }; #define MAX_BINDS 32 diff --git a/tpws/protocol.c b/tpws/protocol.c index 4c5e996..9aff70f 100644 --- a/tpws/protocol.c +++ b/tpws/protocol.c @@ -9,7 +9,7 @@ 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; size_t method_len; @@ -17,9 +17,32 @@ bool IsHttp(const uint8_t *data, size_t len) { method_len = strlen(*method); 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) { @@ -107,6 +130,37 @@ bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char * 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) #include +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 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:" 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); @@ -14,6 +18,8 @@ const char *HttpFind2ndLevelDomain(const char *host); int HttpReplyCode(const uint8_t *data, size_t len); // must be pre-checked by IsHttpReply 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); 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 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); +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); diff --git a/tpws/tamper.c b/tpws/tamper.c index 222b1de..7ae3b7f 100644 --- a/tpws/tamper.c +++ b/tpws/tamper.c @@ -8,48 +8,13 @@ #include #include -// 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 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; size_t method_len = 0, pos; - const char **method; - bool bIsHttp = false, bBypass = false, bHaveHost = false, bHostExcluded = false; + const char *method; + bool bBypass = false, bHaveHost = false, bHostExcluded = false; char bRemovedHostSpace = 0; 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_flags=0; - for (method = http_methods; *method; method++) + if ((method = HttpMethod(segment,*size))) { - method_len = strlen(*method); - if (method_len <= *size && !memcmp(segment, *method, method_len)) - { - bIsHttp = true; - method_len -= 2; // "GET /" => "GET" - break; - } - } - if (bIsHttp) - { - VPRINT("Data block looks like http request start : %s", *method) + method_len = strlen(method)-2; + VPRINT("Data block looks like http request start : %s", method) 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 - if ((params.hostlist || params.hostlist_exclude) && find_host(&pHost,segment,*size)) + if ((params.hostlist || params.hostlist_exclude) && HttpFindHost(&pHost,segment,*size)) { p = pHost + 5; 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 if (pHost) pHost++; // Host: position will move by 1 byte } - if ((params.hostdot || params.hosttab) && *size '%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); } - if (params.hostpad && find_host(&pHost,segment,*size)) + if (params.hostpad && HttpFindHost(&pHost,segment,*size)) { // add : XXXXX: 5) { // construct 2 TLS records from one diff --git a/tpws/tpws.c b/tpws/tpws.c index e672fc1..190c609 100644 --- a/tpws/tpws.c +++ b/tpws/tpws.c @@ -829,6 +829,7 @@ void parse_params(int argc, char *argv[]) } 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_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 (!LoadIncludeHostLists())