mirror of
https://github.com/bol-van/zapret.git
synced 2024-12-02 14:40:52 +03:00
Compare commits
No commits in common. "03d51a3ccc8ffb40cdf934a7d14dd48c4db9c48f" and "080cbe9c5370bc4bdb39a27b9c54f506936ff33b" have entirely different histories.
03d51a3ccc
...
080cbe9c53
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -1224,7 +1224,7 @@ tpws_check_domain_http_bypass_()
|
||||
done
|
||||
else
|
||||
for mss in '' 88; do
|
||||
s3=${mss:+--mss=$mss}
|
||||
s3=${mss:+--mss=$mss --mss-pf=$HTTPS_PORT}
|
||||
for s2 in '' '--oob' '--disorder' '--oob --disorder'; do
|
||||
for pos in sni sniext; do
|
||||
s="--split-tls=$pos"
|
||||
|
26
nfq/desync.c
26
nfq/desync.c
@ -282,8 +282,8 @@ static void auto_hostlist_reset_fail_counter(struct desync_profile *dp, const ch
|
||||
if (fail_counter)
|
||||
{
|
||||
HostFailPoolDel(&dp->hostlist_auto_fail_counters, fail_counter);
|
||||
DLOG("auto hostlist (profile %d) : %s : fail counter reset. website is working.\n", dp->n, hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : fail counter reset. website is working.", hostname, dp->n);
|
||||
DLOG("auto hostlist : %s : fail counter reset. website is working.\n", hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : fail counter reset. website is working.", hostname);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -331,19 +331,19 @@ static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname
|
||||
}
|
||||
}
|
||||
fail_counter->counter++;
|
||||
DLOG("auto hostlist (profile %d) : %s : fail counter %d/%d\n", dp->n, hostname, fail_counter->counter, dp->hostlist_auto_fail_threshold);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : fail counter %d/%d", hostname, dp->n, fail_counter->counter, dp->hostlist_auto_fail_threshold);
|
||||
DLOG("auto hostlist : %s : fail counter %d/%d\n", hostname, fail_counter->counter, dp->hostlist_auto_fail_threshold);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : fail counter %d/%d", hostname, fail_counter->counter, dp->hostlist_auto_fail_threshold);
|
||||
if (fail_counter->counter >= dp->hostlist_auto_fail_threshold)
|
||||
{
|
||||
DLOG("auto hostlist (profile %d) : fail threshold reached. about to add %s to auto hostlist\n", dp->n, hostname);
|
||||
DLOG("auto hostlist : fail threshold reached. about to add %s to auto hostlist\n", hostname);
|
||||
HostFailPoolDel(&dp->hostlist_auto_fail_counters, fail_counter);
|
||||
|
||||
DLOG("auto hostlist (profile %d) : rechecking %s to avoid duplicates\n", dp->n, hostname);
|
||||
DLOG("auto hostlist : rechecking %s to avoid duplicates\n", hostname);
|
||||
bool bExcluded=false;
|
||||
if (!HostlistCheck(dp, hostname, &bExcluded) && !bExcluded)
|
||||
{
|
||||
DLOG("auto hostlist (profile %d) : adding %s to %s\n", dp->n, hostname, dp->hostlist_auto_filename);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : adding to %s", hostname, dp->n, dp->hostlist_auto_filename);
|
||||
DLOG("auto hostlist : adding %s\n", hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : adding", hostname);
|
||||
if (!StrPoolAddStr(&dp->hostlist, hostname))
|
||||
{
|
||||
fprintf(stderr, "StrPoolAddStr out of memory\n");
|
||||
@ -358,8 +358,8 @@ static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname
|
||||
}
|
||||
else
|
||||
{
|
||||
DLOG("auto hostlist (profile %d) : NOT adding %s\n", dp->n, hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : NOT adding, duplicate detected", hostname, dp->n);
|
||||
DLOG("auto hostlist : NOT adding %s\n", hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : NOT adding, duplicate detected", hostname);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -368,7 +368,7 @@ static void process_retrans_fail(t_ctrack *ctrack, uint8_t proto)
|
||||
{
|
||||
if (ctrack && ctrack->dp && ctrack->hostname && auto_hostlist_retrans(ctrack, proto, ctrack->dp->hostlist_auto_retrans_threshold))
|
||||
{
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : tcp retrans threshold reached", ctrack->hostname, ctrack->dp->n);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : tcp retrans threshold reached", ctrack->hostname);
|
||||
auto_hostlist_failed(ctrack->dp, ctrack->hostname);
|
||||
}
|
||||
}
|
||||
@ -683,7 +683,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
if (tcphdr->th_flags & TH_RST)
|
||||
{
|
||||
DLOG("incoming RST detected for hostname %s\n", ctrack->hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : incoming RST", ctrack->hostname, ctrack->dp->n);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : incoming RST", ctrack->hostname);
|
||||
bFail = true;
|
||||
}
|
||||
else if (len_payload && ctrack->l7proto==HTTP)
|
||||
@ -695,7 +695,7 @@ static uint8_t dpi_desync_tcp_packet_play(bool replay, size_t reasm_offset, uint
|
||||
if (bFail)
|
||||
{
|
||||
DLOG("redirect to another domain detected. possibly DPI redirect.\n");
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : redirect to another domain", ctrack->hostname, ctrack->dp->n);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : redirect to another domain", ctrack->hostname);
|
||||
}
|
||||
else
|
||||
DLOG("local or in-domain redirect detected. it's not a DPI redirect.\n");
|
||||
|
@ -319,7 +319,6 @@ bool pf_in_range(uint16_t port, const port_filter *pf)
|
||||
bool pf_parse(const char *s, port_filter *pf)
|
||||
{
|
||||
unsigned int v1,v2;
|
||||
char c;
|
||||
|
||||
if (!s) return false;
|
||||
if (*s=='~')
|
||||
@ -329,13 +328,13 @@ bool pf_parse(const char *s, port_filter *pf)
|
||||
}
|
||||
else
|
||||
pf->neg=false;
|
||||
if (sscanf(s,"%u-%u%c",&v1,&v2,&c)==2)
|
||||
if (sscanf(s,"%u-%u",&v1,&v2)==2)
|
||||
{
|
||||
if (v1>65535 || v2>65535 || v1>v2) return false;
|
||||
pf->from=(uint16_t)v1;
|
||||
pf->to=(uint16_t)v2;
|
||||
}
|
||||
else if (sscanf(s,"%u%c",&v1,&c)==1)
|
||||
else if (sscanf(s,"%u",&v1)==1)
|
||||
{
|
||||
if (v1>65535) return false;
|
||||
pf->to=pf->from=(uint16_t)v1;
|
||||
|
@ -164,21 +164,6 @@ bool saconvmapped(struct sockaddr_storage *a)
|
||||
return false;
|
||||
}
|
||||
|
||||
void sacopy(struct sockaddr_storage *sa_dest, const struct sockaddr *sa)
|
||||
{
|
||||
switch(sa->sa_family)
|
||||
{
|
||||
case AF_INET:
|
||||
memcpy(sa_dest,sa,sizeof(struct sockaddr_in));
|
||||
break;
|
||||
case AF_INET6:
|
||||
memcpy(sa_dest,sa,sizeof(struct sockaddr_in6));
|
||||
break;
|
||||
default:
|
||||
sa_dest->ss_family = 0;
|
||||
}
|
||||
}
|
||||
|
||||
bool is_localnet(const struct sockaddr *a)
|
||||
{
|
||||
// match 127.0.0.0/8, 0.0.0.0, ::1, ::0, :ffff:127.0.0.0/104, :ffff:0.0.0.0
|
||||
@ -256,34 +241,27 @@ bool pf_in_range(uint16_t port, const port_filter *pf)
|
||||
bool pf_parse(const char *s, port_filter *pf)
|
||||
{
|
||||
unsigned int v1,v2;
|
||||
char c;
|
||||
|
||||
if (!s) return false;
|
||||
if (*s=='~')
|
||||
if (*s=='~')
|
||||
{
|
||||
pf->neg=true;
|
||||
s++;
|
||||
}
|
||||
else
|
||||
pf->neg=false;
|
||||
if (sscanf(s,"%u-%u%c",&v1,&v2,&c)==2)
|
||||
if (sscanf(s,"%u-%u",&v1,&v2)==2)
|
||||
{
|
||||
if (v1>65535 || v2>65535 || v1>v2) return false;
|
||||
if (!v1 || v1>65535 || v2>65535 || v1>v2) return false;
|
||||
pf->from=(uint16_t)v1;
|
||||
pf->to=(uint16_t)v2;
|
||||
}
|
||||
else if (sscanf(s,"%u%c",&v1,&c)==1)
|
||||
else if (sscanf(s,"%u",&v1)==1)
|
||||
{
|
||||
if (v1>65535) return false;
|
||||
if (!v1 || v1>65535) return false;
|
||||
pf->to=pf->from=(uint16_t)v1;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
// deny all case
|
||||
if (!pf->from && !pf->to) pf->neg=true;
|
||||
return true;
|
||||
}
|
||||
bool pf_is_empty(const port_filter *pf)
|
||||
{
|
||||
return !pf->neg && !pf->from && !pf->to;
|
||||
}
|
||||
|
@ -25,8 +25,6 @@ uint16_t saport(const struct sockaddr *sa);
|
||||
// true = was converted
|
||||
bool saconvmapped(struct sockaddr_storage *a);
|
||||
|
||||
void sacopy(struct sockaddr_storage *sa_dest, const struct sockaddr *sa);
|
||||
|
||||
bool is_localnet(const struct sockaddr *a);
|
||||
bool is_linklocal(const struct sockaddr_in6* a);
|
||||
bool is_private6(const struct sockaddr_in6* a);
|
||||
@ -57,7 +55,6 @@ typedef struct
|
||||
} port_filter;
|
||||
bool pf_in_range(uint16_t port, const port_filter *pf);
|
||||
bool pf_parse(const char *s, port_filter *pf);
|
||||
bool pf_is_empty(const port_filter *pf);
|
||||
|
||||
#ifndef IN_LOOPBACK
|
||||
#define IN_LOOPBACK(a) ((((uint32_t) (a)) & 0xff000000) == 0x7f000000)
|
||||
|
@ -154,53 +154,35 @@ static bool HostlistCheck_(strpool *hostlist, strpool *hostlist_exclude, const c
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool LoadIncludeHostListsForProfile(struct desync_profile *dp)
|
||||
{
|
||||
if (!LoadHostLists(&dp->hostlist, &dp->hostlist_files))
|
||||
return false;
|
||||
if (*dp->hostlist_auto_filename)
|
||||
{
|
||||
dp->hostlist_auto_mod_time = file_mod_time(dp->hostlist_auto_filename);
|
||||
NonEmptyHostlist(&dp->hostlist);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// return : true = apply fooling, false = do not apply
|
||||
bool HostlistCheck(struct desync_profile *dp, const char *host, bool *excluded)
|
||||
bool HostlistCheck(const char *host, bool *excluded)
|
||||
{
|
||||
VPRINT("* Hostlist check for profile %d\n",dp->n);
|
||||
if (*dp->hostlist_auto_filename)
|
||||
if (*params.hostlist_auto_filename)
|
||||
{
|
||||
time_t t = file_mod_time(dp->hostlist_auto_filename);
|
||||
if (t!=dp->hostlist_auto_mod_time)
|
||||
time_t t = file_mod_time(params.hostlist_auto_filename);
|
||||
if (t!=params.hostlist_auto_mod_time)
|
||||
{
|
||||
DLOG_CONDUP("Autohostlist '%s' from profile %d was modified. Reloading include hostlists for this profile.\n",dp->hostlist_auto_filename, dp->n);
|
||||
if (!LoadIncludeHostListsForProfile(dp))
|
||||
DLOG_CONDUP("Autohostlist was modified by another process. Reloading include hostslist.\n");
|
||||
if (!LoadIncludeHostLists())
|
||||
{
|
||||
// what will we do without hostlist ?? sure, gonna die
|
||||
exit(1);
|
||||
}
|
||||
dp->hostlist_auto_mod_time = t;
|
||||
NonEmptyHostlist(&dp->hostlist);
|
||||
params.hostlist_auto_mod_time = t;
|
||||
}
|
||||
}
|
||||
return HostlistCheck_(dp->hostlist, dp->hostlist_exclude, host, excluded);
|
||||
return HostlistCheck_(params.hostlist, params.hostlist_exclude, host, excluded);
|
||||
}
|
||||
|
||||
bool LoadIncludeHostLists()
|
||||
{
|
||||
struct desync_profile_list *dpl;
|
||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||
if (!LoadIncludeHostListsForProfile(&dpl->dp))
|
||||
return false;
|
||||
if (!LoadHostLists(¶ms.hostlist, ¶ms.hostlist_files))
|
||||
return false;
|
||||
if (*params.hostlist_auto_filename)
|
||||
params.hostlist_auto_mod_time = file_mod_time(params.hostlist_auto_filename);
|
||||
return true;
|
||||
}
|
||||
bool LoadExcludeHostLists()
|
||||
{
|
||||
struct desync_profile_list *dpl;
|
||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||
if (!LoadHostLists(&dpl->dp.hostlist_exclude, &dpl->dp.hostlist_exclude_files))
|
||||
return false;
|
||||
return true;
|
||||
return LoadHostLists(¶ms.hostlist_exclude, ¶ms.hostlist_exclude_files);
|
||||
}
|
||||
|
@ -2,7 +2,6 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include "pools.h"
|
||||
#include "params.h"
|
||||
|
||||
bool AppendHostList(strpool **hostlist, char *filename);
|
||||
bool LoadHostLists(strpool **hostlist, struct str_list_head *file_list);
|
||||
@ -11,4 +10,4 @@ bool LoadExcludeHostLists();
|
||||
bool NonEmptyHostlist(strpool **hostlist);
|
||||
bool SearchHostList(strpool *hostlist, const char *host);
|
||||
// return : true = apply fooling, false = do not apply
|
||||
bool HostlistCheck(struct desync_profile *dp,const char *host, bool *excluded);
|
||||
bool HostlistCheck(const char *host, bool *excluded);
|
@ -138,56 +138,3 @@ int HOSTLIST_DEBUGLOG_APPEND(const char *format, ...)
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head)
|
||||
{
|
||||
struct desync_profile_list *entry = calloc(1,sizeof(struct desync_profile_list));
|
||||
if (!entry) return NULL;
|
||||
|
||||
LIST_INIT(&entry->dp.hostlist_files);
|
||||
LIST_INIT(&entry->dp.hostlist_exclude_files);
|
||||
entry->dp.filter_ipv4 = entry->dp.filter_ipv6 = true;
|
||||
|
||||
memcpy(entry->dp.hostspell, "host", 4); // default hostspell
|
||||
entry->dp.hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
|
||||
entry->dp.hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
|
||||
|
||||
// add to the tail
|
||||
struct desync_profile_list *dpn,*dpl=LIST_FIRST(¶ms.desync_profiles);
|
||||
if (dpl)
|
||||
{
|
||||
while ((dpn=LIST_NEXT(dpl,next))) dpl = dpn;
|
||||
LIST_INSERT_AFTER(dpl, entry, next);
|
||||
}
|
||||
else
|
||||
LIST_INSERT_HEAD(¶ms.desync_profiles, entry, next);
|
||||
|
||||
return entry;
|
||||
}
|
||||
static void dp_entry_destroy(struct desync_profile_list *entry)
|
||||
{
|
||||
strlist_destroy(&entry->dp.hostlist_files);
|
||||
strlist_destroy(&entry->dp.hostlist_exclude_files);
|
||||
StrPoolDestroy(&entry->dp.hostlist_exclude);
|
||||
StrPoolDestroy(&entry->dp.hostlist);
|
||||
HostFailPoolDestroy(&entry->dp.hostlist_auto_fail_counters);
|
||||
free(entry);
|
||||
}
|
||||
void dp_list_destroy(struct desync_profile_list_head *head)
|
||||
{
|
||||
struct desync_profile_list *entry;
|
||||
while ((entry = LIST_FIRST(head)))
|
||||
{
|
||||
LIST_REMOVE(entry, next);
|
||||
dp_entry_destroy(entry);
|
||||
}
|
||||
}
|
||||
bool dp_list_have_autohostlist(struct desync_profile_list_head *head)
|
||||
{
|
||||
struct desync_profile_list *dpl;
|
||||
LIST_FOREACH(dpl, head, next)
|
||||
if (*dpl->dp.hostlist_auto_filename)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
@ -27,10 +27,27 @@ struct bind_s
|
||||
|
||||
enum log_target { LOG_TARGET_CONSOLE=0, LOG_TARGET_FILE, LOG_TARGET_SYSLOG };
|
||||
|
||||
struct desync_profile
|
||||
struct params_s
|
||||
{
|
||||
int n; // number of the profile
|
||||
struct bind_s binds[MAX_BINDS];
|
||||
int binds_last;
|
||||
bool bind_wait_only;
|
||||
uint16_t port;
|
||||
|
||||
uint8_t proxy_type;
|
||||
bool no_resolve;
|
||||
bool skip_nodelay;
|
||||
bool droproot;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
bool daemon;
|
||||
int maxconn,resolver_threads,maxfiles,max_orphan_time;
|
||||
int local_rcvbuf,local_sndbuf,remote_rcvbuf,remote_sndbuf;
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
int tcp_user_timeout_local,tcp_user_timeout_remote;
|
||||
#endif
|
||||
|
||||
bool tamper; // any tamper option is set
|
||||
bool hostcase, hostdot, hosttab, hostnospace, methodspace, methodeol, unixeol, domcase;
|
||||
int hostpad;
|
||||
char hostspell[4];
|
||||
@ -43,59 +60,30 @@ struct desync_profile
|
||||
bool disorder, disorder_http, disorder_tls;
|
||||
bool oob, oob_http, oob_tls;
|
||||
uint8_t oob_byte;
|
||||
int ttl_default;
|
||||
|
||||
int mss;
|
||||
port_filter mss_pf;
|
||||
|
||||
bool tamper_start_n,tamper_cutoff_n;
|
||||
unsigned int tamper_start,tamper_cutoff;
|
||||
|
||||
bool filter_ipv4,filter_ipv6;
|
||||
port_filter pf_tcp;
|
||||
char pidfile[256];
|
||||
|
||||
strpool *hostlist, *hostlist_exclude;
|
||||
struct str_list_head hostlist_files, hostlist_exclude_files;
|
||||
char hostlist_auto_filename[PATH_MAX];
|
||||
char hostlist_auto_filename[PATH_MAX], hostlist_auto_debuglog[PATH_MAX];
|
||||
int hostlist_auto_fail_threshold, hostlist_auto_fail_time;
|
||||
time_t hostlist_auto_mod_time;
|
||||
hostfail_pool *hostlist_auto_fail_counters;
|
||||
};
|
||||
|
||||
struct desync_profile_list {
|
||||
struct desync_profile dp;
|
||||
LIST_ENTRY(desync_profile_list) next;
|
||||
};
|
||||
LIST_HEAD(desync_profile_list_head, desync_profile_list);
|
||||
struct desync_profile_list *dp_list_add(struct desync_profile_list_head *head);
|
||||
void dp_list_destroy(struct desync_profile_list_head *head);
|
||||
bool dp_list_have_autohostlist(struct desync_profile_list_head *head);
|
||||
bool tamper_start_n,tamper_cutoff_n;
|
||||
unsigned int tamper_start,tamper_cutoff;
|
||||
|
||||
struct params_s
|
||||
{
|
||||
int debug;
|
||||
enum log_target debug_target;
|
||||
char debug_logfile[PATH_MAX];
|
||||
|
||||
struct bind_s binds[MAX_BINDS];
|
||||
int binds_last;
|
||||
bool bind_wait_only;
|
||||
uint16_t port;
|
||||
struct sockaddr_in connect_bind4;
|
||||
struct sockaddr_in6 connect_bind6;
|
||||
char connect_bind6_ifname[IF_NAMESIZE];
|
||||
|
||||
uint8_t proxy_type;
|
||||
bool no_resolve;
|
||||
bool skip_nodelay;
|
||||
bool droproot;
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
bool daemon;
|
||||
char pidfile[256];
|
||||
int maxconn,resolver_threads,maxfiles,max_orphan_time;
|
||||
int local_rcvbuf,local_sndbuf,remote_rcvbuf,remote_sndbuf;
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
int tcp_user_timeout_local,tcp_user_timeout_remote;
|
||||
#endif
|
||||
int debug;
|
||||
enum log_target debug_target;
|
||||
char debug_logfile[PATH_MAX];
|
||||
|
||||
#if defined(BSD)
|
||||
bool pf_enable;
|
||||
@ -103,13 +91,6 @@ struct params_s
|
||||
#ifdef SPLICE_PRESENT
|
||||
bool nosplice;
|
||||
#endif
|
||||
|
||||
int ttl_default;
|
||||
char hostlist_auto_debuglog[PATH_MAX];
|
||||
|
||||
bool tamper; // any tamper option is set
|
||||
bool tamper_lim; // tamper-start or tamper-cutoff set in any profile
|
||||
struct desync_profile_list_head desync_profiles;
|
||||
};
|
||||
|
||||
extern struct params_s params;
|
||||
|
@ -25,45 +25,12 @@ bool IsHttp(const uint8_t *data, size_t len)
|
||||
{
|
||||
return !!HttpMethod(data,len);
|
||||
}
|
||||
|
||||
static bool IsHostAt(const uint8_t *p)
|
||||
{
|
||||
return \
|
||||
p[0]=='\n' &&
|
||||
(p[1]=='H' || p[1]=='h') &&
|
||||
(p[2]=='o' || p[2]=='O') &&
|
||||
(p[3]=='s' || p[3]=='S') &&
|
||||
(p[4]=='t' || p[4]=='T') &&
|
||||
p[5]==':';
|
||||
}
|
||||
static uint8_t *FindHostIn(uint8_t *buf, size_t bs)
|
||||
{
|
||||
size_t pos;
|
||||
if (bs<6) return NULL;
|
||||
bs-=6;
|
||||
for(pos=0;pos<=bs;pos++)
|
||||
if (IsHostAt(buf+pos))
|
||||
return buf+pos;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
static const uint8_t *FindHostInConst(const uint8_t *buf, size_t bs)
|
||||
{
|
||||
size_t pos;
|
||||
if (bs<6) return NULL;
|
||||
bs-=6;
|
||||
for(pos=0;pos<=bs;pos++)
|
||||
if (IsHostAt(buf+pos))
|
||||
return buf+pos;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
// pHost points to "Host: ..."
|
||||
bool HttpFindHost(uint8_t **pHost,uint8_t *buf,size_t bs)
|
||||
{
|
||||
if (!*pHost)
|
||||
{
|
||||
*pHost = FindHostIn(buf, bs);
|
||||
*pHost = memmem(buf, bs, "\nHost:", 6);
|
||||
if (*pHost) (*pHost)++;
|
||||
}
|
||||
return !!*pHost;
|
||||
@ -72,7 +39,7 @@ bool HttpFindHostConst(const uint8_t **pHost,const uint8_t *buf,size_t bs)
|
||||
{
|
||||
if (!*pHost)
|
||||
{
|
||||
*pHost = FindHostInConst(buf, bs);
|
||||
*pHost = memmem(buf, bs, "\nHost:", 6);
|
||||
if (*pHost) (*pHost)++;
|
||||
}
|
||||
return !!*pHost;
|
||||
@ -165,7 +132,7 @@ bool HttpReplyLooksLikeDPIRedirect(const uint8_t *data, size_t len, const char *
|
||||
}
|
||||
size_t HttpPos(enum httpreqpos tpos_type, size_t hpos_pos, const uint8_t *http, size_t sz)
|
||||
{
|
||||
const uint8_t *method, *host=NULL;
|
||||
const uint8_t *method, *host;
|
||||
int i;
|
||||
|
||||
switch(tpos_type)
|
||||
|
316
tpws/tamper.c
316
tpws/tamper.c
@ -1,87 +1,24 @@
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include "tamper.h"
|
||||
#include "params.h"
|
||||
#include "hostlist.h"
|
||||
#include "protocol.h"
|
||||
#include "helpers.h"
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
static bool dp_match_l3l4(struct desync_profile *dp, bool ipv6, uint16_t tcp_port)
|
||||
{
|
||||
return \
|
||||
((!ipv6 && dp->filter_ipv4) || (ipv6 && dp->filter_ipv6)) &&
|
||||
(!tcp_port || pf_in_range(tcp_port,&dp->pf_tcp));
|
||||
}
|
||||
static bool dp_match(struct desync_profile *dp, bool ipv6, uint16_t tcp_port, const char *hostname)
|
||||
{
|
||||
if (dp_match_l3l4(dp,ipv6,tcp_port))
|
||||
{
|
||||
// autohostlist profile matching l3/l4 filter always win
|
||||
if (*dp->hostlist_auto_filename) return true;
|
||||
|
||||
if (dp->hostlist || dp->hostlist_exclude)
|
||||
{
|
||||
// without known hostname first profile matching l3/l4 filter and without hostlist filter wins
|
||||
if (hostname)
|
||||
return HostlistCheck(dp, hostname, NULL);
|
||||
}
|
||||
else
|
||||
// profile without hostlist filter wins
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
static struct desync_profile *dp_find(struct desync_profile_list_head *head, bool ipv6, uint16_t tcp_port, const char *hostname)
|
||||
{
|
||||
struct desync_profile_list *dpl;
|
||||
VPRINT("desync profile search for hostname='%s' ipv6=%u tcp_port=%u\n", hostname ? hostname : "", ipv6, tcp_port);
|
||||
LIST_FOREACH(dpl, head, next)
|
||||
{
|
||||
if (dp_match(&dpl->dp,ipv6,tcp_port,hostname))
|
||||
{
|
||||
VPRINT("desync profile %d matches\n",dpl->dp.n);
|
||||
return &dpl->dp;
|
||||
}
|
||||
}
|
||||
VPRINT("desync profile not found\n");
|
||||
return NULL;
|
||||
}
|
||||
void apply_desync_profile(t_ctrack *ctrack, const struct sockaddr *dest)
|
||||
{
|
||||
ctrack->dp = dp_find(¶ms.desync_profiles, dest->sa_family==AF_INET6, saport(dest), ctrack->hostname);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// segment buffer has at least 5 extra bytes to extend data block
|
||||
void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, 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;
|
||||
size_t method_len = 0, pos;
|
||||
size_t tpos, spos;
|
||||
const char *method;
|
||||
bool bHaveHost = false;
|
||||
bool bBypass = false, bHaveHost = false, bHostExcluded = false;
|
||||
char *pc, Host[256];
|
||||
t_l7proto l7proto;
|
||||
|
||||
|
||||
DBGPRINT("tamper_out\n");
|
||||
|
||||
if (params.debug)
|
||||
{
|
||||
char ip_port[48];
|
||||
ntop46_port(dest,ip_port,sizeof(ip_port));
|
||||
VPRINT("tampering tcp segment with size %zu to %s\n", *size, ip_port);
|
||||
if (ctrack->dp) VPRINT("using cached desync profile %d\n",ctrack->dp->n);
|
||||
if (ctrack->hostname) VPRINT("connection hostname: %s\n", ctrack->hostname);
|
||||
}
|
||||
|
||||
if (dest->sa_family!=AF_INET && dest->sa_family!=AF_INET6)
|
||||
{
|
||||
DLOG_ERR("tamper_out dest family unknown\n");
|
||||
return;
|
||||
}
|
||||
|
||||
*split_pos=0;
|
||||
*split_flags=0;
|
||||
|
||||
@ -89,8 +26,9 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
||||
{
|
||||
method_len = strlen(method)-2;
|
||||
VPRINT("Data block looks like http request start : %s\n", method);
|
||||
l7proto=HTTP;
|
||||
if (HttpFindHost(&pHost,segment,*size))
|
||||
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) && HttpFindHost(&pHost,segment,*size))
|
||||
{
|
||||
p = pHost + 5;
|
||||
while (p < (segment + *size) && (*p == ' ' || *p == '\t')) p++;
|
||||
@ -99,57 +37,13 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
||||
memcpy(Host, p, pp - p);
|
||||
Host[pp - p] = '\0';
|
||||
bHaveHost = true;
|
||||
VPRINT("Requested Host is : %s\n", Host);
|
||||
for(pc = Host; *pc; pc++) *pc=tolower(*pc);
|
||||
bBypass = !HostlistCheck(Host, &bHostExcluded);
|
||||
}
|
||||
}
|
||||
else if (IsTLSClientHello(segment,*size,false))
|
||||
{
|
||||
VPRINT("Data block contains TLS ClientHello\n");
|
||||
l7proto=TLS;
|
||||
bHaveHost=TLSHelloExtractHost((uint8_t*)segment,*size,Host,sizeof(Host),false);
|
||||
}
|
||||
else
|
||||
{
|
||||
VPRINT("Data block contains unknown payload\n");
|
||||
l7proto = UNKNOWN;
|
||||
}
|
||||
|
||||
if (ctrack->l7proto==UNKNOWN) ctrack->l7proto=l7proto;
|
||||
|
||||
if (bHaveHost)
|
||||
{
|
||||
VPRINT("request hostname: %s\n", Host);
|
||||
if (!ctrack->hostname)
|
||||
if (!bBypass)
|
||||
{
|
||||
if (!(ctrack->hostname=strdup(Host)))
|
||||
{
|
||||
DLOG_ERR("strdup hostname : out of memory\n");
|
||||
return;
|
||||
}
|
||||
|
||||
struct desync_profile *dp_prev = ctrack->dp;
|
||||
apply_desync_profile(ctrack, dest);
|
||||
if (ctrack->dp!=dp_prev)
|
||||
VPRINT("desync profile changed by revealed hostname !\n");
|
||||
else if (*ctrack->dp->hostlist_auto_filename)
|
||||
{
|
||||
bool bHostExcluded;
|
||||
if (!HostlistCheck(ctrack->dp, Host, &bHostExcluded))
|
||||
{
|
||||
ctrack->b_ah_check = !bHostExcluded;
|
||||
VPRINT("Not acting on this request\n");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!ctrack->dp) return;
|
||||
|
||||
switch(l7proto)
|
||||
{
|
||||
case HTTP:
|
||||
if (ctrack->dp->unixeol)
|
||||
if (params.unixeol)
|
||||
{
|
||||
p = pp = segment;
|
||||
while ((p = memmem(p, segment + *size - p, "\r\n", 2)))
|
||||
@ -167,10 +61,10 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
||||
}
|
||||
pHost = NULL; // invalidate
|
||||
}
|
||||
if (ctrack->dp->methodeol && (*size+1+!ctrack->dp->unixeol)<=segment_buffer_size)
|
||||
if (params.methodeol && (*size+1+!params.unixeol)<=segment_buffer_size)
|
||||
{
|
||||
VPRINT("Adding EOL before method\n");
|
||||
if (ctrack->dp->unixeol)
|
||||
if (params.unixeol)
|
||||
{
|
||||
memmove(segment + 1, segment, *size);
|
||||
(*size)++;;
|
||||
@ -185,7 +79,7 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
||||
}
|
||||
pHost = NULL; // invalidate
|
||||
}
|
||||
if (ctrack->dp->methodspace && *size<segment_buffer_size)
|
||||
if (params.methodspace && *size<segment_buffer_size)
|
||||
{
|
||||
// we only work with data blocks looking as HTTP query, so method is at the beginning
|
||||
VPRINT("Adding extra space after method\n");
|
||||
@ -196,20 +90,20 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
||||
(*size)++; // block will grow by 1 byte
|
||||
if (pHost) pHost++; // Host: position will move by 1 byte
|
||||
}
|
||||
if ((ctrack->dp->hostdot || ctrack->dp->hosttab) && *size<segment_buffer_size && HttpFindHost(&pHost,segment,*size))
|
||||
if ((params.hostdot || params.hosttab) && *size<segment_buffer_size && HttpFindHost(&pHost,segment,*size))
|
||||
{
|
||||
p = pHost + 5;
|
||||
while (p < (segment + *size) && *p != '\r' && *p != '\n') p++;
|
||||
if (p < (segment + *size))
|
||||
{
|
||||
pos = p - segment;
|
||||
VPRINT("Adding %s to host name at pos %zu\n", ctrack->dp->hostdot ? "dot" : "tab", pos);
|
||||
VPRINT("Adding %s to host name at pos %zu\n", params.hostdot ? "dot" : "tab", pos);
|
||||
memmove(p + 1, p, *size - pos);
|
||||
*p = ctrack->dp->hostdot ? '.' : '\t'; // insert dot or tab
|
||||
*p = params.hostdot ? '.' : '\t'; // insert dot or tab
|
||||
(*size)++; // block will grow by 1 byte
|
||||
}
|
||||
}
|
||||
if (ctrack->dp->domcase && HttpFindHost(&pHost,segment,*size))
|
||||
if (params.domcase && HttpFindHost(&pHost,segment,*size))
|
||||
{
|
||||
p = pHost + 5;
|
||||
pos = p - segment;
|
||||
@ -217,7 +111,7 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
||||
for (; p < (segment + *size) && *p != '\r' && *p != '\n'; p++)
|
||||
*p = (((size_t)p) & 1) ? tolower(*p) : toupper(*p);
|
||||
}
|
||||
if (ctrack->dp->hostnospace && HttpFindHost(&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;
|
||||
pos = p - segment;
|
||||
@ -225,17 +119,17 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
||||
memmove(p - 1, p, *size - pos);
|
||||
(*size)--; // block will shrink by 1 byte
|
||||
}
|
||||
if (ctrack->dp->hostcase && HttpFindHost(&pHost,segment,*size))
|
||||
if (params.hostcase && HttpFindHost(&pHost,segment,*size))
|
||||
{
|
||||
VPRINT("Changing 'Host:' => '%c%c%c%c:' at pos %td\n", ctrack->dp->hostspell[0], ctrack->dp->hostspell[1], ctrack->dp->hostspell[2], ctrack->dp->hostspell[3], pHost - segment);
|
||||
memcpy(pHost, ctrack->dp->hostspell, 4);
|
||||
VPRINT("Changing 'Host:' => '%c%c%c%c:' at pos %td\n", params.hostspell[0], params.hostspell[1], params.hostspell[2], params.hostspell[3], pHost - segment);
|
||||
memcpy(pHost, params.hostspell, 4);
|
||||
}
|
||||
if (ctrack->dp->hostpad && HttpFindHost(&pHost,segment,*size))
|
||||
if (params.hostpad && HttpFindHost(&pHost,segment,*size))
|
||||
{
|
||||
// add : XXXXX: <padding?[\r\n|\n]
|
||||
char s[8];
|
||||
size_t hsize = ctrack->dp->unixeol ? 8 : 9;
|
||||
size_t hostpad = ctrack->dp->hostpad<hsize ? hsize : ctrack->dp->hostpad;
|
||||
size_t hsize = params.unixeol ? 8 : 9;
|
||||
size_t hostpad = params.hostpad<hsize ? hsize : params.hostpad;
|
||||
|
||||
if ((hsize+*size)>segment_buffer_size)
|
||||
VPRINT("could not add host padding : buffer too small\n");
|
||||
@ -265,7 +159,7 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
||||
p+=7;
|
||||
memset(p,'a'+rand()%('z'-'a'+1),padsize);
|
||||
p+=padsize;
|
||||
if (ctrack->dp->unixeol)
|
||||
if (params.unixeol)
|
||||
*p++='\n';
|
||||
else
|
||||
{
|
||||
@ -277,16 +171,40 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
||||
pHost = NULL; // invalidate
|
||||
}
|
||||
}
|
||||
*split_pos = HttpPos(ctrack->dp->split_http_req, ctrack->dp->split_pos, segment, *size);
|
||||
if (ctrack->dp->disorder_http) *split_flags |= SPLIT_FLAG_DISORDER;
|
||||
if (ctrack->dp->oob_http) *split_flags |= SPLIT_FLAG_OOB;
|
||||
break;
|
||||
*split_pos = HttpPos(params.split_http_req, params.split_pos, segment, *size);
|
||||
if (params.disorder_http) *split_flags |= SPLIT_FLAG_DISORDER;
|
||||
if (params.oob_http) *split_flags |= SPLIT_FLAG_OOB;
|
||||
}
|
||||
else
|
||||
{
|
||||
VPRINT("Not acting on this request\n");
|
||||
}
|
||||
}
|
||||
else if (IsTLSClientHello(segment,*size,false))
|
||||
{
|
||||
size_t tpos=0,spos=0;
|
||||
|
||||
if (!ctrack->l7proto) ctrack->l7proto=TLS;
|
||||
|
||||
VPRINT("packet contains TLS ClientHello\n");
|
||||
// we need host only if hostlist is present
|
||||
if ((params.hostlist || params.hostlist_exclude) && TLSHelloExtractHost((uint8_t*)segment,*size,Host,sizeof(Host),false))
|
||||
{
|
||||
VPRINT("hostname: %s\n",Host);
|
||||
bHaveHost = true;
|
||||
bBypass = !HostlistCheck(Host, &bHostExcluded);
|
||||
}
|
||||
if (bBypass)
|
||||
{
|
||||
VPRINT("Not acting on this request\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
spos = TLSPos(params.split_tls, params.split_pos, segment, *size, 0);
|
||||
|
||||
case TLS:
|
||||
spos = TLSPos(ctrack->dp->split_tls, ctrack->dp->split_pos, segment, *size, 0);
|
||||
if ((5+*size)<=segment_buffer_size)
|
||||
{
|
||||
tpos = TLSPos(ctrack->dp->tlsrec, ctrack->dp->tlsrec_pos+5, segment, *size, 0);
|
||||
tpos = TLSPos(params.tlsrec, params.tlsrec_pos+5, segment, *size, 0);
|
||||
if (tpos>5)
|
||||
{
|
||||
// construct 2 TLS records from one
|
||||
@ -310,46 +228,52 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
||||
}
|
||||
|
||||
if (spos && spos < *size)
|
||||
{
|
||||
VPRINT("split pos %zu\n",spos);
|
||||
*split_pos = spos;
|
||||
}
|
||||
|
||||
if (ctrack->dp->disorder_tls) *split_flags |= SPLIT_FLAG_DISORDER;
|
||||
if (ctrack->dp->oob_tls) *split_flags |= SPLIT_FLAG_OOB;
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
if (ctrack->dp->split_any_protocol && ctrack->dp->split_pos < *size)
|
||||
*split_pos = ctrack->dp->split_pos;
|
||||
if (params.disorder_tls) *split_flags |= SPLIT_FLAG_DISORDER;
|
||||
if (params.oob_tls) *split_flags |= SPLIT_FLAG_OOB;
|
||||
}
|
||||
}
|
||||
else if (params.split_any_protocol && params.split_pos < *size)
|
||||
*split_pos = params.split_pos;
|
||||
|
||||
if (ctrack->dp->disorder) *split_flags |= SPLIT_FLAG_DISORDER;
|
||||
if (ctrack->dp->oob) *split_flags |= SPLIT_FLAG_OOB;
|
||||
if (bHaveHost && bBypass && !bHostExcluded && *params.hostlist_auto_filename)
|
||||
{
|
||||
DBGPRINT("tamper_out put hostname : %s\n", Host);
|
||||
if (ctrack->hostname) free(ctrack->hostname);
|
||||
ctrack->hostname=strdup(Host);
|
||||
}
|
||||
if (params.disorder) *split_flags |= SPLIT_FLAG_DISORDER;
|
||||
if (params.oob) *split_flags |= SPLIT_FLAG_OOB;
|
||||
}
|
||||
|
||||
static void auto_hostlist_reset_fail_counter(struct desync_profile *dp, const char *hostname)
|
||||
static void auto_hostlist_reset_fail_counter(const char *hostname)
|
||||
{
|
||||
if (hostname)
|
||||
{
|
||||
hostfail_pool *fail_counter;
|
||||
|
||||
fail_counter = HostFailPoolFind(dp->hostlist_auto_fail_counters, hostname);
|
||||
fail_counter = HostFailPoolFind(params.hostlist_auto_fail_counters, hostname);
|
||||
if (fail_counter)
|
||||
{
|
||||
HostFailPoolDel(&dp->hostlist_auto_fail_counters, fail_counter);
|
||||
VPRINT("auto hostlist (profile %d) : %s : fail counter reset. website is working.\n", dp->n, hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : fail counter reset. website is working.", hostname, dp->n);
|
||||
HostFailPoolDel(¶ms.hostlist_auto_fail_counters, fail_counter);
|
||||
VPRINT("auto hostlist : %s : fail counter reset. website is working.\n", hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : fail counter reset. website is working.", hostname);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname)
|
||||
static void auto_hostlist_failed(const char *hostname)
|
||||
{
|
||||
hostfail_pool *fail_counter;
|
||||
|
||||
fail_counter = HostFailPoolFind(dp->hostlist_auto_fail_counters, hostname);
|
||||
fail_counter = HostFailPoolFind(params.hostlist_auto_fail_counters, hostname);
|
||||
if (!fail_counter)
|
||||
{
|
||||
fail_counter = HostFailPoolAdd(&dp->hostlist_auto_fail_counters, hostname, dp->hostlist_auto_fail_time);
|
||||
fail_counter = HostFailPoolAdd(¶ms.hostlist_auto_fail_counters, hostname, params.hostlist_auto_fail_time);
|
||||
if (!fail_counter)
|
||||
{
|
||||
DLOG_ERR("HostFailPoolAdd: out of memory\n");
|
||||
@ -357,35 +281,35 @@ static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname
|
||||
}
|
||||
}
|
||||
fail_counter->counter++;
|
||||
VPRINT("auto hostlist (profile %d) : %s : fail counter %d/%d\n", dp->n , hostname, fail_counter->counter, dp->hostlist_auto_fail_threshold);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : fail counter %d/%d", hostname, dp->n, fail_counter->counter, dp->hostlist_auto_fail_threshold);
|
||||
if (fail_counter->counter >= dp->hostlist_auto_fail_threshold)
|
||||
VPRINT("auto hostlist : %s : fail counter %d/%d\n", hostname, fail_counter->counter, params.hostlist_auto_fail_threshold);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : fail counter %d/%d", hostname, fail_counter->counter, params.hostlist_auto_fail_threshold);
|
||||
if (fail_counter->counter >= params.hostlist_auto_fail_threshold)
|
||||
{
|
||||
VPRINT("auto hostlist (profile %d) : fail threshold reached. adding %s to auto hostlist\n", dp->n , hostname);
|
||||
HostFailPoolDel(&dp->hostlist_auto_fail_counters, fail_counter);
|
||||
VPRINT("auto hostlist : fail threshold reached. adding %s to auto hostlist\n", hostname);
|
||||
HostFailPoolDel(¶ms.hostlist_auto_fail_counters, fail_counter);
|
||||
|
||||
VPRINT("auto hostlist (profile %d) : rechecking %s to avoid duplicates\n", dp->n, hostname);
|
||||
VPRINT("auto hostlist : rechecking %s to avoid duplicates\n", hostname);
|
||||
bool bExcluded=false;
|
||||
if (!HostlistCheck(dp, hostname, &bExcluded) && !bExcluded)
|
||||
if (!HostlistCheck(hostname, &bExcluded) && !bExcluded)
|
||||
{
|
||||
VPRINT("auto hostlist (profile %d) : adding %s to %s\n", dp->n, hostname, dp->hostlist_auto_filename);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : adding to %s", hostname, dp->n, dp->hostlist_auto_filename);
|
||||
if (!StrPoolAddStr(&dp->hostlist, hostname))
|
||||
VPRINT("auto hostlist : adding %s\n", hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : adding", hostname);
|
||||
if (!StrPoolAddStr(¶ms.hostlist, hostname))
|
||||
{
|
||||
DLOG_ERR("StrPoolAddStr out of memory\n");
|
||||
return;
|
||||
}
|
||||
if (!append_to_list_file(dp->hostlist_auto_filename, hostname))
|
||||
if (!append_to_list_file(params.hostlist_auto_filename, hostname))
|
||||
{
|
||||
DLOG_PERROR("write to auto hostlist:");
|
||||
return;
|
||||
}
|
||||
dp->hostlist_auto_mod_time = file_mod_time(dp->hostlist_auto_filename);
|
||||
params.hostlist_auto_mod_time = file_mod_time(params.hostlist_auto_filename);
|
||||
}
|
||||
else
|
||||
{
|
||||
VPRINT("auto hostlist (profile %d) : NOT adding %s\n", dp->n, hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : NOT adding, duplicate detected", hostname, dp->n);
|
||||
VPRINT("auto hostlist : NOT adding %s\n", hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : NOT adding, duplicate detected", hostname);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -396,9 +320,9 @@ void tamper_in(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,siz
|
||||
|
||||
DBGPRINT("tamper_in hostname=%s\n", ctrack->hostname);
|
||||
|
||||
if (ctrack->dp && ctrack->b_ah_check)
|
||||
if (*params.hostlist_auto_filename)
|
||||
{
|
||||
HostFailPoolPurgeRateLimited(&ctrack->dp->hostlist_auto_fail_counters);
|
||||
HostFailPoolPurgeRateLimited(¶ms.hostlist_auto_fail_counters);
|
||||
|
||||
if (ctrack->l7proto==HTTP && ctrack->hostname)
|
||||
{
|
||||
@ -409,7 +333,7 @@ void tamper_in(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,siz
|
||||
if (bFail)
|
||||
{
|
||||
VPRINT("redirect to another domain detected. possibly DPI redirect.\n");
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : redirect to another domain", ctrack->hostname, ctrack->dp->n);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : redirect to another domain", ctrack->hostname);
|
||||
}
|
||||
else
|
||||
VPRINT("local or in-domain redirect detected. it's not a DPI redirect.\n");
|
||||
@ -419,9 +343,11 @@ void tamper_in(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,siz
|
||||
// received not http reply. do not monitor this connection anymore
|
||||
VPRINT("incoming unknown HTTP data detected for hostname %s\n", ctrack->hostname);
|
||||
}
|
||||
if (bFail) auto_hostlist_failed(ctrack->dp, ctrack->hostname);
|
||||
if (bFail) auto_hostlist_failed(ctrack->hostname);
|
||||
|
||||
}
|
||||
if (!bFail) auto_hostlist_reset_fail_counter(ctrack->dp, ctrack->hostname);
|
||||
if (!bFail) auto_hostlist_reset_fail_counter(ctrack->hostname);
|
||||
|
||||
}
|
||||
ctrack->bTamperInCutoff = true;
|
||||
}
|
||||
@ -430,32 +356,30 @@ void rst_in(t_ctrack *ctrack)
|
||||
{
|
||||
DBGPRINT("rst_in hostname=%s\n", ctrack->hostname);
|
||||
|
||||
if (ctrack->dp && ctrack->b_ah_check)
|
||||
{
|
||||
HostFailPoolPurgeRateLimited(&ctrack->dp->hostlist_auto_fail_counters);
|
||||
if (!*params.hostlist_auto_filename) return;
|
||||
|
||||
if (!ctrack->bTamperInCutoff && ctrack->hostname)
|
||||
{
|
||||
VPRINT("incoming RST detected for hostname %s\n", ctrack->hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : incoming RST", ctrack->hostname, ctrack->dp->n);
|
||||
auto_hostlist_failed(ctrack->dp, ctrack->hostname);
|
||||
}
|
||||
HostFailPoolPurgeRateLimited(¶ms.hostlist_auto_fail_counters);
|
||||
|
||||
if (!ctrack->bTamperInCutoff && ctrack->hostname)
|
||||
{
|
||||
VPRINT("incoming RST detected for hostname %s\n", ctrack->hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : incoming RST", ctrack->hostname);
|
||||
auto_hostlist_failed(ctrack->hostname);
|
||||
}
|
||||
}
|
||||
void hup_out(t_ctrack *ctrack)
|
||||
{
|
||||
DBGPRINT("hup_out hostname=%s\n", ctrack->hostname);
|
||||
|
||||
if (ctrack->dp && ctrack->b_ah_check)
|
||||
{
|
||||
HostFailPoolPurgeRateLimited(&ctrack->dp->hostlist_auto_fail_counters);
|
||||
|
||||
if (!ctrack->bTamperInCutoff && ctrack->hostname)
|
||||
{
|
||||
// local leg dropped connection after first request. probably due to timeout.
|
||||
VPRINT("local leg closed connection after first request (timeout ?). hostname: %s\n", ctrack->hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : client closed connection without server reply", ctrack->hostname, ctrack->dp->n);
|
||||
auto_hostlist_failed(ctrack->dp, ctrack->hostname);
|
||||
}
|
||||
if (!*params.hostlist_auto_filename) return;
|
||||
|
||||
HostFailPoolPurgeRateLimited(¶ms.hostlist_auto_fail_counters);
|
||||
|
||||
if (!ctrack->bTamperInCutoff && ctrack->hostname)
|
||||
{
|
||||
// local leg dropped connection after first request. probably due to timeout.
|
||||
VPRINT("local leg closed connection after first request (timeout ?). hostname: %s\n", ctrack->hostname);
|
||||
HOSTLIST_DEBUGLOG_APPEND("%s : client closed connection without server reply", ctrack->hostname);
|
||||
auto_hostlist_failed(ctrack->hostname);
|
||||
}
|
||||
}
|
||||
|
@ -4,8 +4,6 @@
|
||||
#include <stdint.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "params.h"
|
||||
|
||||
#define SPLIT_FLAG_DISORDER 0x01
|
||||
#define SPLIT_FLAG_OOB 0x02
|
||||
|
||||
@ -16,14 +14,10 @@ typedef struct
|
||||
t_l7proto l7proto;
|
||||
bool bFirstReplyChecked;
|
||||
bool bTamperInCutoff;
|
||||
bool b_ah_check;
|
||||
char *hostname;
|
||||
struct desync_profile *dp; // desync profile cache
|
||||
} t_ctrack;
|
||||
|
||||
void apply_desync_profile(t_ctrack *ctrack, const struct sockaddr *dest);
|
||||
|
||||
void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, 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);
|
||||
void tamper_in(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,size_t *size);
|
||||
// connection reset by remote leg
|
||||
void rst_in(t_ctrack *ctrack);
|
||||
|
251
tpws/tpws.c
251
tpws/tpws.c
@ -46,7 +46,8 @@ bool bHup = false;
|
||||
static void onhup(int sig)
|
||||
{
|
||||
printf("HUP received !\n");
|
||||
printf("Will reload hostlist on next request (if any)\n");
|
||||
if (params.hostlist || params.hostlist_exclude)
|
||||
printf("Will reload hostlists on next request\n");
|
||||
bHup = true;
|
||||
}
|
||||
// should be called in normal execution
|
||||
@ -66,14 +67,7 @@ void dohup(void)
|
||||
static void onusr2(int sig)
|
||||
{
|
||||
printf("\nHOSTFAIL POOL DUMP\n");
|
||||
|
||||
struct desync_profile_list *dpl;
|
||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||
{
|
||||
printf("\nDESYNC PROFILE %d\n",dpl->dp.n);
|
||||
HostFailPoolDump(dpl->dp.hostlist_auto_fail_counters);
|
||||
}
|
||||
|
||||
HostFailPoolDump(params.hostlist_auto_fail_counters);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
@ -176,11 +170,7 @@ static void exithelp(void)
|
||||
#endif
|
||||
" --debug=0|1|2|syslog|@<filename>\t; 1 and 2 means log to console and set debug level. for other targets use --debug-level.\n"
|
||||
" --debug-level=0|1|2\t\t\t; specify debug level\n"
|
||||
"\nMULTI-STRATEGY:\n"
|
||||
" --new\t\t\t\t\t; begin new strategy\n"
|
||||
" --filter-l3=ipv4|ipv6\t\t\t; L3 protocol filter. multiple comma separated values allowed.\n"
|
||||
" --filter-tcp=[~]port1[-port2]\t\t; TCP port filter. ~ means negation\n"
|
||||
"\nHOSTLIST FILTER:\n"
|
||||
"\nFILTER:\n"
|
||||
" --hostlist=<filename>\t\t\t; only act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
|
||||
" --hostlist-exclude=<filename>\t\t; do not act on hosts in the list (one host per line, subdomains auto apply, gzip supported, multiple hostlists allowed)\n"
|
||||
" --hostlist-auto=<filename>\t\t; detect DPI blocks and build hostlist automatically\n"
|
||||
@ -213,6 +203,7 @@ static void exithelp(void)
|
||||
" --tlsrec-pos=<pos>\t\t\t; make 2 TLS records. split at specified pos\n"
|
||||
#ifdef __linux__
|
||||
" --mss=<int>\t\t\t\t; set client MSS. forces server to split messages but significantly decreases speed !\n"
|
||||
" --mss-pf=[~]port1[-port2]\t\t; MSS port filter. ~ means negation\n"
|
||||
#endif
|
||||
" --tamper-start=[n]<pos>\t\t; start tampering only from specified outbound stream position. default is 0. 'n' means data block number.\n"
|
||||
" --tamper-cutoff=[n]<pos>\t\t; do not tamper anymore after specified outbound stream position. default is unlimited.\n",
|
||||
@ -225,7 +216,11 @@ static void exithelp(void)
|
||||
}
|
||||
static void cleanup_params(void)
|
||||
{
|
||||
dp_list_destroy(¶ms.desync_profiles);
|
||||
strlist_destroy(¶ms.hostlist_files);
|
||||
strlist_destroy(¶ms.hostlist_exclude_files);
|
||||
StrPoolDestroy(¶ms.hostlist_exclude);
|
||||
StrPoolDestroy(¶ms.hostlist);
|
||||
HostFailPoolDestroy(¶ms.hostlist_auto_fail_counters);
|
||||
}
|
||||
static void exithelp_clean(void)
|
||||
{
|
||||
@ -290,32 +285,6 @@ bool parse_tlspos(const char *s, enum tlspos *pos)
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool wf_make_l3(char *opt, bool *ipv4, bool *ipv6)
|
||||
{
|
||||
char *e,*p,c;
|
||||
|
||||
for (p=opt,*ipv4=*ipv6=false ; p ; )
|
||||
{
|
||||
if ((e = strchr(p,',')))
|
||||
{
|
||||
c=*e;
|
||||
*e=0;
|
||||
}
|
||||
|
||||
if (!strcmp(p,"ipv4"))
|
||||
*ipv4 = true;
|
||||
else if (!strcmp(p,"ipv6"))
|
||||
*ipv6 = true;
|
||||
else return false;
|
||||
|
||||
if (e)
|
||||
{
|
||||
*e++=c;
|
||||
}
|
||||
p = e;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void parse_params(int argc, char *argv[])
|
||||
{
|
||||
@ -323,13 +292,18 @@ void parse_params(int argc, char *argv[])
|
||||
int v, i;
|
||||
|
||||
memset(¶ms, 0, sizeof(params));
|
||||
memcpy(params.hostspell, "host", 4); // default hostspell
|
||||
params.maxconn = DEFAULT_MAX_CONN;
|
||||
params.max_orphan_time = DEFAULT_MAX_ORPHAN_TIME;
|
||||
params.binds_last = -1;
|
||||
params.hostlist_auto_fail_threshold = HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT;
|
||||
params.hostlist_auto_fail_time = HOSTLIST_AUTO_FAIL_TIME_DEFAULT;
|
||||
#if defined(__linux__) || defined(__APPLE__)
|
||||
params.tcp_user_timeout_local = DEFAULT_TCP_USER_TIMEOUT_LOCAL;
|
||||
params.tcp_user_timeout_remote = DEFAULT_TCP_USER_TIMEOUT_REMOTE;
|
||||
#endif
|
||||
LIST_INIT(¶ms.hostlist_files);
|
||||
LIST_INIT(¶ms.hostlist_exclude_files);
|
||||
|
||||
#if defined(__OpenBSD__) || defined(__APPLE__)
|
||||
params.pf_enable = true; // OpenBSD and MacOS have no other choice
|
||||
@ -340,17 +314,6 @@ void parse_params(int argc, char *argv[])
|
||||
params.droproot = true;
|
||||
}
|
||||
|
||||
struct desync_profile_list *dpl;
|
||||
struct desync_profile *dp;
|
||||
int desync_profile_count=0;
|
||||
if (!(dpl = dp_list_add(¶ms.desync_profiles)))
|
||||
{
|
||||
DLOG_ERR("desync_profile_add: out of memory\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
dp = &dpl->dp;
|
||||
dp->n = ++desync_profile_count;
|
||||
|
||||
const struct option long_options[] = {
|
||||
{ "help",no_argument,0,0 },// optidx=0
|
||||
{ "h",no_argument,0,0 },// optidx=1
|
||||
@ -408,22 +371,18 @@ void parse_params(int argc, char *argv[])
|
||||
{ "tamper-start",required_argument,0,0 },// optidx=53
|
||||
{ "tamper-cutoff",required_argument,0,0 },// optidx=54
|
||||
{ "connect-bind-addr",required_argument,0,0 },// optidx=55
|
||||
|
||||
{ "new",no_argument,0,0 }, // optidx=56
|
||||
{ "filter-l3",required_argument,0,0 }, // optidx=57
|
||||
{ "filter-tcp",required_argument,0,0 }, // optidx=58
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
{ "enable-pf",no_argument,0,0 },// optidx=59
|
||||
{ "enable-pf",no_argument,0,0 },// optidx=56
|
||||
#elif defined(__APPLE__)
|
||||
{ "local-tcp-user-timeout",required_argument,0,0 },// optidx=59
|
||||
{ "remote-tcp-user-timeout",required_argument,0,0 },// optidx=60
|
||||
{ "local-tcp-user-timeout",required_argument,0,0 },// optidx=56
|
||||
{ "remote-tcp-user-timeout",required_argument,0,0 },// optidx=57
|
||||
#elif defined(__linux__)
|
||||
{ "local-tcp-user-timeout",required_argument,0,0 },// optidx=59
|
||||
{ "remote-tcp-user-timeout",required_argument,0,0 },// optidx=60
|
||||
{ "mss",required_argument,0,0 },// optidx=61
|
||||
{ "local-tcp-user-timeout",required_argument,0,0 },// optidx=56
|
||||
{ "remote-tcp-user-timeout",required_argument,0,0 },// optidx=57
|
||||
{ "mss",required_argument,0,0 },// optidx=58
|
||||
{ "mss-pf",required_argument,0,0 },// optidx=59
|
||||
#ifdef SPLICE_PRESENT
|
||||
{ "nosplice",no_argument,0,0 },// optidx=62
|
||||
{ "nosplice",no_argument,0,0 },// optidx=60
|
||||
#endif
|
||||
#endif
|
||||
{ "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility
|
||||
@ -554,7 +513,7 @@ void parse_params(int argc, char *argv[])
|
||||
}
|
||||
break;
|
||||
case 17: /* hostcase */
|
||||
dp->hostcase = true;
|
||||
params.hostcase = true;
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 18: /* hostspell */
|
||||
@ -563,28 +522,28 @@ void parse_params(int argc, char *argv[])
|
||||
DLOG_ERR("hostspell must be exactly 4 chars long\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
dp->hostcase = true;
|
||||
memcpy(dp->hostspell, optarg, 4);
|
||||
params.hostcase = true;
|
||||
memcpy(params.hostspell, optarg, 4);
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 19: /* hostdot */
|
||||
dp->hostdot = true;
|
||||
params.hostdot = true;
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 20: /* hostnospace */
|
||||
dp->hostnospace = true;
|
||||
params.hostnospace = true;
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 21: /* hostpad */
|
||||
dp->hostpad = atoi(optarg);
|
||||
params.hostpad = atoi(optarg);
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 22: /* domcase */
|
||||
dp->domcase = true;
|
||||
params.domcase = true;
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 23: /* split-http-req */
|
||||
if (!parse_httpreqpos(optarg, &dp->split_http_req))
|
||||
if (!parse_httpreqpos(optarg, ¶ms.split_http_req))
|
||||
{
|
||||
DLOG_ERR("Invalid argument for split-http-req\n");
|
||||
exit_clean(1);
|
||||
@ -592,7 +551,7 @@ void parse_params(int argc, char *argv[])
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 24: /* split-tls */
|
||||
if (!parse_tlspos(optarg, &dp->split_tls))
|
||||
if (!parse_tlspos(optarg, ¶ms.split_tls))
|
||||
{
|
||||
DLOG_ERR("Invalid argument for split-tls\n");
|
||||
exit_clean(1);
|
||||
@ -602,7 +561,7 @@ void parse_params(int argc, char *argv[])
|
||||
case 25: /* split-pos */
|
||||
i = atoi(optarg);
|
||||
if (i>0)
|
||||
dp->split_pos = i;
|
||||
params.split_pos = i;
|
||||
else
|
||||
{
|
||||
DLOG_ERR("Invalid argument for split-pos\n");
|
||||
@ -611,13 +570,13 @@ void parse_params(int argc, char *argv[])
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 26: /* split-any-protocol */
|
||||
dp->split_any_protocol = true;
|
||||
params.split_any_protocol = true;
|
||||
break;
|
||||
case 27: /* disorder */
|
||||
if (optarg)
|
||||
{
|
||||
if (!strcmp(optarg,"http")) dp->disorder_http=true;
|
||||
else if (!strcmp(optarg,"tls")) dp->disorder_tls=true;
|
||||
if (!strcmp(optarg,"http")) params.disorder_http=true;
|
||||
else if (!strcmp(optarg,"tls")) params.disorder_tls=true;
|
||||
else
|
||||
{
|
||||
DLOG_ERR("Invalid argument for disorder\n");
|
||||
@ -625,14 +584,14 @@ void parse_params(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
else
|
||||
dp->disorder = true;
|
||||
params.disorder = true;
|
||||
save_default_ttl();
|
||||
break;
|
||||
case 28: /* oob */
|
||||
if (optarg)
|
||||
{
|
||||
if (!strcmp(optarg,"http")) dp->oob_http=true;
|
||||
else if (!strcmp(optarg,"tls")) dp->oob_tls=true;
|
||||
if (!strcmp(optarg,"http")) params.oob_http=true;
|
||||
else if (!strcmp(optarg,"tls")) params.oob_tls=true;
|
||||
else
|
||||
{
|
||||
DLOG_ERR("Invalid argument for oob\n");
|
||||
@ -640,39 +599,39 @@ void parse_params(int argc, char *argv[])
|
||||
}
|
||||
}
|
||||
else
|
||||
dp->oob = true;
|
||||
params.oob = true;
|
||||
break;
|
||||
case 29: /* oob-data */
|
||||
{
|
||||
size_t l = strlen(optarg);
|
||||
unsigned int bt;
|
||||
if (l==1) dp->oob_byte = (uint8_t)*optarg;
|
||||
if (l==1) params.oob_byte = (uint8_t)*optarg;
|
||||
else if (l!=4 || sscanf(optarg,"0x%02X",&bt)!=1)
|
||||
{
|
||||
DLOG_ERR("Invalid argument for oob-data\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
else dp->oob_byte = (uint8_t)bt;
|
||||
else params.oob_byte = (uint8_t)bt;
|
||||
}
|
||||
break;
|
||||
case 30: /* methodspace */
|
||||
dp->methodspace = true;
|
||||
params.methodspace = true;
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 31: /* methodeol */
|
||||
dp->methodeol = true;
|
||||
params.methodeol = true;
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 32: /* hosttab */
|
||||
dp->hosttab = true;
|
||||
params.hosttab = true;
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 33: /* unixeol */
|
||||
dp->unixeol = true;
|
||||
params.unixeol = true;
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 34: /* tlsrec */
|
||||
if (!parse_tlspos(optarg, &dp->tlsrec))
|
||||
if (!parse_tlspos(optarg, ¶ms.tlsrec))
|
||||
{
|
||||
DLOG_ERR("Invalid argument for tlsrec\n");
|
||||
exit_clean(1);
|
||||
@ -680,8 +639,8 @@ void parse_params(int argc, char *argv[])
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 35: /* tlsrec-pos */
|
||||
if ((dp->tlsrec_pos = atoi(optarg))>0)
|
||||
dp->tlsrec = tlspos_pos;
|
||||
if ((params.tlsrec_pos = atoi(optarg))>0)
|
||||
params.tlsrec = tlspos_pos;
|
||||
else
|
||||
{
|
||||
DLOG_ERR("Invalid argument for tlsrec-pos\n");
|
||||
@ -690,7 +649,7 @@ void parse_params(int argc, char *argv[])
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 36: /* hostlist */
|
||||
if (!strlist_add(&dp->hostlist_files, optarg))
|
||||
if (!strlist_add(¶ms.hostlist_files, optarg))
|
||||
{
|
||||
DLOG_ERR("strlist_add failed\n");
|
||||
exit_clean(1);
|
||||
@ -698,7 +657,7 @@ void parse_params(int argc, char *argv[])
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 37: /* hostlist-exclude */
|
||||
if (!strlist_add(&dp->hostlist_exclude_files, optarg))
|
||||
if (!strlist_add(¶ms.hostlist_exclude_files, optarg))
|
||||
{
|
||||
DLOG_ERR("strlist_add failed\n");
|
||||
exit_clean(1);
|
||||
@ -706,9 +665,9 @@ void parse_params(int argc, char *argv[])
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 38: /* hostlist-auto */
|
||||
if (*dp->hostlist_auto_filename)
|
||||
if (*params.hostlist_auto_filename)
|
||||
{
|
||||
DLOG_ERR("only one auto hostlist per profile is supported\n");
|
||||
DLOG_ERR("only one auto hostlist is supported\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
{
|
||||
@ -728,26 +687,26 @@ void parse_params(int argc, char *argv[])
|
||||
if (params.droproot && chown(optarg, params.uid, -1))
|
||||
DLOG_ERR("could not chown %s. auto hostlist file may not be writable after privilege drop\n", optarg);
|
||||
}
|
||||
if (!strlist_add(&dp->hostlist_files, optarg))
|
||||
if (!strlist_add(¶ms.hostlist_files, optarg))
|
||||
{
|
||||
DLOG_ERR("strlist_add failed\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
strncpy(dp->hostlist_auto_filename, optarg, sizeof(dp->hostlist_auto_filename));
|
||||
dp->hostlist_auto_filename[sizeof(dp->hostlist_auto_filename) - 1] = '\0';
|
||||
strncpy(params.hostlist_auto_filename, optarg, sizeof(params.hostlist_auto_filename));
|
||||
params.hostlist_auto_filename[sizeof(params.hostlist_auto_filename) - 1] = '\0';
|
||||
params.tamper = true; // need to detect blocks and update autohostlist. cannot just slice.
|
||||
break;
|
||||
case 39: /* hostlist-auto-fail-threshold */
|
||||
dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
|
||||
if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20)
|
||||
params.hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
|
||||
if (params.hostlist_auto_fail_threshold<1 || params.hostlist_auto_fail_threshold>20)
|
||||
{
|
||||
DLOG_ERR("auto hostlist fail threshold must be within 1..20\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 40: /* hostlist-auto-fail-time */
|
||||
dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg);
|
||||
if (dp->hostlist_auto_fail_time<1)
|
||||
params.hostlist_auto_fail_time = (uint8_t)atoi(optarg);
|
||||
if (params.hostlist_auto_fail_time<1)
|
||||
{
|
||||
DLOG_ERR("auto hostlist fail time is not valid\n");
|
||||
exit_clean(1);
|
||||
@ -861,28 +820,26 @@ void parse_params(int argc, char *argv[])
|
||||
const char *p=optarg;
|
||||
if (*p=='n')
|
||||
{
|
||||
dp->tamper_start_n=true;
|
||||
params.tamper_start_n=true;
|
||||
p++;
|
||||
}
|
||||
else
|
||||
dp->tamper_start_n=false;
|
||||
dp->tamper_start = atoi(p);
|
||||
params.tamper_start_n=false;
|
||||
params.tamper_start = atoi(p);
|
||||
}
|
||||
params.tamper_lim = true;
|
||||
break;
|
||||
case 54: /* tamper-cutoff */
|
||||
{
|
||||
const char *p=optarg;
|
||||
if (*p=='n')
|
||||
{
|
||||
dp->tamper_cutoff_n=true;
|
||||
params.tamper_cutoff_n=true;
|
||||
p++;
|
||||
}
|
||||
else
|
||||
dp->tamper_cutoff_n=false;
|
||||
dp->tamper_cutoff = atoi(p);
|
||||
params.tamper_cutoff_n=false;
|
||||
params.tamper_cutoff = atoi(p);
|
||||
}
|
||||
params.tamper_lim = true;
|
||||
break;
|
||||
case 55: /* connect-bind-addr */
|
||||
{
|
||||
@ -911,37 +868,12 @@ void parse_params(int argc, char *argv[])
|
||||
}
|
||||
break;
|
||||
|
||||
|
||||
case 56: /* new */
|
||||
if (!(dpl = dp_list_add(¶ms.desync_profiles)))
|
||||
{
|
||||
DLOG_ERR("desync_profile_add: out of memory\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
dp = &dpl->dp;
|
||||
dp->n = ++desync_profile_count;
|
||||
break;
|
||||
case 57: /* filter-l3 */
|
||||
if (!wf_make_l3(optarg,&dp->filter_ipv4,&dp->filter_ipv6))
|
||||
{
|
||||
DLOG_ERR("bad value for --filter-l3\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 58: /* filter-tcp */
|
||||
if (!pf_parse(optarg,&dp->pf_tcp))
|
||||
{
|
||||
DLOG_ERR("Invalid port filter : %s\n",optarg);
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
case 59: /* enable-pf */
|
||||
case 56: /* enable-pf */
|
||||
params.pf_enable = true;
|
||||
break;
|
||||
#elif defined(__linux__) || defined(__APPLE__)
|
||||
case 59: /* local-tcp-user-timeout */
|
||||
case 56: /* local-tcp-user-timeout */
|
||||
params.tcp_user_timeout_local = atoi(optarg);
|
||||
if (params.tcp_user_timeout_local<0 || params.tcp_user_timeout_local>86400)
|
||||
{
|
||||
@ -949,7 +881,7 @@ void parse_params(int argc, char *argv[])
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 60: /* remote-tcp-user-timeout */
|
||||
case 57: /* remote-tcp-user-timeout */
|
||||
params.tcp_user_timeout_remote = atoi(optarg);
|
||||
if (params.tcp_user_timeout_remote<0 || params.tcp_user_timeout_remote>86400)
|
||||
{
|
||||
@ -960,17 +892,24 @@ void parse_params(int argc, char *argv[])
|
||||
#endif
|
||||
|
||||
#if defined(__linux__)
|
||||
case 61: /* mss */
|
||||
case 58: /* mss */
|
||||
// this option does not work in any BSD and MacOS. OS may accept but it changes nothing
|
||||
dp->mss = atoi(optarg);
|
||||
if (dp->mss<88 || dp->mss>32767)
|
||||
params.mss = atoi(optarg);
|
||||
if (params.mss<88 || params.mss>32767)
|
||||
{
|
||||
DLOG_ERR("Invalid value for MSS. Linux accepts MSS 88-32767.\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
case 59: /* mss-pf */
|
||||
if (!pf_parse(optarg,¶ms.mss_pf))
|
||||
{
|
||||
DLOG_ERR("Invalid MSS port filter.\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
break;
|
||||
#ifdef SPLICE_PRESENT
|
||||
case 62: /* nosplice */
|
||||
case 60: /* nosplice */
|
||||
params.nosplice = true;
|
||||
break;
|
||||
#endif
|
||||
@ -986,36 +925,22 @@ void parse_params(int argc, char *argv[])
|
||||
{
|
||||
params.binds_last=0; // default bind to all
|
||||
}
|
||||
if (!params.resolver_threads) params.resolver_threads = 5 + params.maxconn/50;
|
||||
|
||||
VPRINT("adding low-priority default empty desync profile\n");
|
||||
// add default empty profile
|
||||
if (!(dpl = dp_list_add(¶ms.desync_profiles)))
|
||||
if (params.skip_nodelay && (params.split_http_req || params.split_pos))
|
||||
{
|
||||
DLOG_ERR("desync_profile_add: out of memory\n");
|
||||
DLOG_ERR("Cannot split with --skip-nodelay\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
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;
|
||||
|
||||
DLOG_CONDUP("we have %d user defined desync profile(s) and default low priority profile 0\n",desync_profile_count);
|
||||
|
||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
||||
{
|
||||
dp = &dpl->dp;
|
||||
if (dp->split_tls==tlspos_none && dp->split_pos) dp->split_tls=tlspos_pos;
|
||||
if (dp->split_http_req==httpreqpos_none && dp->split_pos) dp->split_http_req=httpreqpos_pos;
|
||||
if (*dp->hostlist_auto_filename) dp->hostlist_auto_mod_time = file_mod_time(dp->hostlist_auto_filename);
|
||||
if (params.skip_nodelay && (dp->split_tls || dp->split_http_req || dp->split_pos))
|
||||
{
|
||||
DLOG_ERR("Cannot split with --skip-nodelay\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (*params.hostlist_auto_filename) params.hostlist_auto_mod_time = file_mod_time(params.hostlist_auto_filename);
|
||||
if (!LoadIncludeHostLists())
|
||||
{
|
||||
DLOG_ERR("Include hostlist load failed\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
if (*params.hostlist_auto_filename) NonEmptyHostlist(¶ms.hostlist);
|
||||
if (!LoadExcludeHostLists())
|
||||
{
|
||||
DLOG_ERR("Exclude hostlist load failed\n");
|
||||
@ -1132,7 +1057,7 @@ static bool set_ulimit(void)
|
||||
// additional 1/2 for unpaired remote legs sending buffers
|
||||
// 16 for listen_fd, epoll, hostlist, ...
|
||||
#ifdef SPLICE_PRESENT
|
||||
fdmax = (params.nosplice ? 2 : (params.tamper && !params.tamper_lim ? 4 : 6)) * params.maxconn;
|
||||
fdmax = (params.nosplice ? 2 : (params.tamper && !params.tamper_start && !params.tamper_cutoff ? 4 : 6)) * params.maxconn;
|
||||
#else
|
||||
fdmax = 2 * params.maxconn;
|
||||
#endif
|
||||
|
115
tpws/tpws_conn.c
115
tpws/tpws_conn.c
@ -368,7 +368,7 @@ static void set_user_timeout(int fd, int timeout)
|
||||
//Createas a socket and initiates the connection to the host specified by
|
||||
//remote_addr.
|
||||
//Returns -1 if something fails, >0 on success (socket fd).
|
||||
static int connect_remote(const struct sockaddr *remote_addr, int mss)
|
||||
static int connect_remote(const struct sockaddr *remote_addr, bool bApplyConnectionFooling)
|
||||
{
|
||||
int remote_fd = 0, yes = 1, no = 0;
|
||||
|
||||
@ -406,18 +406,24 @@ static int connect_remote(const struct sockaddr *remote_addr, int mss)
|
||||
close(remote_fd);
|
||||
return -1;
|
||||
}
|
||||
#ifdef __linux__
|
||||
if (mss)
|
||||
if (bApplyConnectionFooling && params.mss)
|
||||
{
|
||||
VPRINT("Setting MSS %d\n", mss);
|
||||
if (setsockopt(remote_fd, IPPROTO_TCP, TCP_MAXSEG, &mss, sizeof(int)) <0)
|
||||
uint16_t port = saport(remote_addr);
|
||||
if (pf_in_range(port,¶ms.mss_pf))
|
||||
{
|
||||
DLOG_PERROR("setsockopt (TCP_MAXSEG, connect_remote)");
|
||||
close(remote_fd);
|
||||
return -1;
|
||||
VPRINT("Setting MSS %d\n",params.mss);
|
||||
if (setsockopt(remote_fd, IPPROTO_TCP, TCP_MAXSEG, ¶ms.mss, sizeof(int)) <0)
|
||||
{
|
||||
DLOG_PERROR("setsockopt (TCP_MAXSEG, connect_remote)");
|
||||
close(remote_fd);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
VPRINT("Not setting MSS. Port %u is out of MSS port range.\n",port);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// if no bind address specified - address family will be 0 in params_connect_bindX
|
||||
if(remote_addr->sa_family == params.connect_bind4.sin_family)
|
||||
@ -488,12 +494,13 @@ static tproxy_conn_t *new_conn(int fd, bool remote)
|
||||
tproxy_conn_t *conn;
|
||||
|
||||
//Create connection object and fill in information
|
||||
if((conn = (tproxy_conn_t*) calloc(1, sizeof(tproxy_conn_t))) == NULL)
|
||||
if((conn = (tproxy_conn_t*) malloc(sizeof(tproxy_conn_t))) == NULL)
|
||||
{
|
||||
DLOG_ERR("Could not allocate memory for connection\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memset(conn, 0, sizeof(tproxy_conn_t));
|
||||
conn->state = CONN_UNAVAILABLE;
|
||||
conn->fd = fd;
|
||||
conn->remote = remote;
|
||||
@ -501,7 +508,7 @@ static tproxy_conn_t *new_conn(int fd, bool remote)
|
||||
#ifdef SPLICE_PRESENT
|
||||
// if dont tamper - both legs are spliced, create 2 pipes
|
||||
// otherwise create pipe only in local leg
|
||||
if (!params.nosplice && ( !remote || !params.tamper || params.tamper_lim ) && pipe2(conn->splice_pipe, O_NONBLOCK) != 0)
|
||||
if (!params.nosplice && ( !remote || !params.tamper || params.tamper_start || params.tamper_cutoff ) && pipe2(conn->splice_pipe, O_NONBLOCK) != 0)
|
||||
{
|
||||
DLOG_ERR("Could not create the splice pipe\n");
|
||||
free_conn(conn);
|
||||
@ -599,7 +606,7 @@ static tproxy_conn_t* add_tcp_connection(int efd, struct tailhead *conn_list,int
|
||||
|
||||
if (proxy_type==CONN_TYPE_TRANSPARENT)
|
||||
{
|
||||
if ((remote_fd = connect_remote((struct sockaddr *)&orig_dst, 0)) < 0)
|
||||
if ((remote_fd = connect_remote((struct sockaddr *)&orig_dst, true)) < 0)
|
||||
{
|
||||
DLOG_ERR("Failed to connect\n");
|
||||
close(local_fd);
|
||||
@ -619,8 +626,6 @@ static tproxy_conn_t* add_tcp_connection(int efd, struct tailhead *conn_list,int
|
||||
|
||||
if (proxy_type==CONN_TYPE_TRANSPARENT)
|
||||
{
|
||||
sacopy(&conn->dest, (struct sockaddr *)&orig_dst);
|
||||
|
||||
if(!(conn->partner = new_conn(remote_fd, true)))
|
||||
{
|
||||
free_conn(conn);
|
||||
@ -662,10 +667,6 @@ static tproxy_conn_t* add_tcp_connection(int efd, struct tailhead *conn_list,int
|
||||
TAILQ_INSERT_HEAD(conn_list, conn->partner, conn_ptrs);
|
||||
legs_remote++;
|
||||
}
|
||||
|
||||
if (proxy_type==CONN_TYPE_TRANSPARENT)
|
||||
apply_desync_profile(&conn->track, (struct sockaddr *)&conn->dest);
|
||||
|
||||
return conn;
|
||||
}
|
||||
|
||||
@ -781,26 +782,32 @@ static bool handle_unsent(tproxy_conn_t *conn)
|
||||
}
|
||||
|
||||
|
||||
static bool proxy_mode_connect_remote(tproxy_conn_t *conn, struct tailhead *conn_list)
|
||||
bool proxy_mode_connect_remote(const struct sockaddr *sa, tproxy_conn_t *conn, struct tailhead *conn_list)
|
||||
{
|
||||
int remote_fd;
|
||||
|
||||
if (params.debug>=1)
|
||||
{
|
||||
char ip_port[48];
|
||||
ntop46_port((struct sockaddr *)&conn->dest,ip_port,sizeof(ip_port));
|
||||
ntop46_port(sa,ip_port,sizeof(ip_port));
|
||||
VPRINT("socks target for fd=%d is : %s\n", conn->fd, ip_port);
|
||||
}
|
||||
if (check_local_ip((struct sockaddr *)&conn->dest))
|
||||
if (check_local_ip((struct sockaddr *)sa))
|
||||
{
|
||||
VPRINT("Dropping connection to local address for security reasons\n");
|
||||
socks_send_rep(conn->socks_ver, conn->fd, S5_REP_NOT_ALLOWED_BY_RULESET);
|
||||
return false;
|
||||
}
|
||||
|
||||
apply_desync_profile(&conn->track, (struct sockaddr *)&conn->dest);
|
||||
bool bConnFooling=true;
|
||||
if (conn->track.hostname && params.mss)
|
||||
{
|
||||
bConnFooling=HostlistCheck(conn->track.hostname, NULL);
|
||||
if (!bConnFooling)
|
||||
VPRINT("0-phase desync hostlist check negative. not acting on this connection.\n");
|
||||
}
|
||||
|
||||
if ((remote_fd = connect_remote((struct sockaddr *)&conn->dest, conn->track.dp ? conn->track.dp->mss : 0)) < 0)
|
||||
if ((remote_fd = connect_remote(sa, bConnFooling)) < 0)
|
||||
{
|
||||
DLOG_ERR("socks failed to connect (1) errno=%d\n", errno);
|
||||
socks_send_rep_errno(conn->socks_ver, conn->fd, errno);
|
||||
@ -838,6 +845,7 @@ static bool handle_proxy_mode(tproxy_conn_t *conn, struct tailhead *conn_list)
|
||||
|
||||
ssize_t rd,wr;
|
||||
char buf[sizeof(s5_req)]; // s5_req - the largest possible req
|
||||
struct sockaddr_storage ss;
|
||||
|
||||
// receive proxy control message
|
||||
rd=recv(conn->fd, buf, sizeof(buf), MSG_DONTWAIT);
|
||||
@ -920,10 +928,10 @@ static bool handle_proxy_mode(tproxy_conn_t *conn, struct tailhead *conn_list)
|
||||
socks4_send_rep(conn->fd, S4_REP_FAILED);
|
||||
return false;
|
||||
}
|
||||
conn->dest.ss_family = AF_INET;
|
||||
((struct sockaddr_in*)&conn->dest)->sin_port = m->port;
|
||||
((struct sockaddr_in*)&conn->dest)->sin_addr.s_addr = m->ip;
|
||||
return proxy_mode_connect_remote(conn, conn_list);
|
||||
ss.ss_family = AF_INET;
|
||||
((struct sockaddr_in*)&ss)->sin_port = m->port;
|
||||
((struct sockaddr_in*)&ss)->sin_addr.s_addr = m->ip;
|
||||
return proxy_mode_connect_remote((struct sockaddr *)&ss, conn, conn_list);
|
||||
}
|
||||
break;
|
||||
case S_WAIT_REQUEST:
|
||||
@ -952,16 +960,16 @@ static bool handle_proxy_mode(tproxy_conn_t *conn, struct tailhead *conn_list)
|
||||
switch(m->atyp)
|
||||
{
|
||||
case S5_ATYP_IP4:
|
||||
conn->dest.ss_family = AF_INET;
|
||||
((struct sockaddr_in*)&conn->dest)->sin_port = m->d4.port;
|
||||
((struct sockaddr_in*)&conn->dest)->sin_addr = m->d4.addr;
|
||||
ss.ss_family = AF_INET;
|
||||
((struct sockaddr_in*)&ss)->sin_port = m->d4.port;
|
||||
((struct sockaddr_in*)&ss)->sin_addr = m->d4.addr;
|
||||
break;
|
||||
case S5_ATYP_IP6:
|
||||
conn->dest.ss_family = AF_INET6;
|
||||
((struct sockaddr_in6*)&conn->dest)->sin6_port = m->d6.port;
|
||||
((struct sockaddr_in6*)&conn->dest)->sin6_addr = m->d6.addr;
|
||||
((struct sockaddr_in6*)&conn->dest)->sin6_flowinfo = 0;
|
||||
((struct sockaddr_in6*)&conn->dest)->sin6_scope_id = 0;
|
||||
ss.ss_family = AF_INET6;
|
||||
((struct sockaddr_in6*)&ss)->sin6_port = m->d6.port;
|
||||
((struct sockaddr_in6*)&ss)->sin6_addr = m->d6.addr;
|
||||
((struct sockaddr_in6*)&ss)->sin6_flowinfo = 0;
|
||||
((struct sockaddr_in6*)&ss)->sin6_scope_id = 0;
|
||||
break;
|
||||
case S5_ATYP_DOM:
|
||||
{
|
||||
@ -998,7 +1006,7 @@ static bool handle_proxy_mode(tproxy_conn_t *conn, struct tailhead *conn_list)
|
||||
return false; // should not be here. S5_REQ_CONNECT_VALID checks for valid atyp
|
||||
|
||||
}
|
||||
return proxy_mode_connect_remote(conn,conn_list);
|
||||
return proxy_mode_connect_remote((struct sockaddr *)&ss,conn,conn_list);
|
||||
}
|
||||
break;
|
||||
case S_WAIT_RESOLVE:
|
||||
@ -1037,8 +1045,7 @@ static bool resolve_complete(struct resolve_item *ri, struct tailhead *conn_list
|
||||
DBGPRINT("resolve_complete put hostname : %s\n", ri->dom);
|
||||
conn->track.hostname = strdup(ri->dom);
|
||||
}
|
||||
sacopy(&conn->dest, (struct sockaddr *)&ri->ss);
|
||||
return proxy_mode_connect_remote(conn,conn_list);
|
||||
return proxy_mode_connect_remote((struct sockaddr *)&ri->ss,conn,conn_list);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -1053,17 +1060,8 @@ static bool resolve_complete(struct resolve_item *ri, struct tailhead *conn_list
|
||||
|
||||
static bool in_tamper_out_range(tproxy_conn_t *conn)
|
||||
{
|
||||
if (!conn->track.dp) return true;
|
||||
bool in_range = \
|
||||
((conn->track.dp->tamper_start_n ? (conn->tnrd+1) : conn->trd) >= conn->track.dp->tamper_start &&
|
||||
(!conn->track.dp->tamper_cutoff || (conn->track.dp->tamper_cutoff_n ? (conn->tnrd+1) : conn->trd) < conn->track.dp->tamper_cutoff));
|
||||
DBGPRINT("tamper_out range check. stream pos %" PRIu64 "(n%" PRIu64 "). tamper range %s%u-%s%u (%s)\n",
|
||||
conn->trd, conn->tnrd+1,
|
||||
conn->track.dp ? conn->track.dp->tamper_start_n ? "n" : "" : "?" , conn->track.dp ? conn->track.dp->tamper_start : 0,
|
||||
conn->track.dp ? conn->track.dp->tamper_cutoff_n ? "n" : "" : "?" , conn->track.dp ? conn->track.dp->tamper_cutoff : 0,
|
||||
in_range ? "IN RANGE" : "OUT OF RANGE");
|
||||
return in_range;
|
||||
|
||||
return (params.tamper_start_n ? (conn->tnrd+1) : conn->trd) >= params.tamper_start &&
|
||||
(!params.tamper_cutoff || (params.tamper_cutoff_n ? (conn->tnrd+1) : conn->trd) < params.tamper_cutoff);
|
||||
}
|
||||
|
||||
static void tamper(tproxy_conn_t *conn, uint8_t *segment, size_t segment_buffer_size, size_t *segment_size, size_t *split_pos, uint8_t *split_flags)
|
||||
@ -1074,26 +1072,33 @@ static void tamper(tproxy_conn_t *conn, uint8_t *segment, size_t segment_buffer_
|
||||
if (conn->remote)
|
||||
{
|
||||
if (conn_partner_alive(conn) && !conn->partner->track.bTamperInCutoff)
|
||||
{
|
||||
tamper_in(&conn->partner->track,segment,segment_buffer_size,segment_size);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (in_tamper_out_range(conn))
|
||||
tamper_out(&conn->track,(struct sockaddr*)&conn->dest,segment,segment_buffer_size,segment_size,split_pos,split_flags);
|
||||
bool in_range = in_tamper_out_range(conn);
|
||||
DBGPRINT("tamper_out stream pos %" PRIu64 "(n%" PRIu64 "). tamper range %s%u-%s%u (%s)\n",
|
||||
conn->trd, conn->tnrd+1,
|
||||
params.tamper_start_n ? "n" : "" , params.tamper_start,
|
||||
params.tamper_cutoff_n ? "n" : "" , params.tamper_cutoff,
|
||||
in_range ? "IN RANGE" : "OUT OF RANGE");
|
||||
if (in_range) tamper_out(&conn->track,segment,segment_buffer_size,segment_size,split_pos,split_flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// buffer must have at least one extra byte for OOB
|
||||
static ssize_t send_or_buffer_oob(send_buffer_t *sb, int fd, uint8_t *buf, size_t len, int ttl, bool oob, uint8_t oob_byte)
|
||||
static ssize_t send_or_buffer_oob(send_buffer_t *sb, int fd, uint8_t *buf, size_t len, int ttl, bool oob)
|
||||
{
|
||||
ssize_t wr;
|
||||
if (oob)
|
||||
{
|
||||
VPRINT("Sending OOB byte %02X\n", oob_byte);
|
||||
VPRINT("Sending OOB byte %02X\n", params.oob_byte);
|
||||
uint8_t oob_save;
|
||||
oob_save = buf[len];
|
||||
buf[len] = oob_byte;
|
||||
buf[len] = params.oob_byte;
|
||||
wr = send_or_buffer(sb, fd, buf, len+1, MSG_OOB, ttl);
|
||||
buf[len] = oob_save;
|
||||
}
|
||||
@ -1206,7 +1211,7 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32
|
||||
{
|
||||
VPRINT("Splitting at pos %zu%s\n", split_pos, (split_flags & SPLIT_FLAG_DISORDER) ? " with disorder" : "");
|
||||
|
||||
wr = send_or_buffer_oob(conn->partner->wr_buf, conn->partner->fd, buf, split_pos, !!(split_flags & SPLIT_FLAG_DISORDER), !!(split_flags & SPLIT_FLAG_OOB), conn->track.dp ? conn->track.dp->oob_byte : 0);
|
||||
wr = send_or_buffer_oob(conn->partner->wr_buf, conn->partner->fd, buf, split_pos, !!(split_flags & SPLIT_FLAG_DISORDER), !!(split_flags & SPLIT_FLAG_OOB));
|
||||
DBGPRINT("send_or_buffer(1) fd=%d wr=%zd err=%d\n",conn->partner->fd,wr,errno);
|
||||
if (wr >= 0)
|
||||
{
|
||||
|
@ -54,7 +54,6 @@ struct tproxy_conn
|
||||
int splice_pipe[2];
|
||||
conn_state_t state;
|
||||
conn_type_t conn_type;
|
||||
struct sockaddr_storage dest;
|
||||
|
||||
struct tproxy_conn *partner; // other leg
|
||||
time_t orphan_since;
|
||||
|
Loading…
Reference in New Issue
Block a user