mirror of
https://github.com/bol-van/zapret.git
synced 2024-11-30 05:50:53 +03:00
Compare commits
No commits in common. "f0cc49c7e3cacb552725d9026f8bb4e0cc11483a" and "fc2d511d78fc929c2fa58074a781349ac079b749" have entirely different histories.
f0cc49c7e3
...
fc2d511d78
@ -812,7 +812,7 @@ tpws - это transparent proxy.
|
|||||||
--skip-nodelay ; не устанавливать в исходящих соединения TCP_NODELAY. несовместимо со split.
|
--skip-nodelay ; не устанавливать в исходящих соединения TCP_NODELAY. несовместимо со split.
|
||||||
--local-tcp-user-timeout=<seconds> ; таймаут соединений client-proxy (по умолчанию : 10 сек, 0 = оставить системное значение)
|
--local-tcp-user-timeout=<seconds> ; таймаут соединений client-proxy (по умолчанию : 10 сек, 0 = оставить системное значение)
|
||||||
--remote-tcp-user-timeout=<seconds> ; таймаут соединений proxy-target (по умолчанию : 20 сек, 0 = оставить системное значение)
|
--remote-tcp-user-timeout=<seconds> ; таймаут соединений proxy-target (по умолчанию : 20 сек, 0 = оставить системное значение)
|
||||||
--fix-seg=<int> ; исправлять неудачи tcp сегментации ценой задержек для всех клиентов и замедления. ждать до N мс. по умолчанию 30 мс.
|
--fix-seg ; исправлять неудачи tcp сегментации ценой задержек для всех клиентов и замедления
|
||||||
|
|
||||||
--split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации
|
--split-pos=N|-N|marker+N|marker-N ; список через запятую маркеров для tcp сегментации
|
||||||
--split-any-protocol ; применять сегментацию к любым пакетам. по умолчанию - только к известным протоколам (http, TLS)
|
--split-any-protocol ; применять сегментацию к любым пакетам. по умолчанию - только к известным протоколам (http, TLS)
|
||||||
@ -881,16 +881,12 @@ tpws, как и nfqws, поддерживает множественную се
|
|||||||
Как показывается практика, проблемы могут начаться , если количество сплит позиций превышает 8.
|
Как показывается практика, проблемы могут начаться , если количество сплит позиций превышает 8.
|
||||||
При неудаче сегментации будет выводиться сообщение `WARNING ! segmentation failed`.
|
При неудаче сегментации будет выводиться сообщение `WARNING ! segmentation failed`.
|
||||||
Если вы его видите, это повод снизить количество сплит позиций.
|
Если вы его видите, это повод снизить количество сплит позиций.
|
||||||
Если это не вариант, для ядер Linux >=4.6 есть параметр `--fix-seg`. Он позволяет подождать завершение отсылки перед отправкой следующей части.
|
Если это не вариант, есть параметр `--fix-seg`. Он позволяет подождать завершение отсылки перед отправкой следующей части.
|
||||||
Но этот вариант ломает модель асинхронной обработки событий. Пока идет ожидание, все остальные соединения не обрабатываются
|
Но этот вариант ломает модель асинхронной обработки событий. Пока идет ожидание, все остальные соединения не обрабатываются
|
||||||
и кратковременно подвисают. На практике это может быть совсем небольшое ожидание - менее 10 мс.
|
и кратковременно подвисают. На практике это может быть совсем небольшое ожидание - менее 10 мс.
|
||||||
И производится оно только , если происходит split, и в ожидании есть реальная необходимость.
|
И производится оно только , если происходит split, и в ожидании есть реальная необходимость.
|
||||||
В высоконагруженных системах данный вариант не рекомендуется. Но для домашнего использования может подойти, и вы эти задержки даже не заметите.
|
В высоконагруженных системах данный вариант не рекомендуется. Но для домашнего использования может подойти, и вы эти задержки даже не заметите.
|
||||||
|
|
||||||
Если вы пытаетесь сплитнуть массивную передачу с `--split-any-protocol`, когда информация поступает быстрее отсылки,
|
|
||||||
то без `--fix-seg` ошибки сегментации будут сыпаться сплошным потоком.
|
|
||||||
Работа по массивному потоку без ограничителей `--tamper-start` и `--tamper-cutoff` обычно лишена смысла.
|
|
||||||
|
|
||||||
tpws работает на уровне сокетов, поэтому длинный запрос, не вмещающийся в 1 пакет (TLS с kyber), он получает целым блоком.
|
tpws работает на уровне сокетов, поэтому длинный запрос, не вмещающийся в 1 пакет (TLS с kyber), он получает целым блоком.
|
||||||
На каждую сплит часть он делает отдельный вызов `send()`. Но ОС не сможет отослать данные в одном пакете, если размер превысит MTU.
|
На каждую сплит часть он делает отдельный вызов `send()`. Но ОС не сможет отослать данные в одном пакете, если размер превысит MTU.
|
||||||
В случае слишком большого сегмента ОС дополнительно его порежет на более мелкие. Результат должен быть аналогичен nfqws.
|
В случае слишком большого сегмента ОС дополнительно его порежет на более мелкие. Результат должен быть аналогичен nfqws.
|
||||||
|
@ -10,7 +10,6 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <libgen.h>
|
#include <libgen.h>
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
#include <linux/tcp.h>
|
#include <linux/tcp.h>
|
||||||
@ -478,24 +477,6 @@ void msleep(unsigned int ms)
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
bool socket_supports_notsent()
|
|
||||||
{
|
|
||||||
int sfd;
|
|
||||||
struct tcp_info tcpi;
|
|
||||||
|
|
||||||
sfd = socket(AF_INET,SOCK_STREAM,0);
|
|
||||||
if (sfd<0) return false;
|
|
||||||
|
|
||||||
socklen_t ts = sizeof(tcpi);
|
|
||||||
if (getsockopt(sfd, IPPROTO_TCP, TCP_INFO, (char *)&tcpi, &ts) < 0)
|
|
||||||
{
|
|
||||||
close(sfd);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
close(sfd);
|
|
||||||
|
|
||||||
return ts>=((char *)&tcpi.tcpi_notsent_bytes - (char *)&tcpi.tcpi_state + sizeof(tcpi.tcpi_notsent_bytes));
|
|
||||||
}
|
|
||||||
bool socket_has_notsent(int sfd)
|
bool socket_has_notsent(int sfd)
|
||||||
{
|
{
|
||||||
struct tcp_info tcpi;
|
struct tcp_info tcpi;
|
||||||
@ -503,11 +484,10 @@ bool socket_has_notsent(int sfd)
|
|||||||
|
|
||||||
if (getsockopt(sfd, IPPROTO_TCP, TCP_INFO, (char *)&tcpi, &ts) < 0)
|
if (getsockopt(sfd, IPPROTO_TCP, TCP_INFO, (char *)&tcpi, &ts) < 0)
|
||||||
return false;
|
return false;
|
||||||
if (tcpi.tcpi_state != 1) // TCP_ESTABLISHED
|
if (tcpi.tcpi_state != 1)
|
||||||
return false;
|
return false;
|
||||||
size_t s = (char *)&tcpi.tcpi_notsent_bytes - (char *)&tcpi + sizeof(tcpi.tcpi_notsent_bytes);
|
size_t s = (char *)&tcpi.tcpi_notsent_bytes - (char *)&tcpi.tcpi_state;
|
||||||
if (ts < s)
|
if (ts < s)
|
||||||
// old structure version
|
|
||||||
return false;
|
return false;
|
||||||
return !!tcpi.tcpi_notsent_bytes;
|
return !!tcpi.tcpi_notsent_bytes;
|
||||||
}
|
}
|
||||||
|
@ -120,7 +120,6 @@ static inline const struct in6_addr *mask_from_preflen6(uint8_t preflen)
|
|||||||
|
|
||||||
void msleep(unsigned int ms);
|
void msleep(unsigned int ms);
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
bool socket_supports_notsent();
|
|
||||||
bool socket_has_notsent(int sfd);
|
bool socket_has_notsent(int sfd);
|
||||||
bool socket_wait_notsent(int sfd, unsigned int delay_ms, unsigned int *wasted_ms);
|
bool socket_wait_notsent(int sfd, unsigned int delay_ms, unsigned int *wasted_ms);
|
||||||
#endif
|
#endif
|
||||||
|
@ -18,8 +18,6 @@
|
|||||||
#define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3
|
#define HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT 3
|
||||||
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
|
#define HOSTLIST_AUTO_FAIL_TIME_DEFAULT 60
|
||||||
|
|
||||||
#define FIX_SEG_DEFAULT_MAX_WAIT 30
|
|
||||||
|
|
||||||
enum bindll { unwanted=0, no, prefer, force };
|
enum bindll { unwanted=0, no, prefer, force };
|
||||||
|
|
||||||
#define MAX_BINDS 32
|
#define MAX_BINDS 32
|
||||||
@ -104,14 +102,13 @@ struct params_s
|
|||||||
char connect_bind6_ifname[IF_NAMESIZE];
|
char connect_bind6_ifname[IF_NAMESIZE];
|
||||||
|
|
||||||
uint8_t proxy_type;
|
uint8_t proxy_type;
|
||||||
unsigned int fix_seg;
|
|
||||||
bool fix_seg_avail;
|
|
||||||
bool no_resolve;
|
bool no_resolve;
|
||||||
bool skip_nodelay;
|
bool skip_nodelay;
|
||||||
|
bool fix_seg;
|
||||||
bool droproot;
|
bool droproot;
|
||||||
bool daemon;
|
|
||||||
uid_t uid;
|
uid_t uid;
|
||||||
gid_t gid;
|
gid_t gid;
|
||||||
|
bool daemon;
|
||||||
char pidfile[256];
|
char pidfile[256];
|
||||||
int maxconn,resolver_threads,maxfiles,max_orphan_time;
|
int maxconn,resolver_threads,maxfiles,max_orphan_time;
|
||||||
int local_rcvbuf,local_sndbuf,remote_rcvbuf,remote_sndbuf;
|
int local_rcvbuf,local_sndbuf,remote_rcvbuf,remote_sndbuf;
|
||||||
|
29
tpws/tpws.c
29
tpws/tpws.c
@ -171,7 +171,7 @@ static void exithelp(void)
|
|||||||
" --enable-pf\t\t\t\t; enable PF redirector support. required in FreeBSD when used with PF firewall.\n"
|
" --enable-pf\t\t\t\t; enable PF redirector support. required in FreeBSD when used with PF firewall.\n"
|
||||||
#endif
|
#endif
|
||||||
#if defined(__linux__)
|
#if defined(__linux__)
|
||||||
" --fix-seg=<int>\t\t\t; fix segmentation failures at the cost of possible slowdown. wait up to N msec (default %u)\n"
|
" --fix-seg\t\t\t\t; fix segmentation failures at the cost of possible slowdown\n"
|
||||||
#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"
|
||||||
@ -192,7 +192,7 @@ static void exithelp(void)
|
|||||||
"\nTAMPER:\n"
|
"\nTAMPER:\n"
|
||||||
" --split-pos=N|-N|marker+N|marker-N\t; comma separated list of split positions\n"
|
" --split-pos=N|-N|marker+N|marker-N\t; comma separated list of split positions\n"
|
||||||
"\t\t\t\t\t; markers: method,host,endhost,sld,endsld,midsld,sniext\n"
|
"\t\t\t\t\t; markers: method,host,endhost,sld,endsld,midsld,sniext\n"
|
||||||
" --split-any-protocol\t\t\t; split not only http and TLS\n"
|
" --split-any-protocol\t\t\t; split not only http and https\n"
|
||||||
#if defined(BSD) && !defined(__APPLE__)
|
#if defined(BSD) && !defined(__APPLE__)
|
||||||
" --disorder[=http|tls]\t\t\t; when splitting simulate sending second fragment first (BSD sends entire message instead of first fragment, this is not good)\n"
|
" --disorder[=http|tls]\t\t\t; when splitting simulate sending second fragment first (BSD sends entire message instead of first fragment, this is not good)\n"
|
||||||
#else
|
#else
|
||||||
@ -218,9 +218,6 @@ static void exithelp(void)
|
|||||||
" --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",
|
||||||
#if defined(__linux__) || defined(__APPLE__)
|
#if defined(__linux__) || defined(__APPLE__)
|
||||||
DEFAULT_TCP_USER_TIMEOUT_LOCAL,DEFAULT_TCP_USER_TIMEOUT_REMOTE,
|
DEFAULT_TCP_USER_TIMEOUT_LOCAL,DEFAULT_TCP_USER_TIMEOUT_REMOTE,
|
||||||
#endif
|
|
||||||
#ifdef __linux__
|
|
||||||
FIX_SEG_DEFAULT_MAX_WAIT,
|
|
||||||
#endif
|
#endif
|
||||||
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT
|
HOSTLIST_AUTO_FAIL_THRESHOLD_DEFAULT, HOSTLIST_AUTO_FAIL_TIME_DEFAULT
|
||||||
);
|
);
|
||||||
@ -538,8 +535,6 @@ void parse_params(int argc, char *argv[])
|
|||||||
params.pf_enable = true; // OpenBSD and MacOS have no other choice
|
params.pf_enable = true; // OpenBSD and MacOS have no other choice
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
params.fix_seg_avail = socket_supports_notsent();
|
|
||||||
|
|
||||||
LIST_INIT(¶ms.hostlists);
|
LIST_INIT(¶ms.hostlists);
|
||||||
LIST_INIT(¶ms.ipsets);
|
LIST_INIT(¶ms.ipsets);
|
||||||
|
|
||||||
@ -643,7 +638,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=62
|
{ "local-tcp-user-timeout",required_argument,0,0 }, // optidx=62
|
||||||
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=63
|
{ "remote-tcp-user-timeout",required_argument,0,0 }, // optidx=63
|
||||||
{ "mss",required_argument,0,0 }, // optidx=64
|
{ "mss",required_argument,0,0 }, // optidx=64
|
||||||
{ "fix-seg",optional_argument,0,0 }, // optidx=65
|
{ "fix-seg",no_argument,0,0 }, // optidx=65
|
||||||
#ifdef SPLICE_PRESENT
|
#ifdef SPLICE_PRESENT
|
||||||
{ "nosplice",no_argument,0,0 }, // optidx=66
|
{ "nosplice",no_argument,0,0 }, // optidx=66
|
||||||
#endif
|
#endif
|
||||||
@ -1238,23 +1233,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 65: /* fix-seg */
|
case 65: /* fix-seg */
|
||||||
if (!params.fix_seg_avail)
|
params.fix_seg = true;
|
||||||
{
|
|
||||||
DLOG_ERR("--fix-seg is supported since kernel 4.6\n");
|
|
||||||
exit_clean(1);
|
|
||||||
}
|
|
||||||
if (optarg)
|
|
||||||
{
|
|
||||||
i = atoi(optarg);
|
|
||||||
if (i < 0 || i > 1000)
|
|
||||||
{
|
|
||||||
DLOG_ERR("fix_seg value must be within 0..1000\n");
|
|
||||||
exit_clean(1);
|
|
||||||
}
|
|
||||||
params.fix_seg = i;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
params.fix_seg = FIX_SEG_DEFAULT_MAX_WAIT;
|
|
||||||
break;
|
break;
|
||||||
#ifdef SPLICE_PRESENT
|
#ifdef SPLICE_PRESENT
|
||||||
case 66: /* nosplice */
|
case 66: /* nosplice */
|
||||||
|
@ -1118,24 +1118,8 @@ static ssize_t send_oob(int fd, uint8_t *buf, size_t len, int ttl, bool oob, uin
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static unsigned int segfail_count=0;
|
|
||||||
static time_t segfail_report_time=0;
|
|
||||||
static void report_segfail(void)
|
|
||||||
{
|
|
||||||
time_t now = time(NULL);
|
|
||||||
segfail_count++;
|
|
||||||
if (now==segfail_report_time)
|
|
||||||
VPRINT("WARNING ! segmentation failed. total fails : %u\n", segfail_count);
|
|
||||||
else
|
|
||||||
{
|
|
||||||
DLOG_ERR("WARNING ! segmentation failed. total fails : %u\n", segfail_count);
|
|
||||||
segfail_report_time = now;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define RD_BLOCK_SIZE 65536
|
#define RD_BLOCK_SIZE 65536
|
||||||
#define MAX_WASTE (1024*1024)
|
#define MAX_WASTE (1024*1024)
|
||||||
|
|
||||||
static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32_t evt)
|
static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32_t evt)
|
||||||
{
|
{
|
||||||
int numbytes;
|
int numbytes;
|
||||||
@ -1247,25 +1231,6 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32
|
|||||||
bApplyDisorder = !(i & 1) && i<multisplit_count && (split_flags & SPLIT_FLAG_DISORDER);
|
bApplyDisorder = !(i & 1) && i<multisplit_count && (split_flags & SPLIT_FLAG_DISORDER);
|
||||||
bApplyOOB = i==0 && (split_flags & SPLIT_FLAG_OOB);
|
bApplyOOB = i==0 && (split_flags & SPLIT_FLAG_OOB);
|
||||||
len = to-from;
|
len = to-from;
|
||||||
#ifdef __linux__
|
|
||||||
if (params.fix_seg_avail)
|
|
||||||
{
|
|
||||||
if (params.fix_seg)
|
|
||||||
{
|
|
||||||
unsigned int wasted;
|
|
||||||
bool bWaitOK = socket_wait_notsent(conn->partner->fd, params.fix_seg, &wasted);
|
|
||||||
if (wasted)
|
|
||||||
VPRINT("WARNING ! wasted %u ms to fix segmenation\n", wasted);
|
|
||||||
if (!bWaitOK)
|
|
||||||
report_segfail();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (socket_has_notsent(conn->partner->fd))
|
|
||||||
report_segfail();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
VPRINT("Sending multisplit part %d %zd-%zd (len %zd)%s%s : ", i+1, from, to, len, bApplyDisorder ? " with disorder" : "", bApplyOOB ? " with OOB" : "");
|
VPRINT("Sending multisplit part %d %zd-%zd (len %zd)%s%s : ", i+1, from, to, len, bApplyDisorder ? " with disorder" : "", bApplyOOB ? " with OOB" : "");
|
||||||
packet_debug(buf+from,len);
|
packet_debug(buf+from,len);
|
||||||
wr = send_oob(conn->partner->fd, buf+from, len, bApplyDisorder, bApplyOOB, conn->track.dp ? conn->track.dp->oob_byte : 0);
|
wr = send_oob(conn->partner->fd, buf+from, len, bApplyDisorder, bApplyOOB, conn->track.dp ? conn->track.dp->oob_byte : 0);
|
||||||
@ -1279,6 +1244,21 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32
|
|||||||
if (wr>0) conn->partner->twr += wr;
|
if (wr>0) conn->partner->twr += wr;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
#ifdef __linux__
|
||||||
|
if (params.fix_seg)
|
||||||
|
{
|
||||||
|
unsigned int wasted;
|
||||||
|
if (!socket_wait_notsent(conn->partner->fd, 20, &wasted))
|
||||||
|
DLOG_ERR("WARNING ! segmentation failed\n");
|
||||||
|
if (wasted)
|
||||||
|
VPRINT("WARNING ! wasted %u ms to fix segmenation\n", wasted);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (socket_has_notsent(conn->partner->fd))
|
||||||
|
DLOG_ERR("WARNING ! segmentation failed\n");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
from = to;
|
from = to;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user