mirror of
https://github.com/bol-van/zapret.git
synced 2024-12-02 14:40:52 +03:00
v4
This commit is contained in:
parent
7443de517a
commit
7984222771
@ -22,3 +22,6 @@ ISP support : successfully tested sknt.ru on 'domru' configuration
|
|||||||
other configs will probably also work, but cannot test
|
other configs will probably also work, but cannot test
|
||||||
compile : openwrt compile howto
|
compile : openwrt compile howto
|
||||||
|
|
||||||
|
v4
|
||||||
|
|
||||||
|
tpws : added ability to insert extra space after http method : "GET /" => "GET /"
|
||||||
|
42
readme.txt
42
readme.txt
@ -1,4 +1,4 @@
|
|||||||
zapret v.3
|
zapret v.4
|
||||||
|
|
||||||
Для чего это надо
|
Для чего это надо
|
||||||
-----------------
|
-----------------
|
||||||
@ -23,6 +23,7 @@
|
|||||||
что сервер увеличил window size, и все пойдет как обычно.
|
что сервер увеличил window size, и все пойдет как обычно.
|
||||||
|
|
||||||
Другие DPI спотыкаются, когда заголовок "Host:" пишется в другом регистре : например, "host:".
|
Другие DPI спотыкаются, когда заголовок "Host:" пишется в другом регистре : например, "host:".
|
||||||
|
Кое-где работает добавление дополнительного проблема после метода : "GET /" => "GET /".
|
||||||
|
|
||||||
Как это реализовать на практике в системе linux
|
Как это реализовать на практике в системе linux
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
@ -76,11 +77,13 @@ transparent proxy (TPROXY или DNAT). TPROXY не работает с соед
|
|||||||
и для этого пользователя отключается DNAT через "-m owner". Полное проксирование требует больше ресурсов
|
и для этого пользователя отключается DNAT через "-m owner". Полное проксирование требует больше ресурсов
|
||||||
процессора, чем манипуляция с исходящими пакетами без реконструкции TCP соединения.
|
процессора, чем манипуляция с исходящими пакетами без реконструкции TCP соединения.
|
||||||
|
|
||||||
|
iptables -t nat -I PREROUTING -p tcp --dport 80 -j DNAT --to 127.0.0.1:1188
|
||||||
|
iptables -t nat -I OUTPUT -p tcp --dport 80 -m owner ! --uid-owner tpws -j DNAT --to 127.0.0.1:1188
|
||||||
|
|
||||||
nfqws
|
nfqws
|
||||||
-----
|
-----
|
||||||
|
|
||||||
Эта программа и есть модификатор пакетов и обработчик очереди NFQUEUE.
|
Эта программа - модификатор пакетов и обработчик очереди NFQUEUE.
|
||||||
Она берет следующие параметры :
|
Она берет следующие параметры :
|
||||||
--qnum=200 ; номер очереди
|
--qnum=200 ; номер очереди
|
||||||
--wsize=4 ; менять tcp window size на указанный размер
|
--wsize=4 ; менять tcp window size на указанный размер
|
||||||
@ -91,11 +94,13 @@ tpws
|
|||||||
-----
|
-----
|
||||||
|
|
||||||
tpws - это transparent proxy.
|
tpws - это transparent proxy.
|
||||||
--bind-addr ; на каком адресе слушать
|
--bind-addr ; на каком адресе слушать. может быть ipv4 или ipv6 адрес. если не указано, то слушает на всех адресах ipv4 и ipv6
|
||||||
--port=<port> ; на каком порту слушать
|
--port=<port> ; на каком порту слушать
|
||||||
--split-http-req=method|host ; способ разделения http запросов на сегменты : около метода (GET,POST) или около заголовка Host
|
--split-http-req=method|host ; способ разделения http запросов на сегменты : около метода (GET,POST) или около заголовка Host
|
||||||
--hostcase ; change Host: => host:
|
--hostcase ; замена "Host:" => "host:"
|
||||||
--daemon ; daemonize
|
--methodspace ; добавить пробел после метода : "GET /" => "GET /"
|
||||||
|
--daemon ; демонизировать прогу
|
||||||
|
--user=<username> ; менять uid процесса
|
||||||
|
|
||||||
Провайдеры
|
Провайдеры
|
||||||
----------
|
----------
|
||||||
@ -107,6 +112,8 @@ dom.ru : нужно проксирование HTTP сессий через tpws
|
|||||||
блокировок, поэтому если вдруг на каком-то сайте вылезает блокировочный баннер, то идите в консоль firefox, вкладка network.
|
блокировок, поэтому если вдруг на каком-то сайте вылезает блокировочный баннер, то идите в консоль firefox, вкладка network.
|
||||||
Загружайте сайт и смотрите куда идет редирект. Потом вносите домен в zapret-hosts-user.txt. Например, на kinozal.tv имеются
|
Загружайте сайт и смотрите куда идет редирект. Потом вносите домен в zapret-hosts-user.txt. Например, на kinozal.tv имеются
|
||||||
2 запрашиваемых поддомена : s.kinozal.tv и st.kinozal.tv с разными IP адресами.
|
2 запрашиваемых поддомена : s.kinozal.tv и st.kinozal.tv с разными IP адресами.
|
||||||
|
sknt.ru : проверена работа с tpws с параметром "--split-http-req=method". возможно, будет работать nfqueue, пока возможности
|
||||||
|
проверить нет
|
||||||
|
|
||||||
Пример установки на debian 7
|
Пример установки на debian 7
|
||||||
----------------------------
|
----------------------------
|
||||||
@ -141,6 +148,31 @@ dom.ru : нужно проксирование HTTP сессий через tpws
|
|||||||
Попробуйте снять дамп в wireshark или "tcpdump -vvv -X host <ip>", посмотрите действительно ли первый
|
Попробуйте снять дамп в wireshark или "tcpdump -vvv -X host <ip>", посмотрите действительно ли первый
|
||||||
сегмент TCP уходит коротким и меняется ли регистр "Host:".
|
сегмент TCP уходит коротким и меняется ли регистр "Host:".
|
||||||
|
|
||||||
|
ubuntu 12,14
|
||||||
|
------------
|
||||||
|
|
||||||
|
Имеется готовый конфиг для upstart : zapret.conf. Его нужно скопировать в /etc/init и настроить по аналогии с debian.
|
||||||
|
Запуск службы : "start zapret"
|
||||||
|
Останов службы : "stop zapret"
|
||||||
|
|
||||||
|
Другие linux системы
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
Существует несколько основных систем запуска служб : sysvinit, upstart, systemd.
|
||||||
|
Насройка зависит от системы, используемой в вашем дистрибутиве.
|
||||||
|
Типичная стратегия - найти скрипт или конфигурацию запуска других служб и написать свой по аналогии,
|
||||||
|
при необходимости почитывая документации по системе запуска.
|
||||||
|
Нужные команды можно взять из предложенных скриптов.
|
||||||
|
|
||||||
|
Фаерволлы
|
||||||
|
---------
|
||||||
|
|
||||||
|
Если вы используете какую-то систему управления фаерволом, то она может вступать в конфликт
|
||||||
|
с имеющимся скриптом запуска. В этом случае правила для iptables должны быть прикручены
|
||||||
|
к вашему фаерволу отдельно от скрипта запуска tpws или nfqws.
|
||||||
|
Именно так решается вопрос в случае с openwrt, поскольку там своя система управления фаерволом.
|
||||||
|
При повторном применении правил она могла бы поломать настройки iptables, сделанные скриптом из init.d.
|
||||||
|
|
||||||
Что делать с openwrt
|
Что делать с openwrt
|
||||||
--------------------
|
--------------------
|
||||||
|
|
||||||
|
55
tpws/tpws.c
55
tpws/tpws.c
@ -33,7 +33,7 @@ struct params_s
|
|||||||
gid_t gid;
|
gid_t gid;
|
||||||
uint16_t port;
|
uint16_t port;
|
||||||
bool daemon;
|
bool daemon;
|
||||||
bool hostcase,methodcase;
|
bool hostcase,methodcase,methodspace;
|
||||||
enum splithttpreq split_http_req;
|
enum splithttpreq split_http_req;
|
||||||
int maxconn;
|
int maxconn;
|
||||||
};
|
};
|
||||||
@ -77,11 +77,13 @@ void close_tcp_conn(tproxy_conn_t *conn, struct tailhead *conn_list,
|
|||||||
static const char *http_split_methods[]={"GET /","POST /","HEAD /","OPTIONS /",NULL};
|
static const char *http_split_methods[]={"GET /","POST /","HEAD /","OPTIONS /",NULL};
|
||||||
static const char *http_split_host[]={"\r\nHost: ",NULL};
|
static const char *http_split_host[]={"\r\nHost: ",NULL};
|
||||||
|
|
||||||
|
#define RD_BLOCK_SIZE 8192
|
||||||
|
|
||||||
bool handle_epollin(tproxy_conn_t *conn,int *data_transferred){
|
bool handle_epollin(tproxy_conn_t *conn,int *data_transferred){
|
||||||
int numbytes;
|
int numbytes;
|
||||||
int fd_in, fd_out;
|
int fd_in, fd_out;
|
||||||
bool bOutgoing;
|
bool bOutgoing;
|
||||||
ssize_t rd=0,wr=0;
|
ssize_t rd=0,wr=0,bs;
|
||||||
|
|
||||||
//Easy way to determin which socket is ready for reading
|
//Easy way to determin which socket is ready for reading
|
||||||
//TODO: Optimize. This one allows me quick lookup for conn, but
|
//TODO: Optimize. This one allows me quick lookup for conn, but
|
||||||
@ -104,40 +106,63 @@ bool handle_epollin(tproxy_conn_t *conn,int *data_transferred){
|
|||||||
{
|
{
|
||||||
if (bOutgoing)
|
if (bOutgoing)
|
||||||
{
|
{
|
||||||
char buf[8192],*p;
|
char buf[RD_BLOCK_SIZE+1],*p;
|
||||||
ssize_t l,split_pos=0;
|
ssize_t l,split_pos=0,pos;
|
||||||
const char **split_array,**split_item;
|
const char **split_array,**split_item,**item;
|
||||||
|
|
||||||
rd = recv(fd_in,buf,sizeof(buf),MSG_DONTWAIT);
|
rd = recv(fd_in,buf,RD_BLOCK_SIZE,MSG_DONTWAIT);
|
||||||
if (rd>0)
|
if (rd>0)
|
||||||
{
|
{
|
||||||
|
bs = rd;
|
||||||
|
if (params.methodspace)
|
||||||
|
{
|
||||||
|
for(item=http_split_methods;*item;item++)
|
||||||
|
{
|
||||||
|
l = strlen(*item);
|
||||||
|
if (p=find_bin(buf,bs,*item,l))
|
||||||
|
{
|
||||||
|
pos = p-buf;
|
||||||
|
printf("Found http method '%s' at pos %d. Adding extra space.\n",*item,pos);
|
||||||
|
p += l-1;
|
||||||
|
pos += l-1;
|
||||||
|
memmove(p+1,p,bs-pos);
|
||||||
|
*p = ' '; // insert extra space
|
||||||
|
bs++; // block will grow by 1 byte
|
||||||
|
split_pos = pos; // remember split positing and use it if required
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
switch (params.split_http_req)
|
switch (params.split_http_req)
|
||||||
{
|
{
|
||||||
case split_method:
|
case split_method:
|
||||||
split_array = http_split_methods;
|
// do we have already split position ? if so use it without another search
|
||||||
|
split_array = split_pos ? NULL : http_split_methods;
|
||||||
break;
|
break;
|
||||||
case split_host:
|
case split_host:
|
||||||
split_array = http_split_host;
|
split_array = http_split_host;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
split_array = NULL;
|
split_array = NULL;
|
||||||
|
split_pos=0;
|
||||||
}
|
}
|
||||||
if (split_array)
|
if (split_array)
|
||||||
{
|
{
|
||||||
for(split_item=split_array;*split_item;split_item++)
|
for(split_item=split_array;*split_item;split_item++)
|
||||||
{
|
{
|
||||||
l = strlen(*split_item);
|
l = strlen(*split_item);
|
||||||
if (p=find_bin(buf,rd,*split_item,l))
|
if (p=find_bin(buf,bs,*split_item,l))
|
||||||
{
|
{
|
||||||
split_pos = p-buf;
|
split_pos = p-buf;
|
||||||
printf("Found split item '%s' at pos %d\n",*split_item,split_pos);
|
printf("Found split item '%s' at pos %d\n",*split_item,split_pos);
|
||||||
split_pos += l-1;
|
split_pos += l-1;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (params.hostcase)
|
if (params.hostcase)
|
||||||
{
|
{
|
||||||
if (p=find_bin(buf,rd,"\r\nHost: ",8))
|
if (p=find_bin(buf,bs,"\r\nHost: ",8))
|
||||||
{
|
{
|
||||||
printf("Changing 'Host:' => 'host:' at pos %d\n",p-buf);
|
printf("Changing 'Host:' => 'host:' at pos %d\n",p-buf);
|
||||||
p[2]='h';
|
p[2]='h';
|
||||||
@ -148,7 +173,7 @@ bool handle_epollin(tproxy_conn_t *conn,int *data_transferred){
|
|||||||
for(split_item=http_split_methods;*split_item;split_item++)
|
for(split_item=http_split_methods;*split_item;split_item++)
|
||||||
{
|
{
|
||||||
l = strlen(*split_item);
|
l = strlen(*split_item);
|
||||||
if (p=find_bin(buf,rd,*split_item,l))
|
if (p=find_bin(buf,bs,*split_item,l))
|
||||||
{
|
{
|
||||||
printf("Changing '%s' case\n",*split_item);
|
printf("Changing '%s' case\n",*split_item);
|
||||||
*p += 'a'-'A';
|
*p += 'a'-'A';
|
||||||
@ -160,11 +185,11 @@ bool handle_epollin(tproxy_conn_t *conn,int *data_transferred){
|
|||||||
{
|
{
|
||||||
wr=send_with_flush(fd_out,buf,split_pos,0);
|
wr=send_with_flush(fd_out,buf,split_pos,0);
|
||||||
if (wr>=0)
|
if (wr>=0)
|
||||||
wr=send(fd_out,buf+split_pos,rd-split_pos,0);
|
wr=send(fd_out,buf+split_pos,bs-split_pos,0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wr=send(fd_out,buf,rd,0);
|
wr=send(fd_out,buf,bs,0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -341,7 +366,7 @@ int8_t block_sigpipe(){
|
|||||||
|
|
||||||
void exithelp()
|
void exithelp()
|
||||||
{
|
{
|
||||||
printf(" --bind-addr=<ipv4_addr>|<ipv6_addr>\n --port=<port>\n --maxconn=<max_connections>\n --split-http-req=method|host\n --hostcase\t\t; change Host: => host:\n --methodcase\t\t; change GET => gET, POST=>pOST, ...\n --daemon\t\t; daemonize\n --user=<username>\t; drop root privs\n");
|
printf(" --bind-addr=<ipv4_addr>|<ipv6_addr>\n --port=<port>\n --maxconn=<max_connections>\n --split-http-req=method|host\n --hostcase\t\t; change Host: => host:\n --methodcase\t\t; change GET => gET, POST=>pOST, ...\n --methodspace\t\t; add extra space after method\n --daemon\t\t; daemonize\n --user=<username>\t; drop root privs\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -364,6 +389,7 @@ void parse_params(int argc, char *argv[])
|
|||||||
{"hostcase",no_argument,0,0},// optidx=7
|
{"hostcase",no_argument,0,0},// optidx=7
|
||||||
{"methodcase",no_argument,0,0},// optidx=8
|
{"methodcase",no_argument,0,0},// optidx=8
|
||||||
{"split-http-req",required_argument,0,0},// optidx=9
|
{"split-http-req",required_argument,0,0},// optidx=9
|
||||||
|
{"methodspace",no_argument,0,0},// optidx=10
|
||||||
{NULL,0,NULL,0}
|
{NULL,0,NULL,0}
|
||||||
};
|
};
|
||||||
while ((v=getopt_long_only(argc,argv,"",long_options,&option_index))!=-1)
|
while ((v=getopt_long_only(argc,argv,"",long_options,&option_index))!=-1)
|
||||||
@ -428,6 +454,9 @@ void parse_params(int argc, char *argv[])
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case 10: /* methodspace */
|
||||||
|
params.methodspace = true;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!params.port)
|
if (!params.port)
|
||||||
|
Loading…
Reference in New Issue
Block a user