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
|
done
|
||||||
else
|
else
|
||||||
for mss in '' 88; do
|
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 s2 in '' '--oob' '--disorder' '--oob --disorder'; do
|
||||||
for pos in sni sniext; do
|
for pos in sni sniext; do
|
||||||
s="--split-tls=$pos"
|
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)
|
if (fail_counter)
|
||||||
{
|
{
|
||||||
HostFailPoolDel(&dp->hostlist_auto_fail_counters, 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);
|
DLOG("auto hostlist : %s : fail counter reset. website is working.\n", hostname);
|
||||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : fail counter reset. website is working.", hostname, dp->n);
|
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++;
|
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);
|
DLOG("auto hostlist : %s : fail counter %d/%d\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);
|
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)
|
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);
|
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;
|
bool bExcluded=false;
|
||||||
if (!HostlistCheck(dp, hostname, &bExcluded) && !bExcluded)
|
if (!HostlistCheck(dp, hostname, &bExcluded) && !bExcluded)
|
||||||
{
|
{
|
||||||
DLOG("auto hostlist (profile %d) : adding %s to %s\n", dp->n, hostname, dp->hostlist_auto_filename);
|
DLOG("auto hostlist : adding %s\n", hostname);
|
||||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : adding to %s", hostname, dp->n, dp->hostlist_auto_filename);
|
HOSTLIST_DEBUGLOG_APPEND("%s : adding", hostname);
|
||||||
if (!StrPoolAddStr(&dp->hostlist, hostname))
|
if (!StrPoolAddStr(&dp->hostlist, hostname))
|
||||||
{
|
{
|
||||||
fprintf(stderr, "StrPoolAddStr out of memory\n");
|
fprintf(stderr, "StrPoolAddStr out of memory\n");
|
||||||
@ -358,8 +358,8 @@ static void auto_hostlist_failed(struct desync_profile *dp, const char *hostname
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DLOG("auto hostlist (profile %d) : NOT adding %s\n", dp->n, hostname);
|
DLOG("auto hostlist : NOT adding %s\n", hostname);
|
||||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : NOT adding, duplicate detected", hostname, dp->n);
|
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))
|
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);
|
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)
|
if (tcphdr->th_flags & TH_RST)
|
||||||
{
|
{
|
||||||
DLOG("incoming RST detected for hostname %s\n", ctrack->hostname);
|
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;
|
bFail = true;
|
||||||
}
|
}
|
||||||
else if (len_payload && ctrack->l7proto==HTTP)
|
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)
|
if (bFail)
|
||||||
{
|
{
|
||||||
DLOG("redirect to another domain detected. possibly DPI redirect.\n");
|
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
|
else
|
||||||
DLOG("local or in-domain redirect detected. it's not a DPI redirect.\n");
|
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)
|
bool pf_parse(const char *s, port_filter *pf)
|
||||||
{
|
{
|
||||||
unsigned int v1,v2;
|
unsigned int v1,v2;
|
||||||
char c;
|
|
||||||
|
|
||||||
if (!s) return false;
|
if (!s) return false;
|
||||||
if (*s=='~')
|
if (*s=='~')
|
||||||
@ -329,13 +328,13 @@ bool pf_parse(const char *s, port_filter *pf)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
pf->neg=false;
|
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>65535 || v2>65535 || v1>v2) return false;
|
||||||
pf->from=(uint16_t)v1;
|
pf->from=(uint16_t)v1;
|
||||||
pf->to=(uint16_t)v2;
|
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>65535) return false;
|
||||||
pf->to=pf->from=(uint16_t)v1;
|
pf->to=pf->from=(uint16_t)v1;
|
||||||
|
@ -164,21 +164,6 @@ bool saconvmapped(struct sockaddr_storage *a)
|
|||||||
return false;
|
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)
|
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
|
// 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)
|
bool pf_parse(const char *s, port_filter *pf)
|
||||||
{
|
{
|
||||||
unsigned int v1,v2;
|
unsigned int v1,v2;
|
||||||
char c;
|
|
||||||
|
|
||||||
if (!s) return false;
|
if (!s) return false;
|
||||||
if (*s=='~')
|
if (*s=='~')
|
||||||
{
|
{
|
||||||
pf->neg=true;
|
pf->neg=true;
|
||||||
s++;
|
s++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pf->neg=false;
|
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->from=(uint16_t)v1;
|
||||||
pf->to=(uint16_t)v2;
|
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;
|
pf->to=pf->from=(uint16_t)v1;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
// deny all case
|
|
||||||
if (!pf->from && !pf->to) pf->neg=true;
|
|
||||||
return 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
|
// true = was converted
|
||||||
bool saconvmapped(struct sockaddr_storage *a);
|
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_localnet(const struct sockaddr *a);
|
||||||
bool is_linklocal(const struct sockaddr_in6* a);
|
bool is_linklocal(const struct sockaddr_in6* a);
|
||||||
bool is_private6(const struct sockaddr_in6* a);
|
bool is_private6(const struct sockaddr_in6* a);
|
||||||
@ -57,7 +55,6 @@ typedef struct
|
|||||||
} port_filter;
|
} port_filter;
|
||||||
bool pf_in_range(uint16_t port, const port_filter *pf);
|
bool pf_in_range(uint16_t port, const port_filter *pf);
|
||||||
bool pf_parse(const char *s, port_filter *pf);
|
bool pf_parse(const char *s, port_filter *pf);
|
||||||
bool pf_is_empty(const port_filter *pf);
|
|
||||||
|
|
||||||
#ifndef IN_LOOPBACK
|
#ifndef IN_LOOPBACK
|
||||||
#define IN_LOOPBACK(a) ((((uint32_t) (a)) & 0xff000000) == 0x7f000000)
|
#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;
|
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
|
// 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 (*params.hostlist_auto_filename)
|
||||||
if (*dp->hostlist_auto_filename)
|
|
||||||
{
|
{
|
||||||
time_t t = file_mod_time(dp->hostlist_auto_filename);
|
time_t t = file_mod_time(params.hostlist_auto_filename);
|
||||||
if (t!=dp->hostlist_auto_mod_time)
|
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);
|
DLOG_CONDUP("Autohostlist was modified by another process. Reloading include hostslist.\n");
|
||||||
if (!LoadIncludeHostListsForProfile(dp))
|
if (!LoadIncludeHostLists())
|
||||||
{
|
{
|
||||||
// what will we do without hostlist ?? sure, gonna die
|
// what will we do without hostlist ?? sure, gonna die
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
dp->hostlist_auto_mod_time = t;
|
params.hostlist_auto_mod_time = t;
|
||||||
NonEmptyHostlist(&dp->hostlist);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return HostlistCheck_(dp->hostlist, dp->hostlist_exclude, host, excluded);
|
return HostlistCheck_(params.hostlist, params.hostlist_exclude, host, excluded);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool LoadIncludeHostLists()
|
bool LoadIncludeHostLists()
|
||||||
{
|
{
|
||||||
struct desync_profile_list *dpl;
|
if (!LoadHostLists(¶ms.hostlist, ¶ms.hostlist_files))
|
||||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
return false;
|
||||||
if (!LoadIncludeHostListsForProfile(&dpl->dp))
|
if (*params.hostlist_auto_filename)
|
||||||
return false;
|
params.hostlist_auto_mod_time = file_mod_time(params.hostlist_auto_filename);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
bool LoadExcludeHostLists()
|
bool LoadExcludeHostLists()
|
||||||
{
|
{
|
||||||
struct desync_profile_list *dpl;
|
return LoadHostLists(¶ms.hostlist_exclude, ¶ms.hostlist_exclude_files);
|
||||||
LIST_FOREACH(dpl, ¶ms.desync_profiles, next)
|
|
||||||
if (!LoadHostLists(&dpl->dp.hostlist_exclude, &dpl->dp.hostlist_exclude_files))
|
|
||||||
return false;
|
|
||||||
return true;
|
|
||||||
}
|
}
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include "pools.h"
|
#include "pools.h"
|
||||||
#include "params.h"
|
|
||||||
|
|
||||||
bool AppendHostList(strpool **hostlist, char *filename);
|
bool AppendHostList(strpool **hostlist, char *filename);
|
||||||
bool LoadHostLists(strpool **hostlist, struct str_list_head *file_list);
|
bool LoadHostLists(strpool **hostlist, struct str_list_head *file_list);
|
||||||
@ -11,4 +10,4 @@ bool LoadExcludeHostLists();
|
|||||||
bool NonEmptyHostlist(strpool **hostlist);
|
bool NonEmptyHostlist(strpool **hostlist);
|
||||||
bool SearchHostList(strpool *hostlist, const char *host);
|
bool SearchHostList(strpool *hostlist, const char *host);
|
||||||
// return : true = apply fooling, false = do not apply
|
// 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
|
else
|
||||||
return 0;
|
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 };
|
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;
|
bool hostcase, hostdot, hosttab, hostnospace, methodspace, methodeol, unixeol, domcase;
|
||||||
int hostpad;
|
int hostpad;
|
||||||
char hostspell[4];
|
char hostspell[4];
|
||||||
@ -43,59 +60,30 @@ struct desync_profile
|
|||||||
bool disorder, disorder_http, disorder_tls;
|
bool disorder, disorder_http, disorder_tls;
|
||||||
bool oob, oob_http, oob_tls;
|
bool oob, oob_http, oob_tls;
|
||||||
uint8_t oob_byte;
|
uint8_t oob_byte;
|
||||||
|
int ttl_default;
|
||||||
|
|
||||||
int mss;
|
int mss;
|
||||||
|
port_filter mss_pf;
|
||||||
|
|
||||||
bool tamper_start_n,tamper_cutoff_n;
|
char pidfile[256];
|
||||||
unsigned int tamper_start,tamper_cutoff;
|
|
||||||
|
|
||||||
bool filter_ipv4,filter_ipv6;
|
|
||||||
port_filter pf_tcp;
|
|
||||||
|
|
||||||
strpool *hostlist, *hostlist_exclude;
|
strpool *hostlist, *hostlist_exclude;
|
||||||
struct str_list_head hostlist_files, hostlist_exclude_files;
|
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;
|
int hostlist_auto_fail_threshold, hostlist_auto_fail_time;
|
||||||
time_t hostlist_auto_mod_time;
|
time_t hostlist_auto_mod_time;
|
||||||
hostfail_pool *hostlist_auto_fail_counters;
|
hostfail_pool *hostlist_auto_fail_counters;
|
||||||
};
|
|
||||||
|
|
||||||
struct desync_profile_list {
|
bool tamper_start_n,tamper_cutoff_n;
|
||||||
struct desync_profile dp;
|
unsigned int tamper_start,tamper_cutoff;
|
||||||
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);
|
|
||||||
|
|
||||||
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_in connect_bind4;
|
||||||
struct sockaddr_in6 connect_bind6;
|
struct sockaddr_in6 connect_bind6;
|
||||||
char connect_bind6_ifname[IF_NAMESIZE];
|
char connect_bind6_ifname[IF_NAMESIZE];
|
||||||
|
|
||||||
uint8_t proxy_type;
|
int debug;
|
||||||
bool no_resolve;
|
enum log_target debug_target;
|
||||||
bool skip_nodelay;
|
char debug_logfile[PATH_MAX];
|
||||||
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
|
|
||||||
|
|
||||||
#if defined(BSD)
|
#if defined(BSD)
|
||||||
bool pf_enable;
|
bool pf_enable;
|
||||||
@ -103,13 +91,6 @@ struct params_s
|
|||||||
#ifdef SPLICE_PRESENT
|
#ifdef SPLICE_PRESENT
|
||||||
bool nosplice;
|
bool nosplice;
|
||||||
#endif
|
#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;
|
extern struct params_s params;
|
||||||
|
@ -25,45 +25,12 @@ bool IsHttp(const uint8_t *data, size_t len)
|
|||||||
{
|
{
|
||||||
return !!HttpMethod(data,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: ..."
|
// pHost points to "Host: ..."
|
||||||
bool HttpFindHost(uint8_t **pHost,uint8_t *buf,size_t bs)
|
bool HttpFindHost(uint8_t **pHost,uint8_t *buf,size_t bs)
|
||||||
{
|
{
|
||||||
if (!*pHost)
|
if (!*pHost)
|
||||||
{
|
{
|
||||||
*pHost = FindHostIn(buf, bs);
|
*pHost = memmem(buf, bs, "\nHost:", 6);
|
||||||
if (*pHost) (*pHost)++;
|
if (*pHost) (*pHost)++;
|
||||||
}
|
}
|
||||||
return !!*pHost;
|
return !!*pHost;
|
||||||
@ -72,7 +39,7 @@ bool HttpFindHostConst(const uint8_t **pHost,const uint8_t *buf,size_t bs)
|
|||||||
{
|
{
|
||||||
if (!*pHost)
|
if (!*pHost)
|
||||||
{
|
{
|
||||||
*pHost = FindHostInConst(buf, bs);
|
*pHost = memmem(buf, bs, "\nHost:", 6);
|
||||||
if (*pHost) (*pHost)++;
|
if (*pHost) (*pHost)++;
|
||||||
}
|
}
|
||||||
return !!*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)
|
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;
|
int i;
|
||||||
|
|
||||||
switch(tpos_type)
|
switch(tpos_type)
|
||||||
|
316
tpws/tamper.c
316
tpws/tamper.c
@ -1,87 +1,24 @@
|
|||||||
#define _GNU_SOURCE
|
#define _GNU_SOURCE
|
||||||
|
|
||||||
#include "tamper.h"
|
#include "tamper.h"
|
||||||
|
#include "params.h"
|
||||||
#include "hostlist.h"
|
#include "hostlist.h"
|
||||||
#include "protocol.h"
|
#include "protocol.h"
|
||||||
#include "helpers.h"
|
#include "helpers.h"
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.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
|
// 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;
|
uint8_t *p, *pp, *pHost = NULL;
|
||||||
size_t method_len = 0, pos;
|
size_t method_len = 0, pos;
|
||||||
size_t tpos, spos;
|
|
||||||
const char *method;
|
const char *method;
|
||||||
bool bHaveHost = false;
|
bool bBypass = false, bHaveHost = false, bHostExcluded = false;
|
||||||
char *pc, Host[256];
|
char *pc, Host[256];
|
||||||
t_l7proto l7proto;
|
|
||||||
|
|
||||||
DBGPRINT("tamper_out\n");
|
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_pos=0;
|
||||||
*split_flags=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;
|
method_len = strlen(method)-2;
|
||||||
VPRINT("Data block looks like http request start : %s\n", method);
|
VPRINT("Data block looks like http request start : %s\n", method);
|
||||||
l7proto=HTTP;
|
if (!ctrack->l7proto) ctrack->l7proto=HTTP;
|
||||||
if (HttpFindHost(&pHost,segment,*size))
|
// 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;
|
p = pHost + 5;
|
||||||
while (p < (segment + *size) && (*p == ' ' || *p == '\t')) p++;
|
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);
|
memcpy(Host, p, pp - p);
|
||||||
Host[pp - p] = '\0';
|
Host[pp - p] = '\0';
|
||||||
bHaveHost = true;
|
bHaveHost = true;
|
||||||
|
VPRINT("Requested Host is : %s\n", Host);
|
||||||
for(pc = Host; *pc; pc++) *pc=tolower(*pc);
|
for(pc = Host; *pc; pc++) *pc=tolower(*pc);
|
||||||
|
bBypass = !HostlistCheck(Host, &bHostExcluded);
|
||||||
}
|
}
|
||||||
}
|
if (!bBypass)
|
||||||
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 (!(ctrack->hostname=strdup(Host)))
|
if (params.unixeol)
|
||||||
{
|
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
p = pp = segment;
|
p = pp = segment;
|
||||||
while ((p = memmem(p, segment + *size - p, "\r\n", 2)))
|
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
|
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");
|
VPRINT("Adding EOL before method\n");
|
||||||
if (ctrack->dp->unixeol)
|
if (params.unixeol)
|
||||||
{
|
{
|
||||||
memmove(segment + 1, segment, *size);
|
memmove(segment + 1, segment, *size);
|
||||||
(*size)++;;
|
(*size)++;;
|
||||||
@ -185,7 +79,7 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
|||||||
}
|
}
|
||||||
pHost = NULL; // invalidate
|
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
|
// we only work with data blocks looking as HTTP query, so method is at the beginning
|
||||||
VPRINT("Adding extra space after method\n");
|
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
|
(*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 ((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;
|
p = pHost + 5;
|
||||||
while (p < (segment + *size) && *p != '\r' && *p != '\n') p++;
|
while (p < (segment + *size) && *p != '\r' && *p != '\n') p++;
|
||||||
if (p < (segment + *size))
|
if (p < (segment + *size))
|
||||||
{
|
{
|
||||||
pos = p - segment;
|
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);
|
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
|
(*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;
|
p = pHost + 5;
|
||||||
pos = p - segment;
|
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++)
|
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 (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;
|
p = pHost + 6;
|
||||||
pos = p - segment;
|
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);
|
memmove(p - 1, p, *size - pos);
|
||||||
(*size)--; // block will shrink by 1 byte
|
(*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);
|
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, ctrack->dp->hostspell, 4);
|
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]
|
// add : XXXXX: <padding?[\r\n|\n]
|
||||||
char s[8];
|
char s[8];
|
||||||
size_t hsize = ctrack->dp->unixeol ? 8 : 9;
|
size_t hsize = params.unixeol ? 8 : 9;
|
||||||
size_t hostpad = ctrack->dp->hostpad<hsize ? hsize : ctrack->dp->hostpad;
|
size_t hostpad = params.hostpad<hsize ? hsize : params.hostpad;
|
||||||
|
|
||||||
if ((hsize+*size)>segment_buffer_size)
|
if ((hsize+*size)>segment_buffer_size)
|
||||||
VPRINT("could not add host padding : buffer too small\n");
|
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;
|
p+=7;
|
||||||
memset(p,'a'+rand()%('z'-'a'+1),padsize);
|
memset(p,'a'+rand()%('z'-'a'+1),padsize);
|
||||||
p+=padsize;
|
p+=padsize;
|
||||||
if (ctrack->dp->unixeol)
|
if (params.unixeol)
|
||||||
*p++='\n';
|
*p++='\n';
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -277,16 +171,40 @@ void tamper_out(t_ctrack *ctrack, const struct sockaddr *dest, uint8_t *segment,
|
|||||||
pHost = NULL; // invalidate
|
pHost = NULL; // invalidate
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
*split_pos = HttpPos(ctrack->dp->split_http_req, ctrack->dp->split_pos, segment, *size);
|
*split_pos = HttpPos(params.split_http_req, params.split_pos, segment, *size);
|
||||||
if (ctrack->dp->disorder_http) *split_flags |= SPLIT_FLAG_DISORDER;
|
if (params.disorder_http) *split_flags |= SPLIT_FLAG_DISORDER;
|
||||||
if (ctrack->dp->oob_http) *split_flags |= SPLIT_FLAG_OOB;
|
if (params.oob_http) *split_flags |= SPLIT_FLAG_OOB;
|
||||||
break;
|
}
|
||||||
|
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)
|
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)
|
if (tpos>5)
|
||||||
{
|
{
|
||||||
// construct 2 TLS records from one
|
// 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)
|
if (spos && spos < *size)
|
||||||
|
{
|
||||||
|
VPRINT("split pos %zu\n",spos);
|
||||||
*split_pos = spos;
|
*split_pos = spos;
|
||||||
|
}
|
||||||
|
|
||||||
if (ctrack->dp->disorder_tls) *split_flags |= SPLIT_FLAG_DISORDER;
|
if (params.disorder_tls) *split_flags |= SPLIT_FLAG_DISORDER;
|
||||||
if (ctrack->dp->oob_tls) *split_flags |= SPLIT_FLAG_OOB;
|
if (params.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;
|
|
||||||
}
|
}
|
||||||
|
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 (bHaveHost && bBypass && !bHostExcluded && *params.hostlist_auto_filename)
|
||||||
if (ctrack->dp->oob) *split_flags |= SPLIT_FLAG_OOB;
|
{
|
||||||
|
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)
|
if (hostname)
|
||||||
{
|
{
|
||||||
hostfail_pool *fail_counter;
|
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)
|
if (fail_counter)
|
||||||
{
|
{
|
||||||
HostFailPoolDel(&dp->hostlist_auto_fail_counters, fail_counter);
|
HostFailPoolDel(¶ms.hostlist_auto_fail_counters, fail_counter);
|
||||||
VPRINT("auto hostlist (profile %d) : %s : fail counter reset. website is working.\n", dp->n, hostname);
|
VPRINT("auto hostlist : %s : fail counter reset. website is working.\n", hostname);
|
||||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : fail counter reset. website is working.", hostname, dp->n);
|
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;
|
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)
|
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)
|
if (!fail_counter)
|
||||||
{
|
{
|
||||||
DLOG_ERR("HostFailPoolAdd: out of memory\n");
|
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++;
|
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);
|
VPRINT("auto hostlist : %s : fail counter %d/%d\n", hostname, fail_counter->counter, params.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);
|
HOSTLIST_DEBUGLOG_APPEND("%s : fail counter %d/%d", hostname, fail_counter->counter, params.hostlist_auto_fail_threshold);
|
||||||
if (fail_counter->counter >= dp->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);
|
VPRINT("auto hostlist : fail threshold reached. adding %s to auto hostlist\n", hostname);
|
||||||
HostFailPoolDel(&dp->hostlist_auto_fail_counters, fail_counter);
|
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;
|
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);
|
VPRINT("auto hostlist : adding %s\n", hostname);
|
||||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : adding to %s", hostname, dp->n, dp->hostlist_auto_filename);
|
HOSTLIST_DEBUGLOG_APPEND("%s : adding", hostname);
|
||||||
if (!StrPoolAddStr(&dp->hostlist, hostname))
|
if (!StrPoolAddStr(¶ms.hostlist, hostname))
|
||||||
{
|
{
|
||||||
DLOG_ERR("StrPoolAddStr out of memory\n");
|
DLOG_ERR("StrPoolAddStr out of memory\n");
|
||||||
return;
|
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:");
|
DLOG_PERROR("write to auto hostlist:");
|
||||||
return;
|
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
|
else
|
||||||
{
|
{
|
||||||
VPRINT("auto hostlist (profile %d) : NOT adding %s\n", dp->n, hostname);
|
VPRINT("auto hostlist : NOT adding %s\n", hostname);
|
||||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : NOT adding, duplicate detected", hostname, dp->n);
|
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);
|
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)
|
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)
|
if (bFail)
|
||||||
{
|
{
|
||||||
VPRINT("redirect to another domain detected. possibly DPI redirect.\n");
|
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
|
else
|
||||||
VPRINT("local or in-domain redirect detected. it's not a DPI redirect.\n");
|
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
|
// received not http reply. do not monitor this connection anymore
|
||||||
VPRINT("incoming unknown HTTP data detected for hostname %s\n", ctrack->hostname);
|
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;
|
ctrack->bTamperInCutoff = true;
|
||||||
}
|
}
|
||||||
@ -430,32 +356,30 @@ void rst_in(t_ctrack *ctrack)
|
|||||||
{
|
{
|
||||||
DBGPRINT("rst_in hostname=%s\n", ctrack->hostname);
|
DBGPRINT("rst_in hostname=%s\n", ctrack->hostname);
|
||||||
|
|
||||||
if (ctrack->dp && ctrack->b_ah_check)
|
if (!*params.hostlist_auto_filename) return;
|
||||||
{
|
|
||||||
HostFailPoolPurgeRateLimited(&ctrack->dp->hostlist_auto_fail_counters);
|
|
||||||
|
|
||||||
if (!ctrack->bTamperInCutoff && ctrack->hostname)
|
HostFailPoolPurgeRateLimited(¶ms.hostlist_auto_fail_counters);
|
||||||
{
|
|
||||||
VPRINT("incoming RST detected for hostname %s\n", ctrack->hostname);
|
if (!ctrack->bTamperInCutoff && ctrack->hostname)
|
||||||
HOSTLIST_DEBUGLOG_APPEND("%s : profile %d : incoming RST", ctrack->hostname, ctrack->dp->n);
|
{
|
||||||
auto_hostlist_failed(ctrack->dp, 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)
|
void hup_out(t_ctrack *ctrack)
|
||||||
{
|
{
|
||||||
DBGPRINT("hup_out hostname=%s\n", ctrack->hostname);
|
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)
|
if (!*params.hostlist_auto_filename) return;
|
||||||
{
|
|
||||||
// local leg dropped connection after first request. probably due to timeout.
|
HostFailPoolPurgeRateLimited(¶ms.hostlist_auto_fail_counters);
|
||||||
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);
|
if (!ctrack->bTamperInCutoff && ctrack->hostname)
|
||||||
auto_hostlist_failed(ctrack->dp, 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 <stdint.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "params.h"
|
|
||||||
|
|
||||||
#define SPLIT_FLAG_DISORDER 0x01
|
#define SPLIT_FLAG_DISORDER 0x01
|
||||||
#define SPLIT_FLAG_OOB 0x02
|
#define SPLIT_FLAG_OOB 0x02
|
||||||
|
|
||||||
@ -16,14 +14,10 @@ typedef struct
|
|||||||
t_l7proto l7proto;
|
t_l7proto l7proto;
|
||||||
bool bFirstReplyChecked;
|
bool bFirstReplyChecked;
|
||||||
bool bTamperInCutoff;
|
bool bTamperInCutoff;
|
||||||
bool b_ah_check;
|
|
||||||
char *hostname;
|
char *hostname;
|
||||||
struct desync_profile *dp; // desync profile cache
|
|
||||||
} t_ctrack;
|
} t_ctrack;
|
||||||
|
|
||||||
void apply_desync_profile(t_ctrack *ctrack, const struct sockaddr *dest);
|
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, 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_in(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,size_t *size);
|
void tamper_in(t_ctrack *ctrack, uint8_t *segment,size_t segment_buffer_size,size_t *size);
|
||||||
// connection reset by remote leg
|
// connection reset by remote leg
|
||||||
void rst_in(t_ctrack *ctrack);
|
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)
|
static void onhup(int sig)
|
||||||
{
|
{
|
||||||
printf("HUP received !\n");
|
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;
|
bHup = true;
|
||||||
}
|
}
|
||||||
// should be called in normal execution
|
// should be called in normal execution
|
||||||
@ -66,14 +67,7 @@ void dohup(void)
|
|||||||
static void onusr2(int sig)
|
static void onusr2(int sig)
|
||||||
{
|
{
|
||||||
printf("\nHOSTFAIL POOL DUMP\n");
|
printf("\nHOSTFAIL POOL DUMP\n");
|
||||||
|
HostFailPoolDump(params.hostlist_auto_fail_counters);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
printf("\n");
|
printf("\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -176,11 +170,7 @@ static void exithelp(void)
|
|||||||
#endif
|
#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=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"
|
" --debug-level=0|1|2\t\t\t; specify debug level\n"
|
||||||
"\nMULTI-STRATEGY:\n"
|
"\nFILTER:\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"
|
|
||||||
" --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=<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-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"
|
" --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"
|
" --tlsrec-pos=<pos>\t\t\t; make 2 TLS records. split at specified pos\n"
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
" --mss=<int>\t\t\t\t; set client MSS. forces server to split messages but significantly decreases speed !\n"
|
" --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
|
#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-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",
|
" --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)
|
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)
|
static void exithelp_clean(void)
|
||||||
{
|
{
|
||||||
@ -290,32 +285,6 @@ bool parse_tlspos(const char *s, enum tlspos *pos)
|
|||||||
return true;
|
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[])
|
void parse_params(int argc, char *argv[])
|
||||||
{
|
{
|
||||||
@ -323,13 +292,18 @@ void parse_params(int argc, char *argv[])
|
|||||||
int v, i;
|
int v, i;
|
||||||
|
|
||||||
memset(¶ms, 0, sizeof(params));
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
memcpy(params.hostspell, "host", 4); // default hostspell
|
||||||
params.maxconn = DEFAULT_MAX_CONN;
|
params.maxconn = DEFAULT_MAX_CONN;
|
||||||
params.max_orphan_time = DEFAULT_MAX_ORPHAN_TIME;
|
params.max_orphan_time = DEFAULT_MAX_ORPHAN_TIME;
|
||||||
params.binds_last = -1;
|
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__)
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
params.tcp_user_timeout_local = DEFAULT_TCP_USER_TIMEOUT_LOCAL;
|
params.tcp_user_timeout_local = DEFAULT_TCP_USER_TIMEOUT_LOCAL;
|
||||||
params.tcp_user_timeout_remote = DEFAULT_TCP_USER_TIMEOUT_REMOTE;
|
params.tcp_user_timeout_remote = DEFAULT_TCP_USER_TIMEOUT_REMOTE;
|
||||||
#endif
|
#endif
|
||||||
|
LIST_INIT(¶ms.hostlist_files);
|
||||||
|
LIST_INIT(¶ms.hostlist_exclude_files);
|
||||||
|
|
||||||
#if defined(__OpenBSD__) || defined(__APPLE__)
|
#if defined(__OpenBSD__) || defined(__APPLE__)
|
||||||
params.pf_enable = true; // OpenBSD and MacOS have no other choice
|
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;
|
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[] = {
|
const struct option long_options[] = {
|
||||||
{ "help",no_argument,0,0 },// optidx=0
|
{ "help",no_argument,0,0 },// optidx=0
|
||||||
{ "h",no_argument,0,0 },// optidx=1
|
{ "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-start",required_argument,0,0 },// optidx=53
|
||||||
{ "tamper-cutoff",required_argument,0,0 },// optidx=54
|
{ "tamper-cutoff",required_argument,0,0 },// optidx=54
|
||||||
{ "connect-bind-addr",required_argument,0,0 },// optidx=55
|
{ "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__)
|
#if defined(__FreeBSD__)
|
||||||
{ "enable-pf",no_argument,0,0 },// optidx=59
|
{ "enable-pf",no_argument,0,0 },// optidx=56
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
{ "local-tcp-user-timeout",required_argument,0,0 },// optidx=59
|
{ "local-tcp-user-timeout",required_argument,0,0 },// optidx=56
|
||||||
{ "remote-tcp-user-timeout",required_argument,0,0 },// optidx=60
|
{ "remote-tcp-user-timeout",required_argument,0,0 },// optidx=57
|
||||||
#elif defined(__linux__)
|
#elif defined(__linux__)
|
||||||
{ "local-tcp-user-timeout",required_argument,0,0 },// optidx=59
|
{ "local-tcp-user-timeout",required_argument,0,0 },// optidx=56
|
||||||
{ "remote-tcp-user-timeout",required_argument,0,0 },// optidx=60
|
{ "remote-tcp-user-timeout",required_argument,0,0 },// optidx=57
|
||||||
{ "mss",required_argument,0,0 },// optidx=61
|
{ "mss",required_argument,0,0 },// optidx=58
|
||||||
|
{ "mss-pf",required_argument,0,0 },// optidx=59
|
||||||
#ifdef SPLICE_PRESENT
|
#ifdef SPLICE_PRESENT
|
||||||
{ "nosplice",no_argument,0,0 },// optidx=62
|
{ "nosplice",no_argument,0,0 },// optidx=60
|
||||||
#endif
|
#endif
|
||||||
#endif
|
#endif
|
||||||
{ "hostlist-auto-retrans-threshold",optional_argument,0,0}, // ignored. for nfqws command line compatibility
|
{ "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;
|
break;
|
||||||
case 17: /* hostcase */
|
case 17: /* hostcase */
|
||||||
dp->hostcase = true;
|
params.hostcase = true;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 18: /* hostspell */
|
case 18: /* hostspell */
|
||||||
@ -563,28 +522,28 @@ void parse_params(int argc, char *argv[])
|
|||||||
DLOG_ERR("hostspell must be exactly 4 chars long\n");
|
DLOG_ERR("hostspell must be exactly 4 chars long\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
dp->hostcase = true;
|
params.hostcase = true;
|
||||||
memcpy(dp->hostspell, optarg, 4);
|
memcpy(params.hostspell, optarg, 4);
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 19: /* hostdot */
|
case 19: /* hostdot */
|
||||||
dp->hostdot = true;
|
params.hostdot = true;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 20: /* hostnospace */
|
case 20: /* hostnospace */
|
||||||
dp->hostnospace = true;
|
params.hostnospace = true;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 21: /* hostpad */
|
case 21: /* hostpad */
|
||||||
dp->hostpad = atoi(optarg);
|
params.hostpad = atoi(optarg);
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 22: /* domcase */
|
case 22: /* domcase */
|
||||||
dp->domcase = true;
|
params.domcase = true;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 23: /* split-http-req */
|
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");
|
DLOG_ERR("Invalid argument for split-http-req\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
@ -592,7 +551,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 24: /* split-tls */
|
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");
|
DLOG_ERR("Invalid argument for split-tls\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
@ -602,7 +561,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
case 25: /* split-pos */
|
case 25: /* split-pos */
|
||||||
i = atoi(optarg);
|
i = atoi(optarg);
|
||||||
if (i>0)
|
if (i>0)
|
||||||
dp->split_pos = i;
|
params.split_pos = i;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DLOG_ERR("Invalid argument for split-pos\n");
|
DLOG_ERR("Invalid argument for split-pos\n");
|
||||||
@ -611,13 +570,13 @@ void parse_params(int argc, char *argv[])
|
|||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 26: /* split-any-protocol */
|
case 26: /* split-any-protocol */
|
||||||
dp->split_any_protocol = true;
|
params.split_any_protocol = true;
|
||||||
break;
|
break;
|
||||||
case 27: /* disorder */
|
case 27: /* disorder */
|
||||||
if (optarg)
|
if (optarg)
|
||||||
{
|
{
|
||||||
if (!strcmp(optarg,"http")) dp->disorder_http=true;
|
if (!strcmp(optarg,"http")) params.disorder_http=true;
|
||||||
else if (!strcmp(optarg,"tls")) dp->disorder_tls=true;
|
else if (!strcmp(optarg,"tls")) params.disorder_tls=true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DLOG_ERR("Invalid argument for disorder\n");
|
DLOG_ERR("Invalid argument for disorder\n");
|
||||||
@ -625,14 +584,14 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dp->disorder = true;
|
params.disorder = true;
|
||||||
save_default_ttl();
|
save_default_ttl();
|
||||||
break;
|
break;
|
||||||
case 28: /* oob */
|
case 28: /* oob */
|
||||||
if (optarg)
|
if (optarg)
|
||||||
{
|
{
|
||||||
if (!strcmp(optarg,"http")) dp->oob_http=true;
|
if (!strcmp(optarg,"http")) params.oob_http=true;
|
||||||
else if (!strcmp(optarg,"tls")) dp->oob_tls=true;
|
else if (!strcmp(optarg,"tls")) params.oob_tls=true;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DLOG_ERR("Invalid argument for oob\n");
|
DLOG_ERR("Invalid argument for oob\n");
|
||||||
@ -640,39 +599,39 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dp->oob = true;
|
params.oob = true;
|
||||||
break;
|
break;
|
||||||
case 29: /* oob-data */
|
case 29: /* oob-data */
|
||||||
{
|
{
|
||||||
size_t l = strlen(optarg);
|
size_t l = strlen(optarg);
|
||||||
unsigned int bt;
|
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)
|
else if (l!=4 || sscanf(optarg,"0x%02X",&bt)!=1)
|
||||||
{
|
{
|
||||||
DLOG_ERR("Invalid argument for oob-data\n");
|
DLOG_ERR("Invalid argument for oob-data\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
else dp->oob_byte = (uint8_t)bt;
|
else params.oob_byte = (uint8_t)bt;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 30: /* methodspace */
|
case 30: /* methodspace */
|
||||||
dp->methodspace = true;
|
params.methodspace = true;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 31: /* methodeol */
|
case 31: /* methodeol */
|
||||||
dp->methodeol = true;
|
params.methodeol = true;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 32: /* hosttab */
|
case 32: /* hosttab */
|
||||||
dp->hosttab = true;
|
params.hosttab = true;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 33: /* unixeol */
|
case 33: /* unixeol */
|
||||||
dp->unixeol = true;
|
params.unixeol = true;
|
||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 34: /* tlsrec */
|
case 34: /* tlsrec */
|
||||||
if (!parse_tlspos(optarg, &dp->tlsrec))
|
if (!parse_tlspos(optarg, ¶ms.tlsrec))
|
||||||
{
|
{
|
||||||
DLOG_ERR("Invalid argument for tlsrec\n");
|
DLOG_ERR("Invalid argument for tlsrec\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
@ -680,8 +639,8 @@ void parse_params(int argc, char *argv[])
|
|||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 35: /* tlsrec-pos */
|
case 35: /* tlsrec-pos */
|
||||||
if ((dp->tlsrec_pos = atoi(optarg))>0)
|
if ((params.tlsrec_pos = atoi(optarg))>0)
|
||||||
dp->tlsrec = tlspos_pos;
|
params.tlsrec = tlspos_pos;
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DLOG_ERR("Invalid argument for tlsrec-pos\n");
|
DLOG_ERR("Invalid argument for tlsrec-pos\n");
|
||||||
@ -690,7 +649,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 36: /* hostlist */
|
case 36: /* hostlist */
|
||||||
if (!strlist_add(&dp->hostlist_files, optarg))
|
if (!strlist_add(¶ms.hostlist_files, optarg))
|
||||||
{
|
{
|
||||||
DLOG_ERR("strlist_add failed\n");
|
DLOG_ERR("strlist_add failed\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
@ -698,7 +657,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 37: /* hostlist-exclude */
|
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");
|
DLOG_ERR("strlist_add failed\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
@ -706,9 +665,9 @@ void parse_params(int argc, char *argv[])
|
|||||||
params.tamper = true;
|
params.tamper = true;
|
||||||
break;
|
break;
|
||||||
case 38: /* hostlist-auto */
|
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);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
@ -728,26 +687,26 @@ void parse_params(int argc, char *argv[])
|
|||||||
if (params.droproot && chown(optarg, params.uid, -1))
|
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);
|
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");
|
DLOG_ERR("strlist_add failed\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
strncpy(dp->hostlist_auto_filename, optarg, sizeof(dp->hostlist_auto_filename));
|
strncpy(params.hostlist_auto_filename, optarg, sizeof(params.hostlist_auto_filename));
|
||||||
dp->hostlist_auto_filename[sizeof(dp->hostlist_auto_filename) - 1] = '\0';
|
params.hostlist_auto_filename[sizeof(params.hostlist_auto_filename) - 1] = '\0';
|
||||||
params.tamper = true; // need to detect blocks and update autohostlist. cannot just slice.
|
params.tamper = true; // need to detect blocks and update autohostlist. cannot just slice.
|
||||||
break;
|
break;
|
||||||
case 39: /* hostlist-auto-fail-threshold */
|
case 39: /* hostlist-auto-fail-threshold */
|
||||||
dp->hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
|
params.hostlist_auto_fail_threshold = (uint8_t)atoi(optarg);
|
||||||
if (dp->hostlist_auto_fail_threshold<1 || dp->hostlist_auto_fail_threshold>20)
|
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");
|
DLOG_ERR("auto hostlist fail threshold must be within 1..20\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 40: /* hostlist-auto-fail-time */
|
case 40: /* hostlist-auto-fail-time */
|
||||||
dp->hostlist_auto_fail_time = (uint8_t)atoi(optarg);
|
params.hostlist_auto_fail_time = (uint8_t)atoi(optarg);
|
||||||
if (dp->hostlist_auto_fail_time<1)
|
if (params.hostlist_auto_fail_time<1)
|
||||||
{
|
{
|
||||||
DLOG_ERR("auto hostlist fail time is not valid\n");
|
DLOG_ERR("auto hostlist fail time is not valid\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
@ -861,28 +820,26 @@ void parse_params(int argc, char *argv[])
|
|||||||
const char *p=optarg;
|
const char *p=optarg;
|
||||||
if (*p=='n')
|
if (*p=='n')
|
||||||
{
|
{
|
||||||
dp->tamper_start_n=true;
|
params.tamper_start_n=true;
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dp->tamper_start_n=false;
|
params.tamper_start_n=false;
|
||||||
dp->tamper_start = atoi(p);
|
params.tamper_start = atoi(p);
|
||||||
}
|
}
|
||||||
params.tamper_lim = true;
|
|
||||||
break;
|
break;
|
||||||
case 54: /* tamper-cutoff */
|
case 54: /* tamper-cutoff */
|
||||||
{
|
{
|
||||||
const char *p=optarg;
|
const char *p=optarg;
|
||||||
if (*p=='n')
|
if (*p=='n')
|
||||||
{
|
{
|
||||||
dp->tamper_cutoff_n=true;
|
params.tamper_cutoff_n=true;
|
||||||
p++;
|
p++;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
dp->tamper_cutoff_n=false;
|
params.tamper_cutoff_n=false;
|
||||||
dp->tamper_cutoff = atoi(p);
|
params.tamper_cutoff = atoi(p);
|
||||||
}
|
}
|
||||||
params.tamper_lim = true;
|
|
||||||
break;
|
break;
|
||||||
case 55: /* connect-bind-addr */
|
case 55: /* connect-bind-addr */
|
||||||
{
|
{
|
||||||
@ -911,37 +868,12 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
break;
|
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__)
|
#if defined(__FreeBSD__)
|
||||||
case 59: /* enable-pf */
|
case 56: /* enable-pf */
|
||||||
params.pf_enable = true;
|
params.pf_enable = true;
|
||||||
break;
|
break;
|
||||||
#elif defined(__linux__) || defined(__APPLE__)
|
#elif defined(__linux__) || defined(__APPLE__)
|
||||||
case 59: /* local-tcp-user-timeout */
|
case 56: /* local-tcp-user-timeout */
|
||||||
params.tcp_user_timeout_local = atoi(optarg);
|
params.tcp_user_timeout_local = atoi(optarg);
|
||||||
if (params.tcp_user_timeout_local<0 || params.tcp_user_timeout_local>86400)
|
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);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 60: /* remote-tcp-user-timeout */
|
case 57: /* remote-tcp-user-timeout */
|
||||||
params.tcp_user_timeout_remote = atoi(optarg);
|
params.tcp_user_timeout_remote = atoi(optarg);
|
||||||
if (params.tcp_user_timeout_remote<0 || params.tcp_user_timeout_remote>86400)
|
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
|
#endif
|
||||||
|
|
||||||
#if defined(__linux__)
|
#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
|
// this option does not work in any BSD and MacOS. OS may accept but it changes nothing
|
||||||
dp->mss = atoi(optarg);
|
params.mss = atoi(optarg);
|
||||||
if (dp->mss<88 || dp->mss>32767)
|
if (params.mss<88 || params.mss>32767)
|
||||||
{
|
{
|
||||||
DLOG_ERR("Invalid value for MSS. Linux accepts MSS 88-32767.\n");
|
DLOG_ERR("Invalid value for MSS. Linux accepts MSS 88-32767.\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
break;
|
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
|
#ifdef SPLICE_PRESENT
|
||||||
case 62: /* nosplice */
|
case 60: /* nosplice */
|
||||||
params.nosplice = true;
|
params.nosplice = true;
|
||||||
break;
|
break;
|
||||||
#endif
|
#endif
|
||||||
@ -986,36 +925,22 @@ void parse_params(int argc, char *argv[])
|
|||||||
{
|
{
|
||||||
params.binds_last=0; // default bind to all
|
params.binds_last=0; // default bind to all
|
||||||
}
|
}
|
||||||
if (!params.resolver_threads) params.resolver_threads = 5 + params.maxconn/50;
|
if (params.skip_nodelay && (params.split_http_req || params.split_pos))
|
||||||
|
|
||||||
VPRINT("adding low-priority default empty desync profile\n");
|
|
||||||
// add default empty profile
|
|
||||||
if (!(dpl = dp_list_add(¶ms.desync_profiles)))
|
|
||||||
{
|
{
|
||||||
DLOG_ERR("desync_profile_add: out of memory\n");
|
DLOG_ERR("Cannot split with --skip-nodelay\n");
|
||||||
exit_clean(1);
|
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);
|
if (*params.hostlist_auto_filename) params.hostlist_auto_mod_time = file_mod_time(params.hostlist_auto_filename);
|
||||||
|
|
||||||
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 (!LoadIncludeHostLists())
|
if (!LoadIncludeHostLists())
|
||||||
{
|
{
|
||||||
DLOG_ERR("Include hostlist load failed\n");
|
DLOG_ERR("Include hostlist load failed\n");
|
||||||
exit_clean(1);
|
exit_clean(1);
|
||||||
}
|
}
|
||||||
|
if (*params.hostlist_auto_filename) NonEmptyHostlist(¶ms.hostlist);
|
||||||
if (!LoadExcludeHostLists())
|
if (!LoadExcludeHostLists())
|
||||||
{
|
{
|
||||||
DLOG_ERR("Exclude hostlist load failed\n");
|
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
|
// additional 1/2 for unpaired remote legs sending buffers
|
||||||
// 16 for listen_fd, epoll, hostlist, ...
|
// 16 for listen_fd, epoll, hostlist, ...
|
||||||
#ifdef SPLICE_PRESENT
|
#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
|
#else
|
||||||
fdmax = 2 * params.maxconn;
|
fdmax = 2 * params.maxconn;
|
||||||
#endif
|
#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
|
//Createas a socket and initiates the connection to the host specified by
|
||||||
//remote_addr.
|
//remote_addr.
|
||||||
//Returns -1 if something fails, >0 on success (socket fd).
|
//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;
|
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);
|
close(remote_fd);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
#ifdef __linux__
|
if (bApplyConnectionFooling && params.mss)
|
||||||
if (mss)
|
|
||||||
{
|
{
|
||||||
VPRINT("Setting MSS %d\n", mss);
|
uint16_t port = saport(remote_addr);
|
||||||
if (setsockopt(remote_fd, IPPROTO_TCP, TCP_MAXSEG, &mss, sizeof(int)) <0)
|
if (pf_in_range(port,¶ms.mss_pf))
|
||||||
{
|
{
|
||||||
DLOG_PERROR("setsockopt (TCP_MAXSEG, connect_remote)");
|
VPRINT("Setting MSS %d\n",params.mss);
|
||||||
close(remote_fd);
|
if (setsockopt(remote_fd, IPPROTO_TCP, TCP_MAXSEG, ¶ms.mss, sizeof(int)) <0)
|
||||||
return -1;
|
{
|
||||||
|
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 no bind address specified - address family will be 0 in params_connect_bindX
|
||||||
if(remote_addr->sa_family == params.connect_bind4.sin_family)
|
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;
|
tproxy_conn_t *conn;
|
||||||
|
|
||||||
//Create connection object and fill in information
|
//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");
|
DLOG_ERR("Could not allocate memory for connection\n");
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(conn, 0, sizeof(tproxy_conn_t));
|
||||||
conn->state = CONN_UNAVAILABLE;
|
conn->state = CONN_UNAVAILABLE;
|
||||||
conn->fd = fd;
|
conn->fd = fd;
|
||||||
conn->remote = remote;
|
conn->remote = remote;
|
||||||
@ -501,7 +508,7 @@ static tproxy_conn_t *new_conn(int fd, bool remote)
|
|||||||
#ifdef SPLICE_PRESENT
|
#ifdef SPLICE_PRESENT
|
||||||
// if dont tamper - both legs are spliced, create 2 pipes
|
// if dont tamper - both legs are spliced, create 2 pipes
|
||||||
// otherwise create pipe only in local leg
|
// 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");
|
DLOG_ERR("Could not create the splice pipe\n");
|
||||||
free_conn(conn);
|
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 (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");
|
DLOG_ERR("Failed to connect\n");
|
||||||
close(local_fd);
|
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)
|
if (proxy_type==CONN_TYPE_TRANSPARENT)
|
||||||
{
|
{
|
||||||
sacopy(&conn->dest, (struct sockaddr *)&orig_dst);
|
|
||||||
|
|
||||||
if(!(conn->partner = new_conn(remote_fd, true)))
|
if(!(conn->partner = new_conn(remote_fd, true)))
|
||||||
{
|
{
|
||||||
free_conn(conn);
|
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);
|
TAILQ_INSERT_HEAD(conn_list, conn->partner, conn_ptrs);
|
||||||
legs_remote++;
|
legs_remote++;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proxy_type==CONN_TYPE_TRANSPARENT)
|
|
||||||
apply_desync_profile(&conn->track, (struct sockaddr *)&conn->dest);
|
|
||||||
|
|
||||||
return conn;
|
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;
|
int remote_fd;
|
||||||
|
|
||||||
if (params.debug>=1)
|
if (params.debug>=1)
|
||||||
{
|
{
|
||||||
char ip_port[48];
|
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);
|
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");
|
VPRINT("Dropping connection to local address for security reasons\n");
|
||||||
socks_send_rep(conn->socks_ver, conn->fd, S5_REP_NOT_ALLOWED_BY_RULESET);
|
socks_send_rep(conn->socks_ver, conn->fd, S5_REP_NOT_ALLOWED_BY_RULESET);
|
||||||
return false;
|
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);
|
DLOG_ERR("socks failed to connect (1) errno=%d\n", errno);
|
||||||
socks_send_rep_errno(conn->socks_ver, conn->fd, 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;
|
ssize_t rd,wr;
|
||||||
char buf[sizeof(s5_req)]; // s5_req - the largest possible req
|
char buf[sizeof(s5_req)]; // s5_req - the largest possible req
|
||||||
|
struct sockaddr_storage ss;
|
||||||
|
|
||||||
// receive proxy control message
|
// receive proxy control message
|
||||||
rd=recv(conn->fd, buf, sizeof(buf), MSG_DONTWAIT);
|
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);
|
socks4_send_rep(conn->fd, S4_REP_FAILED);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
conn->dest.ss_family = AF_INET;
|
ss.ss_family = AF_INET;
|
||||||
((struct sockaddr_in*)&conn->dest)->sin_port = m->port;
|
((struct sockaddr_in*)&ss)->sin_port = m->port;
|
||||||
((struct sockaddr_in*)&conn->dest)->sin_addr.s_addr = m->ip;
|
((struct sockaddr_in*)&ss)->sin_addr.s_addr = m->ip;
|
||||||
return proxy_mode_connect_remote(conn, conn_list);
|
return proxy_mode_connect_remote((struct sockaddr *)&ss, conn, conn_list);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case S_WAIT_REQUEST:
|
case S_WAIT_REQUEST:
|
||||||
@ -952,16 +960,16 @@ static bool handle_proxy_mode(tproxy_conn_t *conn, struct tailhead *conn_list)
|
|||||||
switch(m->atyp)
|
switch(m->atyp)
|
||||||
{
|
{
|
||||||
case S5_ATYP_IP4:
|
case S5_ATYP_IP4:
|
||||||
conn->dest.ss_family = AF_INET;
|
ss.ss_family = AF_INET;
|
||||||
((struct sockaddr_in*)&conn->dest)->sin_port = m->d4.port;
|
((struct sockaddr_in*)&ss)->sin_port = m->d4.port;
|
||||||
((struct sockaddr_in*)&conn->dest)->sin_addr = m->d4.addr;
|
((struct sockaddr_in*)&ss)->sin_addr = m->d4.addr;
|
||||||
break;
|
break;
|
||||||
case S5_ATYP_IP6:
|
case S5_ATYP_IP6:
|
||||||
conn->dest.ss_family = AF_INET6;
|
ss.ss_family = AF_INET6;
|
||||||
((struct sockaddr_in6*)&conn->dest)->sin6_port = m->d6.port;
|
((struct sockaddr_in6*)&ss)->sin6_port = m->d6.port;
|
||||||
((struct sockaddr_in6*)&conn->dest)->sin6_addr = m->d6.addr;
|
((struct sockaddr_in6*)&ss)->sin6_addr = m->d6.addr;
|
||||||
((struct sockaddr_in6*)&conn->dest)->sin6_flowinfo = 0;
|
((struct sockaddr_in6*)&ss)->sin6_flowinfo = 0;
|
||||||
((struct sockaddr_in6*)&conn->dest)->sin6_scope_id = 0;
|
((struct sockaddr_in6*)&ss)->sin6_scope_id = 0;
|
||||||
break;
|
break;
|
||||||
case S5_ATYP_DOM:
|
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 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;
|
break;
|
||||||
case S_WAIT_RESOLVE:
|
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);
|
DBGPRINT("resolve_complete put hostname : %s\n", ri->dom);
|
||||||
conn->track.hostname = strdup(ri->dom);
|
conn->track.hostname = strdup(ri->dom);
|
||||||
}
|
}
|
||||||
sacopy(&conn->dest, (struct sockaddr *)&ri->ss);
|
return proxy_mode_connect_remote((struct sockaddr *)&ri->ss,conn,conn_list);
|
||||||
return proxy_mode_connect_remote(conn,conn_list);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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)
|
static bool in_tamper_out_range(tproxy_conn_t *conn)
|
||||||
{
|
{
|
||||||
if (!conn->track.dp) return true;
|
return (params.tamper_start_n ? (conn->tnrd+1) : conn->trd) >= params.tamper_start &&
|
||||||
bool in_range = \
|
(!params.tamper_cutoff || (params.tamper_cutoff_n ? (conn->tnrd+1) : conn->trd) < params.tamper_cutoff);
|
||||||
((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;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
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->remote)
|
||||||
{
|
{
|
||||||
if (conn_partner_alive(conn) && !conn->partner->track.bTamperInCutoff)
|
if (conn_partner_alive(conn) && !conn->partner->track.bTamperInCutoff)
|
||||||
|
{
|
||||||
tamper_in(&conn->partner->track,segment,segment_buffer_size,segment_size);
|
tamper_in(&conn->partner->track,segment,segment_buffer_size,segment_size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (in_tamper_out_range(conn))
|
bool in_range = in_tamper_out_range(conn);
|
||||||
tamper_out(&conn->track,(struct sockaddr*)&conn->dest,segment,segment_buffer_size,segment_size,split_pos,split_flags);
|
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
|
// 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;
|
ssize_t wr;
|
||||||
if (oob)
|
if (oob)
|
||||||
{
|
{
|
||||||
VPRINT("Sending OOB byte %02X\n", oob_byte);
|
VPRINT("Sending OOB byte %02X\n", params.oob_byte);
|
||||||
uint8_t oob_save;
|
uint8_t oob_save;
|
||||||
oob_save = buf[len];
|
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);
|
wr = send_or_buffer(sb, fd, buf, len+1, MSG_OOB, ttl);
|
||||||
buf[len] = oob_save;
|
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" : "");
|
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);
|
DBGPRINT("send_or_buffer(1) fd=%d wr=%zd err=%d\n",conn->partner->fd,wr,errno);
|
||||||
if (wr >= 0)
|
if (wr >= 0)
|
||||||
{
|
{
|
||||||
|
@ -54,7 +54,6 @@ struct tproxy_conn
|
|||||||
int splice_pipe[2];
|
int splice_pipe[2];
|
||||||
conn_state_t state;
|
conn_state_t state;
|
||||||
conn_type_t conn_type;
|
conn_type_t conn_type;
|
||||||
struct sockaddr_storage dest;
|
|
||||||
|
|
||||||
struct tproxy_conn *partner; // other leg
|
struct tproxy_conn *partner; // other leg
|
||||||
time_t orphan_since;
|
time_t orphan_since;
|
||||||
|
Loading…
Reference in New Issue
Block a user