mirror of
https://github.com/bol-van/zapret.git
synced 2025-05-24 22:32:58 +03:00
tpws --disorder
This commit is contained in:
@@ -172,11 +172,27 @@ bool is_private6(const struct sockaddr_in6* a)
|
||||
|
||||
|
||||
|
||||
int set_keepalive(int fd)
|
||||
bool set_keepalive(int fd)
|
||||
{
|
||||
int yes=1;
|
||||
return setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(int))!=-1;
|
||||
}
|
||||
bool set_ttl(int fd, int ttl)
|
||||
{
|
||||
return setsockopt(fd, IPPROTO_IP, IP_TTL, &ttl, sizeof(ttl))!=-1;
|
||||
}
|
||||
bool set_hl(int fd, int hl)
|
||||
{
|
||||
return setsockopt(fd, IPPROTO_IPV6, IPV6_UNICAST_HOPS, &hl, sizeof(hl))!=-1;
|
||||
}
|
||||
bool set_ttl_hl(int fd, int ttl)
|
||||
{
|
||||
bool b1,b2;
|
||||
// try to set both but one may fail if family is wrong
|
||||
b1=set_ttl(fd, ttl);
|
||||
b2=set_hl(fd, ttl);
|
||||
return b1 || b2;
|
||||
}
|
||||
int get_so_error(int fd)
|
||||
{
|
||||
// getsockopt(SO_ERROR) clears error
|
||||
|
@@ -25,7 +25,10 @@ bool is_localnet(const struct sockaddr *a);
|
||||
bool is_linklocal(const struct sockaddr_in6* a);
|
||||
bool is_private6(const struct sockaddr_in6* a);
|
||||
|
||||
int set_keepalive(int fd);
|
||||
bool set_keepalive(int fd);
|
||||
bool set_ttl(int fd, int ttl);
|
||||
bool set_hl(int fd, int hl);
|
||||
bool set_ttl_hl(int fd, int ttl);
|
||||
int get_so_error(int fd);
|
||||
|
||||
static inline uint16_t pntoh16(const uint8_t *p) {
|
||||
|
@@ -43,6 +43,8 @@ struct params_s
|
||||
enum splithttpreq split_http_req;
|
||||
bool split_any_protocol;
|
||||
int split_pos;
|
||||
bool disorder;
|
||||
int ttl_default;
|
||||
|
||||
char pidfile[256];
|
||||
|
||||
|
102
tpws/tpws.c
102
tpws/tpws.c
@@ -103,6 +103,18 @@ static bool is_interface_online(const char *ifname)
|
||||
close(sock);
|
||||
return !!(ifr.ifr_flags & IFF_UP);
|
||||
}
|
||||
static int get_default_ttl()
|
||||
{
|
||||
int sock,ttl=0;
|
||||
socklen_t optlen=sizeof(ttl);
|
||||
|
||||
if ((sock=socket(PF_INET, SOCK_DGRAM, IPPROTO_IP))!=-1)
|
||||
{
|
||||
getsockopt(sock, IPPROTO_IP, IP_TTL, &ttl, &optlen);
|
||||
close(sock);
|
||||
}
|
||||
return ttl;
|
||||
}
|
||||
|
||||
|
||||
static void exithelp()
|
||||
@@ -147,6 +159,11 @@ static void exithelp()
|
||||
" --split-http-req=method|host\t; split at specified logical part of plain http request\n"
|
||||
" --split-pos=<numeric_offset>\t; split at specified pos. split-http-req takes precedence for http.\n"
|
||||
" --split-any-protocol\t\t; split not only http and https\n"
|
||||
#if defined(BSD) && !defined(__APPLE__)
|
||||
" --disorder\t\t\t; when splitting simulate sending second fragment first (BSD sends entire message instead of first fragment, this is not good)\n"
|
||||
#else
|
||||
" --disorder\t\t\t; when splitting simulate sending second fragment first\n"
|
||||
#endif
|
||||
" --hostcase\t\t\t; change Host: => host:\n"
|
||||
" --hostspell\t\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n"
|
||||
" --hostdot\t\t\t; add \".\" after Host: name\n"
|
||||
@@ -204,6 +221,19 @@ static void checkbind_clean()
|
||||
}
|
||||
|
||||
|
||||
void save_default_ttl()
|
||||
{
|
||||
if (!params.ttl_default)
|
||||
{
|
||||
params.ttl_default = get_default_ttl();
|
||||
if (!params.ttl_default)
|
||||
{
|
||||
fprintf(stderr, "could not get default ttl\n");
|
||||
exit_clean(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void parse_params(int argc, char *argv[])
|
||||
{
|
||||
int option_index = 0;
|
||||
@@ -253,23 +283,24 @@ void parse_params(int argc, char *argv[])
|
||||
{ "split-http-req",required_argument,0,0 },// optidx=23
|
||||
{ "split-pos",required_argument,0,0 },// optidx=24
|
||||
{ "split-any-protocol",optional_argument,0,0},// optidx=25
|
||||
{ "methodspace",no_argument,0,0 },// optidx=26
|
||||
{ "methodeol",no_argument,0,0 },// optidx=27
|
||||
{ "hosttab",no_argument,0,0 },// optidx=28
|
||||
{ "unixeol",no_argument,0,0 },// optidx=29
|
||||
{ "hostlist",required_argument,0,0 },// optidx=30
|
||||
{ "hostlist-exclude",required_argument,0,0 },// optidx=31
|
||||
{ "pidfile",required_argument,0,0 },// optidx=32
|
||||
{ "debug",optional_argument,0,0 },// optidx=33
|
||||
{ "local-rcvbuf",required_argument,0,0 },// optidx=34
|
||||
{ "local-sndbuf",required_argument,0,0 },// optidx=35
|
||||
{ "remote-rcvbuf",required_argument,0,0 },// optidx=36
|
||||
{ "remote-sndbuf",required_argument,0,0 },// optidx=37
|
||||
{ "socks",no_argument,0,0 },// optidx=38
|
||||
{ "no-resolve",no_argument,0,0 },// optidx=39
|
||||
{ "skip-nodelay",no_argument,0,0 },// optidx=40
|
||||
{ "disorder",no_argument,0,0 },// optidx=26
|
||||
{ "methodspace",no_argument,0,0 },// optidx=27
|
||||
{ "methodeol",no_argument,0,0 },// optidx=28
|
||||
{ "hosttab",no_argument,0,0 },// optidx=29
|
||||
{ "unixeol",no_argument,0,0 },// optidx=30
|
||||
{ "hostlist",required_argument,0,0 },// optidx=31
|
||||
{ "hostlist-exclude",required_argument,0,0 },// optidx=32
|
||||
{ "pidfile",required_argument,0,0 },// optidx=33
|
||||
{ "debug",optional_argument,0,0 },// optidx=34
|
||||
{ "local-rcvbuf",required_argument,0,0 },// optidx=35
|
||||
{ "local-sndbuf",required_argument,0,0 },// optidx=36
|
||||
{ "remote-rcvbuf",required_argument,0,0 },// optidx=37
|
||||
{ "remote-sndbuf",required_argument,0,0 },// optidx=38
|
||||
{ "socks",no_argument,0,0 },// optidx=39
|
||||
{ "no-resolve",no_argument,0,0 },// optidx=40
|
||||
{ "skip-nodelay",no_argument,0,0 },// optidx=41
|
||||
#if defined(BSD) && !defined(__OpenBSD__) && !defined(__APPLE__)
|
||||
{ "enable-pf",no_argument,0,0 },// optidx=41
|
||||
{ "enable-pf",no_argument,0,0 },// optidx=42
|
||||
#endif
|
||||
{ NULL,0,NULL,0 }
|
||||
};
|
||||
@@ -453,23 +484,27 @@ void parse_params(int argc, char *argv[])
|
||||
case 25: /* split-any-protocol */
|
||||
params.split_any_protocol = true;
|
||||
break;
|
||||
case 26: /* methodspace */
|
||||
case 26: /* disorder */
|
||||
params.disorder = true;
|
||||
save_default_ttl();
|
||||
break;
|
||||
case 27: /* methodspace */
|
||||
params.methodspace = true;
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 27: /* methodeol */
|
||||
case 28: /* methodeol */
|
||||
params.methodeol = true;
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 28: /* hosttab */
|
||||
case 29: /* hosttab */
|
||||
params.hosttab = true;
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 29: /* unixeol */
|
||||
case 30: /* unixeol */
|
||||
params.unixeol = true;
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 30: /* hostlist */
|
||||
case 31: /* hostlist */
|
||||
if (!strlist_add(¶ms.hostlist_files, optarg))
|
||||
{
|
||||
fprintf(stderr, "strlist_add failed\n");
|
||||
@@ -477,7 +512,7 @@ void parse_params(int argc, char *argv[])
|
||||
}
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 31: /* hostlist-exclude */
|
||||
case 32: /* hostlist-exclude */
|
||||
if (!strlist_add(¶ms.hostlist_exclude_files, optarg))
|
||||
{
|
||||
fprintf(stderr, "strlist_add failed\n");
|
||||
@@ -485,36 +520,36 @@ void parse_params(int argc, char *argv[])
|
||||
}
|
||||
params.tamper = true;
|
||||
break;
|
||||
case 32: /* pidfile */
|
||||
case 33: /* pidfile */
|
||||
strncpy(params.pidfile,optarg,sizeof(params.pidfile));
|
||||
params.pidfile[sizeof(params.pidfile)-1]='\0';
|
||||
break;
|
||||
case 33:
|
||||
case 34:
|
||||
params.debug = optarg ? atoi(optarg) : 1;
|
||||
break;
|
||||
case 34: /* local-rcvbuf */
|
||||
case 35: /* local-rcvbuf */
|
||||
params.local_rcvbuf = atoi(optarg)/2;
|
||||
break;
|
||||
case 35: /* local-sndbuf */
|
||||
case 36: /* local-sndbuf */
|
||||
params.local_sndbuf = atoi(optarg)/2;
|
||||
break;
|
||||
case 36: /* remote-rcvbuf */
|
||||
case 37: /* remote-rcvbuf */
|
||||
params.remote_rcvbuf = atoi(optarg)/2;
|
||||
break;
|
||||
case 37: /* remote-sndbuf */
|
||||
case 38: /* remote-sndbuf */
|
||||
params.remote_sndbuf = atoi(optarg)/2;
|
||||
break;
|
||||
case 38: /* socks */
|
||||
case 39: /* socks */
|
||||
params.proxy_type = CONN_TYPE_SOCKS;
|
||||
break;
|
||||
case 39: /* no-resolve */
|
||||
case 40: /* no-resolve */
|
||||
params.no_resolve = true;
|
||||
break;
|
||||
case 40: /* skip-nodelay */
|
||||
case 41: /* skip-nodelay */
|
||||
params.skip_nodelay = true;
|
||||
break;
|
||||
#if defined(BSD) && !defined(__OpenBSD__) && !defined(__APPLE__)
|
||||
case 41: /* enable-pf */
|
||||
case 42: /* enable-pf */
|
||||
params.pf_enable = true;
|
||||
break;
|
||||
#endif
|
||||
@@ -849,7 +884,7 @@ int main(int argc, char *argv[])
|
||||
fprintf(stderr,"could not initialize redirector !!!\n");
|
||||
goto exiterr;
|
||||
}
|
||||
|
||||
|
||||
for(i=0;i<=params.binds_last;i++)
|
||||
{
|
||||
if (params.debug)
|
||||
@@ -862,6 +897,7 @@ int main(int argc, char *argv[])
|
||||
perror("socket");
|
||||
goto exiterr;
|
||||
}
|
||||
|
||||
#ifndef __OpenBSD__
|
||||
// in OpenBSD always IPV6_ONLY for wildcard sockets
|
||||
if ((list[i].salisten.ss_family == AF_INET6) && setsockopt(listen_fd[i], IPPROTO_IPV6, IPV6_V6ONLY, &list[i].ipv6_only, sizeof(int)) == -1)
|
||||
|
@@ -111,8 +111,29 @@ static bool proxy_remote_conn_ack(tproxy_conn_t *conn, int sock_err)
|
||||
}
|
||||
|
||||
|
||||
ssize_t send_with_ttl(int fd, const void *buf, size_t len, int flags, int ttl)
|
||||
{
|
||||
ssize_t wr;
|
||||
|
||||
static bool send_buffer_create(send_buffer_t *sb, char *data, size_t len)
|
||||
if (ttl)
|
||||
{
|
||||
DBGPRINT("send_with_ttl %d fd=%d",ttl,fd);
|
||||
if (!set_ttl_hl(fd, ttl))
|
||||
fprintf(stderr,"could not set ttl %d to fd=%d\n",ttl,fd);
|
||||
}
|
||||
wr = send(fd, buf, len, flags);
|
||||
if (ttl)
|
||||
{
|
||||
int e=errno;
|
||||
if (!set_ttl_hl(fd, params.ttl_default))
|
||||
fprintf(stderr,"could not set ttl %d to fd=%d\n",params.ttl_default,fd);
|
||||
errno=e;
|
||||
}
|
||||
return wr;
|
||||
}
|
||||
|
||||
|
||||
static bool send_buffer_create(send_buffer_t *sb, char *data, size_t len, int ttl)
|
||||
{
|
||||
if (sb->data)
|
||||
{
|
||||
@@ -128,6 +149,7 @@ static bool send_buffer_create(send_buffer_t *sb, char *data, size_t len)
|
||||
if (data) memcpy(sb->data,data,len);
|
||||
sb->len = len;
|
||||
sb->pos = 0;
|
||||
sb->ttl = ttl;
|
||||
return true;
|
||||
}
|
||||
static void send_buffer_free(send_buffer_t *sb)
|
||||
@@ -162,7 +184,7 @@ static ssize_t send_buffer_send(send_buffer_t *sb, int fd)
|
||||
{
|
||||
ssize_t wr;
|
||||
|
||||
wr = send(fd, sb->data + sb->pos, sb->len - sb->pos, 0);
|
||||
wr = send_with_ttl(fd, sb->data + sb->pos, sb->len - sb->pos, 0, sb->ttl);
|
||||
DBGPRINT("send_buffer_send len=%zu pos=%zu wr=%zd err=%d",sb->len,sb->pos,wr,errno)
|
||||
if (wr>0)
|
||||
{
|
||||
@@ -236,16 +258,16 @@ static bool conn_has_unsent_pair(tproxy_conn_t *conn)
|
||||
}
|
||||
|
||||
|
||||
static ssize_t send_or_buffer(send_buffer_t *sb, int fd, char *buf, size_t len)
|
||||
static ssize_t send_or_buffer(send_buffer_t *sb, int fd, char *buf, size_t len, int ttl)
|
||||
{
|
||||
ssize_t wr=0;
|
||||
if (len)
|
||||
{
|
||||
wr = send(fd, buf, len, 0);
|
||||
wr = send_with_ttl(fd, buf, len, 0, ttl);
|
||||
if (wr<0 && errno==EAGAIN) wr=0;
|
||||
if (wr>=0 && wr<len)
|
||||
{
|
||||
if (!send_buffer_create(sb, buf+wr, len-wr))
|
||||
if (!send_buffer_create(sb, buf+wr, len-wr, ttl))
|
||||
wr=-1;
|
||||
}
|
||||
}
|
||||
@@ -967,19 +989,19 @@ static bool handle_epoll(tproxy_conn_t *conn, struct tailhead *conn_list, uint32
|
||||
if (split_pos)
|
||||
{
|
||||
VPRINT("Splitting at pos %zu", split_pos)
|
||||
wr = send_or_buffer(conn->partner->wr_buf, conn->partner->fd, buf, split_pos);
|
||||
wr = send_or_buffer(conn->partner->wr_buf, conn->partner->fd, buf, split_pos, params.disorder ? 1 : 0);
|
||||
DBGPRINT("send_or_buffer(1) fd=%d wr=%zd err=%d",conn->partner->fd,wr,errno)
|
||||
if (wr >= 0)
|
||||
{
|
||||
conn->partner->twr += wr;
|
||||
wr = send_or_buffer(conn->partner->wr_buf + 1, conn->partner->fd, buf + split_pos, bs - split_pos);
|
||||
wr = send_or_buffer(conn->partner->wr_buf + 1, conn->partner->fd, buf + split_pos, bs - split_pos, 0);
|
||||
DBGPRINT("send_or_buffer(2) fd=%d wr=%zd err=%d",conn->partner->fd,wr,errno)
|
||||
if (wr>0) conn->partner->twr += wr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
wr = send_or_buffer(conn->partner->wr_buf, conn->partner->fd, buf, bs);
|
||||
wr = send_or_buffer(conn->partner->wr_buf, conn->partner->fd, buf, bs, 0);
|
||||
DBGPRINT("send_or_buffer(3) fd=%d wr=%zd err=%d",conn->partner->fd,wr,errno)
|
||||
if (wr>0) conn->partner->twr += wr;
|
||||
}
|
||||
@@ -1039,7 +1061,7 @@ static bool read_all_and_buffer(tproxy_conn_t *conn, int buffer_number)
|
||||
DBGPRINT("read_all_and_buffer(%d) numbytes=%d",buffer_number,numbytes)
|
||||
if (numbytes>0)
|
||||
{
|
||||
if (send_buffer_create(conn->partner->wr_buf+buffer_number, NULL, numbytes))
|
||||
if (send_buffer_create(conn->partner->wr_buf+buffer_number, NULL, numbytes, 0))
|
||||
{
|
||||
ssize_t rd = recv(conn->fd, conn->partner->wr_buf[buffer_number].data, numbytes, MSG_DONTWAIT);
|
||||
if (rd>0)
|
||||
|
@@ -29,6 +29,7 @@ struct send_buffer
|
||||
{
|
||||
char *data;
|
||||
size_t len,pos;
|
||||
int ttl;
|
||||
};
|
||||
typedef struct send_buffer send_buffer_t;
|
||||
|
||||
|
Reference in New Issue
Block a user