Browse Source

gzip support in ipset/*.sh and tpws

pull/33/head
bolvan 6 years ago
parent
commit
c5dc07d049
  1. BIN
      binaries/aarch64/nfqws
  2. BIN
      binaries/aarch64/tpws
  3. BIN
      binaries/armhf/nfqws
  4. BIN
      binaries/armhf/tpws
  5. BIN
      binaries/mips32r1-lsb/nfqws
  6. BIN
      binaries/mips32r1-lsb/tpws
  7. BIN
      binaries/mips32r1-msb/nfqws
  8. BIN
      binaries/mips32r1-msb/tpws
  9. BIN
      binaries/ppc/nfqws
  10. BIN
      binaries/ppc/tpws
  11. BIN
      binaries/x86/nfqws
  12. BIN
      binaries/x86/tpws
  13. BIN
      binaries/x86_64/nfqws
  14. BIN
      binaries/x86_64/tpws
  15. 1
      docs/compile/openwrt/package/zapret/tpws/Makefile
  16. 37
      docs/readme.txt
  17. 3
      init.d/openwrt/zapret
  18. 3
      init.d/sysv/zapret
  19. 5
      install_easy.sh
  20. 2
      ipset/get_hostlist.sh
  21. 0
      ipset/zapret-hosts.txt
  22. 98
      nfq/nfqws.c
  23. 2
      tpws/Makefile
  24. 75
      tpws/gzip.c
  25. 6
      tpws/gzip.h
  26. 82
      tpws/hostlist.c
  27. 5
      tpws/hostlist.h
  28. 25
      tpws/strpool.c
  29. 1
      tpws/strpool.h
  30. 140
      tpws/tpws.c

BIN
binaries/aarch64/nfqws

Binary file not shown.

BIN
binaries/aarch64/tpws

Binary file not shown.

BIN
binaries/armhf/nfqws

Binary file not shown.

BIN
binaries/armhf/tpws

Binary file not shown.

BIN
binaries/mips32r1-lsb/nfqws

Binary file not shown.

BIN
binaries/mips32r1-lsb/tpws

Binary file not shown.

BIN
binaries/mips32r1-msb/nfqws

Binary file not shown.

BIN
binaries/mips32r1-msb/tpws

Binary file not shown.

BIN
binaries/ppc/nfqws

Binary file not shown.

BIN
binaries/ppc/tpws

Binary file not shown.

BIN
binaries/x86/nfqws

Binary file not shown.

BIN
binaries/x86/tpws

Binary file not shown.

BIN
binaries/x86_64/nfqws

Binary file not shown.

BIN
binaries/x86_64/tpws

Binary file not shown.

1
docs/compile/openwrt/package/zapret/tpws/Makefile

@ -12,6 +12,7 @@ define Package/tpws
CATEGORY:=Network
TITLE:=tpws
SUBMENU:=Zapret
DEPENDS:=+zlib
endef
define Build/Prepare

37
docs/readme.txt

@ -97,6 +97,7 @@ nfqws
Эта программа - модификатор пакетов и обработчик очереди NFQUEUE.
Она берет следующие параметры :
--daemon ; демонизировать прогу
--pidfile=<file> ; сохранить PID в файл
--qnum=200 ; номер очереди
--wsize=4 ; менять tcp window size на указанный размер
--hostcase ; менять регистр заголовка "Host:" по умолчанию на "host:".
@ -108,10 +109,11 @@ tpws
-----
tpws - это transparent proxy.
--bind-addr ; на каком адресе слушать. может быть ipv4 или ipv6 адрес. если не указано, то слушает на всех адресах ipv4 и ipv6
--port=<port> ; на каком порту слушать
--daemon ; демонизировать прогу
--pidfile=<file> ; сохранить PID в файл
--user=<username> ; менять uid процесса
--bind-addr ; на каком адресе слушать. может быть ipv4 или ipv6 адрес. если не указано, то слушает на всех адресах ipv4 и ipv6
--port=<port> ; на каком порту слушать
--split-http-req=method|host ; способ разделения http запросов на сегменты : около метода (GET,POST) или около заголовка Host
--split-pos=<offset> ; делить все посылы на сегменты в указанной позиции. Если отсыл длинее 8Kb (размер буфера приема), то будет разделен каждый блок по 8Kb.
--hostcase ; менять регистр заголовка "Host:". по умолчанию на "host:".
@ -126,6 +128,7 @@ tpws - это transparent proxy.
; список читается 1 раз при старте и хранится в памяти в виде иерархической структуры для быстрого поиска.
; для списка РКН может потребоваться система с 128 Mb памяти ! расчитывайте требование RAM для процесса как 3-5 кратный размер файла списка.
; по сигналу HUP список будет перечитан при следующем принятом соединении
; список может быть запакован в gzip. формат автоматически распознается и разжимается
Параметры манипуляции могут сочетаться в любых комбинациях.
Есть исключения : split-pos заменяет split-http-req. hostdot и hosttab взаимоисключающи.
@ -136,7 +139,7 @@ tpws - это transparent proxy.
На выходе получите ipset/zapret-ip-user.txt с IP адресами.
2) ipset/get_reestr.sh получает список доменов от rublacklist и дальше их ресолвит в ip адреса
в файл ipset/zapret-ip.txt. В этом списке есть готовые IP адреса, но судя во всему они там в точности в том виде,
в файл ipset/zapret-ip.txt.gz. В этом списке есть готовые IP адреса, но судя во всему они там в точности в том виде,
что вносит в реестр РосКомПозор. Адреса могут меняться, позор не успевает их обновлять, а провайдеры редко
банят по IP : вместо этого они банят http запросы с "нехорошим" заголовком "Host:" вне зависимости
от IP адреса. Поэтому скрипт ресолвит все сам, хотя это и занимает много времени.
@ -185,7 +188,7 @@ get_reestr.sh может использовать мультипоточный
----------------------------
Альтернативой ipset является использование tpws со списком доменов.
Список доменов РКН может быть получен скриптом ipset/get_hostlist.sh - кладется в ipset/zapret-hosts.txt.
Список доменов РКН может быть получен скриптом ipset/get_hostlist.sh - кладется в ipset/zapret-hosts.txt.gz.
Этот скрипт автоматически добавляет к списку РКН домены из zapret-hosts-user.txt.
tpws должен запускаться без фильтрации по ipset. Весь трафик http идет через tpws, и он решает нужно ли
применять дурение в зависимости от поля Host: в http запросе.
@ -273,7 +276,7 @@ TPWS_OPT_HTTPS="--split-pos=3"
systemctl enable zapret
Удалить старые листы, если они были созданы ранее :
rm /opt/zapret/ipset/zapret-ip.txt* /opt/zapret/ipset/zapret-ip-user.txt* /opt/zapret/ipset/zapret-ip-ipban.txt* /opt/zapret/ipset/zapret-ip-user-ipban.txt* /opt/zapret/ipset/zapret-hosts.txt
rm /opt/zapret/ipset/zapret-ip.txt* /opt/zapret/ipset/zapret-ip-user.txt* /opt/zapret/ipset/zapret-ip-ipban.txt* /opt/zapret/ipset/zapret-ip-user-ipban.txt* /opt/zapret/ipset/zapret-hosts.txt*
По желанию прописать в /opt/zapret/ipset/zapret-hosts-user.txt свои домены.
Выполнить скрипт обновления листа :
/opt/zapret/ipset/get_config.sh
@ -446,18 +449,18 @@ ipset можно выкинуть, если не будем пользовать
rm /tmp/zapret-master.zip
Если места совсем мало :
opkg update
opkg install netcat
cd /tmp
netcat -l -p 1111 >zapret.tar.gz
opkg update
opkg install netcat
cd /tmp
netcat -l -p 1111 >zapret.tar.gz
На linux системе скачать и распаковать zapret. Оставить необходимый минимум файлов.
Запаковать в архив zapret.tar.gz.
md5sum zapret.tar.gz
netcat <router_ip> 1111 <zapret.tar.gz
<ctrl+c>
На роутере
md5sum zapret.tar.gz
Проверить соответствие hash.
Запаковать в архив zapret.tar.gz.
md5sum zapret.tar.gz
netcat <router_ip> 1111 <zapret.tar.gz
<ctrl+c>
На роутере
md5sum zapret.tar.gz
Проверить соответствие hash.
Не стоит работать с распакованной версией zapret на windows. Потеряются ссылки и chmod.
@ -470,7 +473,7 @@ ipset можно выкинуть, если не будем пользовать
Настроить параметры согласно разделу "Выбор параметров".
Удалить старые листы, если они были созданы ранее :
rm /opt/zapret/ipset/zapret-ip.txt* /opt/zapret/ipset/zapret-ip-user.txt* /opt/zapret/ipset/zapret-ip-ipban.txt* /opt/zapret/ipset/zapret-ip-user-ipban.txt* /opt/zapret/ipset/zapret-hosts.txt
rm /opt/zapret/ipset/zapret-ip.txt* /opt/zapret/ipset/zapret-ip-user.txt* /opt/zapret/ipset/zapret-ip-ipban.txt* /opt/zapret/ipset/zapret-ip-user-ipban.txt* /opt/zapret/ipset/zapret-hosts.txt*
По желанию прописать в /opt/zapret/ipset/zapret-hosts-user.txt свои домены.
Выполнить скрипт обновления листа :
/opt/zapret/ipset/get_config.sh

3
init.d/openwrt/zapret

@ -21,7 +21,8 @@ TPPORT_HTTP=1188
TPPORT_HTTPS=1189
TPWS=$ZAPRET_BASE/tpws/tpws
TPWS_USER=daemon
TPWS_HOSTLIST=$ZAPRET_BASE/ipset/zapret-hosts.txt
TPWS_HOSTLIST=$ZAPRET_BASE/ipset/zapret-hosts.txt.gz
[ -f "$TPWS_HOSTLIST" ] || TPWS_HOSTLIST=$ZAPRET_BASE/ipset/zapret-hosts-user.txt
TPWS_OPT_BASE="--user=$TPWS_USER --bind-addr=127.0.0.1"
TPWS_OPT_BASE_HTTP="--port=$TPPORT_HTTP $TPWS_OPT_BASE"
TPWS_OPT_BASE_HTTPS="--port=$TPPORT_HTTPS $TPWS_OPT_BASE"

3
init.d/sysv/zapret

@ -28,7 +28,8 @@ TPPORT_HTTP=1188
TPPORT_HTTPS=1189
TPWS=$ZAPRET_BASE/tpws/tpws
TPWS_USER=tpws
TPWS_HOSTLIST=$ZAPRET_BASE/ipset/zapret-hosts.txt
TPWS_HOSTLIST=$ZAPRET_BASE/ipset/zapret-hosts.txt.gz
[ -f "$TPWS_HOSTLIST" ] || TPWS_HOSTLIST=$ZAPRET_BASE/ipset/zapret-hosts-user.txt
TPWS_OPT_BASE="--user=$TPWS_USER --bind-addr=127.0.0.1"
TPWS_OPT_BASE_HTTP="--port=$TPPORT_HTTP $TPWS_OPT_BASE"
TPWS_OPT_BASE_HTTPS="--port=$TPPORT_HTTPS $TPWS_OPT_BASE"

5
install_easy.sh

@ -283,7 +283,7 @@ check_preprequisites_linux()
exitp 6
}
elif [ -x "$YUM" ] ; then
"$YUM" -y install curl ipset daemonize || {
"$YUM" -y install curl ipset || {
echo could not install prerequisites
exitp 6
}
@ -366,7 +366,8 @@ download_list()
# can be txt or txt.gz
rm -f "$EXEDIR/ipset/zapret-ip.txt"* "$EXEDIR/ipset/zapret-ip-user.txt"* \
"$EXEDIR/ipset/zapret-ip-ipban.txt"* "$EXEDIR/ipset/zapret-ip-user-ipban.txt"*
"$EXEDIR/ipset/zapret-ip-ipban.txt"* "$EXEDIR/ipset/zapret-ip-user-ipban.txt"* \
"$EXEDIR/ipset/zapret-hosts.txt"*
"$GET_LIST" || {
echo could not download ip list
exitp 25

2
ipset/get_hostlist.sh

@ -20,7 +20,7 @@ if test $dlsize -lt 204800; then
echo list file is too small. can be bad.
exit 2
fi
(cut -s -f2 -d';' "$ZREESTR" | grep -a . | sed -re 's/^\*\.(.+)$/\1/' | awk '{ print tolower($0) }' ; cat "$ZUSERLIST" ) | sort -u >"$ZHOSTLIST"
(cut -s -f2 -d';' "$ZREESTR" | grep -a . | sed -re 's/^\*\.(.+)$/\1/' | awk '{ print tolower($0) }' ; cat "$ZUSERLIST" ) | sort -u | zz "$ZHOSTLIST"
rm -f "$ZREESTR"
# force tpws to reload if its running

0
ipset/zapret-hosts.txt

98
nfq/nfqws.c

@ -366,6 +366,46 @@ bool droproot(uid_t uid, gid_t gid)
return true;
}
void daemonize()
{
int pid;
pid = fork();
if (pid == -1)
{
perror("fork: ");
exit(2);
}
else if (pid != 0)
exit(0);
if (setsid() == -1)
exit(2);
if (chdir("/") == -1)
exit(2);
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
/* redirect fd's 0,1,2 to /dev/null */
open("/dev/null", O_RDWR);
/* stdin */
dup(0);
/* stdout */
dup(0);
/* stderror */
}
bool writepid(const char *filename)
{
FILE *F;
if (!(F=fopen(filename,"w")))
return false;
fprintf(F,"%d",getpid());
fclose(F);
return true;
}
void exithelp()
{
printf(
@ -375,6 +415,7 @@ void exithelp()
" --hostspell\t\t; exact spelling of \"Host\" header. must be 4 chars. default is \"host\"\n"
" --hostnospace\t\t; remove space after Host: and add it to User-Agent: to preserve packet size\n"
" --daemon\t\t; daemonize\n"
" --pidfile=<filename>\t; write pid to file\n"
);
exit(1);
}
@ -392,10 +433,12 @@ int main(int argc, char **argv)
bool daemon=false;
uid_t uid=0;
gid_t gid;
char pidfile[256];
memset(&cbdata,0,sizeof(cbdata));
memcpy(cbdata.hostspell,"host",4); // default hostspell
*pidfile = 0;
const struct option long_options[] = {
{"qnum",required_argument,0,0}, // optidx=0
{"daemon",no_argument,0,0}, // optidx=1
@ -404,6 +447,7 @@ int main(int argc, char **argv)
{"hostspell",required_argument,0,0}, // optidx=4
{"hostnospace",no_argument,0,0}, // optidx=5
{"user",required_argument,0,0}, // optidx=6
{"pidfile",required_argument,0,0}, // optidx=7
{NULL,0,NULL,0}
};
if (argc<2) exithelp();
@ -458,64 +502,55 @@ int main(int argc, char **argv)
gid = pwd->pw_gid;
break;
}
case 7: /* pidfile */
strncpy(pidfile,optarg,sizeof(pidfile));
pidfile[sizeof(pidfile)-1]='\0';
break;
}
}
if (daemon)
if (daemon) daemonize();
h = NULL;
qh = NULL;
if (*pidfile && !writepid(pidfile))
{
int pid;
pid = fork();
if (pid == -1)
return -1;
else if (pid != 0)
return 0;
if (setsid() == -1)
return -1;
if (chdir ("/") == -1)
return -1;
close(STDIN_FILENO);
close(STDOUT_FILENO);
close(STDERR_FILENO);
/* redirect fd's 0,1,2 to /dev/null */
open ("/dev/null", O_RDWR);
/* stdin */
dup(0);
/* stdout */
dup(0);
/* stderror */
fprintf(stderr,"could not write pidfile\n");
goto exiterr;
}
printf("opening library handle\n");
h = nfq_open();
if (!h) {
fprintf(stderr, "error during nfq_open()\n");
exit(1);
goto exiterr;
}
printf("unbinding existing nf_queue handler for AF_INET (if any)\n");
if (nfq_unbind_pf(h, AF_INET) < 0) {
fprintf(stderr, "error during nfq_unbind_pf()\n");
exit(1);
goto exiterr;
}
printf("binding nfnetlink_queue as nf_queue handler for AF_INET\n");
if (nfq_bind_pf(h, AF_INET) < 0) {
fprintf(stderr, "error during nfq_bind_pf()\n");
exit(1);
goto exiterr;
}
printf("binding this socket to queue '%u'\n", cbdata.qnum);
qh = nfq_create_queue(h, cbdata.qnum, &cb, &cbdata);
if (!qh) {
fprintf(stderr, "error during nfq_create_queue()\n");
exit(1);
goto exiterr;
}
printf("setting copy_packet mode\n");
if (nfq_set_mode(qh, NFQNL_COPY_PACKET, 0xffff) < 0) {
fprintf(stderr, "can't set packet_copy mode\n");
exit(1);
goto exiterr;
}
fd = nfq_fd(h);
@ -542,5 +577,10 @@ int main(int argc, char **argv)
printf("closing library handle\n");
nfq_close(h);
exit(0);
return 0;
exiterr:
if (qh) nfq_destroy_queue(qh);
if (h) nfq_close(h);
return 1;
}

2
tpws/Makefile

@ -1,6 +1,6 @@
CC ?= gcc
CFLAGS += -s -O3
LIBS =
LIBS = -lz
SRC_FILES = *.c
all: tpws

75
tpws/gzip.c

@ -0,0 +1,75 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "gzip.h"
#define ZCHUNK 16384
#define BUFMIN 128
#define BUFCHUNK (1024*128)
int z_readfile(FILE *F,char **buf,size_t *size)
{
z_stream zs;
int r;
unsigned char in[ZCHUNK];
size_t bufsize;
void *newbuf;
memset(&zs,0,sizeof(zs));
*buf = NULL;
bufsize=*size=0;
r=inflateInit2(&zs,47);
if (r != Z_OK) return r;
do
{
zs.avail_in = fread(in, 1, sizeof(in), F);
if (ferror(F))
{
r = Z_ERRNO;
goto zerr;
}
if (!zs.avail_in) break;
zs.next_in = in;
do
{
if ((bufsize-*size)<BUFMIN)
{
bufsize += BUFCHUNK;
newbuf = *buf ? realloc(*buf,bufsize) : malloc(bufsize);
if (newbuf==*buf)
if (!newbuf)
{
r = Z_MEM_ERROR;
goto zerr;
}
*buf = newbuf;
}
zs.avail_out = bufsize - *size;
zs.next_out = (unsigned char*)(*buf + *size);
r = inflate(&zs, Z_NO_FLUSH);
if (r!=Z_OK && r!=Z_STREAM_END) goto zerr;
*size = bufsize - zs.avail_out;
} while (r==Z_OK && zs.avail_in);
} while (r==Z_OK);
if (*size<bufsize)
{
// free extra space
if (newbuf = realloc(*buf,*size)) *buf=newbuf;
}
inflateEnd(&zs);
return Z_OK;
zerr:
inflateEnd(&zs);
if (*buf)
{
free(*buf);
*buf = NULL;
}
return r;
}

6
tpws/gzip.h

@ -0,0 +1,6 @@
#pragma once
#include <stdio.h>
#include <zlib.h>
int z_readfile(FILE *F,char **buf,size_t *size);

82
tpws/hostlist.c

@ -0,0 +1,82 @@
#include <stdio.h>
#include "hostlist.h"
#include "gzip.h"
static bool addpool(strpool **hostlist, char **s, char *end)
{
char *p;
// advance until eol lowering all chars
for (p = *s; p<end && *p && *p!='\r' && *p != '\n'; p++) *p=tolower(*p);
if (!StrPoolAddStrLen(hostlist, *s, p-*s))
{
StrPoolDestroy(hostlist);
*hostlist = NULL;
return false;
}
// advance to the next line
for (; p<end && (!*p || *p=='\r' || *p=='\n') ; p++);
*s = p;
return true;
}
bool LoadHostList(strpool **hostlist, char *filename)
{
char *p, *e, s[256], *zbuf;
size_t zsize;
int ct = 0;
FILE *F;
if (*hostlist)
{
StrPoolDestroy(hostlist);
*hostlist = NULL;
}
if (!(F = fopen(filename, "rb")))
{
fprintf(stderr, "Could not open %s\n", filename);
return false;
}
if (z_readfile(F,&zbuf,&zsize)==Z_OK)
{
printf("libz compression detected. uncompressed size : %zu\n", zsize);
fclose(F);
p = zbuf;
e = zbuf + zsize;
while(p<e)
{
if (!addpool(hostlist,&p,e))
{
fprintf(stderr, "Not enough memory to store host list : %s\n", filename);
free(zbuf);
return false;
}
ct++;
}
free(zbuf);
}
else
{
fseek(F,0,SEEK_SET);
while (fgets(s, 256, F))
{
p = s;
if (!addpool(hostlist,&p,p+strlen(p)))
{
fprintf(stderr, "Not enough memory to store host list : %s\n", filename);
fclose(F);
return false;
}
ct++;
}
fclose(F);
}
printf("Loaded %d hosts from %s\n", ct, filename);
return true;
}

5
tpws/hostlist.h

@ -0,0 +1,5 @@
#pragma once
#include "strpool.h"
bool LoadHostList(strpool **hostlist, char *filename);

25
tpws/strpool.c

@ -11,6 +11,7 @@ static void ut_oom_recover(strpool *elem)
oom=true;
}
// for zero terminated strings
bool StrPoolAddStr(strpool **pp,const char *s)
{
strpool *elem;
@ -31,6 +32,30 @@ bool StrPoolAddStr(strpool **pp,const char *s)
}
return true;
}
// for not zero terminated strings
bool StrPoolAddStrLen(strpool **pp,const char *s,size_t slen)
{
strpool *elem;
if (!(elem = (strpool*)malloc(sizeof(strpool))))
return false;
if (!(elem->str = malloc(slen+1)))
{
free(elem);
return false;
}
memcpy(elem->str,s,slen);
elem->str[slen]=0;
oom = false;
HASH_ADD_KEYPTR( hh, *pp, elem->str, strlen(elem->str), elem );
if (oom)
{
free(elem->str);
free(elem);
return false;
}
return true;
}
bool StrPoolCheckStr(strpool *p,const char *s)
{
strpool *elem;

1
tpws/strpool.h

@ -15,4 +15,5 @@ typedef struct strpool {
void StrPoolDestroy(strpool **p);
bool StrPoolAddStr(strpool **pp,const char *s);
bool StrPoolAddStrLen(strpool **pp,const char *s,size_t slen);
bool StrPoolCheckStr(strpool *p,const char *s);

140
tpws/tpws.c

@ -24,38 +24,7 @@
#include "tpws.h"
#include "tpws_conn.h"
#include "strpool.h"
bool LoadHostList(strpool **hostlist, char *filename)
{
char *p, s[256];
FILE *F = fopen(filename, "rt");
int ct = 0;
*hostlist = NULL;
if (!F)
{
fprintf(stderr, "Could not open %s\n", filename);
return false;
}
while (fgets(s, 256, F))
{
for (p = s + strlen(s) - 1; p >= s && (*p == '\r' || *p == '\n'); p--) *p = 0;
for (p = s; *p; p++) *p=tolower(*p);
if (!StrPoolAddStr(hostlist, s))
{
StrPoolDestroy(hostlist);
*hostlist = NULL;
fprintf(stderr, "Not enough memory to store host list : %s\n", filename);
fclose(F);
return false;
}
ct++;
}
fclose(F);
printf("Loaded %d hosts from %s\n", ct, filename);
return true;
}
#include "hostlist.h"
enum splithttpreq { split_none = 0, split_method, split_host };
@ -72,6 +41,7 @@ struct params_s
int split_pos;
int maxconn;
char hostfile[256];
char pidfile[256];
strpool *hostlist;
};
@ -104,7 +74,6 @@ void dohup()
{
if (params.hostlist)
{
StrPoolDestroy(&params.hostlist);
if (!LoadHostList(&params.hostlist, params.hostfile))
exit(1);
}
@ -547,11 +516,29 @@ void exithelp()
" --methodeol\t\t; add end-of-line before method\n"
" --unixeol\t\t; replace 0D0A to 0A\n"
" --daemon\t\t; daemonize\n"
" --pidfile=<filename>\t; write pid to file\n"
" --user=<username>\t; drop root privs\n"
);
exit(1);
}
void cleanup_params()
{
if (params.hostlist)
{
StrPoolDestroy(&params.hostlist);
params.hostlist = NULL;
}
}
void exithelp_clean()
{
cleanup_params();
exithelp();
}
void exit_clean(int code)
{
cleanup_params();
exit(code);
}
void parse_params(int argc, char *argv[])
{
int option_index = 0;
@ -580,16 +567,17 @@ void parse_params(int argc, char *argv[])
{ "hosttab",no_argument,0,0 },// optidx=15
{ "unixeol",no_argument,0,0 },// optidx=16
{ "hostlist",required_argument,0,0 },// optidx=17
{ "pidfile",required_argument,0,0 },// optidx=18
{ NULL,0,NULL,0 }
};
while ((v = getopt_long_only(argc, argv, "", long_options, &option_index)) != -1)
{
if (v) exithelp();
if (v) exithelp_clean();
switch (option_index)
{
case 0:
case 1:
exithelp();
exithelp_clean();
break;
case 2: /* bind-addr */
strncpy(params.bindaddr, optarg, sizeof(params.bindaddr));
@ -600,7 +588,7 @@ void parse_params(int argc, char *argv[])
if (i <= 0 || i > 65535)
{
fprintf(stderr, "bad port number\n");
exit(1);
exit_clean(1);
}
params.port = (uint16_t)i;
break;
@ -613,7 +601,7 @@ void parse_params(int argc, char *argv[])
if (!pwd)
{
fprintf(stderr, "non-existent username supplied\n");
exit(1);
exit_clean(1);
}
params.uid = pwd->pw_uid;
params.gid = pwd->pw_gid;
@ -624,7 +612,7 @@ void parse_params(int argc, char *argv[])
if (params.maxconn <= 0)
{
fprintf(stderr, "bad maxconn\n");
exit(1);
exit_clean(1);
}
break;
case 7: /* hostcase */
@ -634,7 +622,7 @@ void parse_params(int argc, char *argv[])
if (strlen(optarg) != 4)
{
fprintf(stderr, "hostspell must be exactly 4 chars long\n");
exit(1);
exit_clean(1);
}
params.hostcase = true;
memcpy(params.hostspell, optarg, 4);
@ -653,7 +641,7 @@ void parse_params(int argc, char *argv[])
else
{
fprintf(stderr, "Invalid argument for split-http-req\n");
exit(1);
exit_clean(1);
}
break;
case 12: /* split-pos */
@ -663,7 +651,7 @@ void parse_params(int argc, char *argv[])
else
{
fprintf(stderr, "Invalid argument for split-pos\n");
exit(1);
exit_clean(1);
}
break;
case 13: /* methodspace */
@ -680,16 +668,20 @@ void parse_params(int argc, char *argv[])
break;
case 17: /* hostlist */
if (!LoadHostList(&params.hostlist, optarg))
exit(1);
exit_clean(1);
strncpy(params.hostfile,optarg,sizeof(params.hostfile));
params.hostfile[sizeof(params.hostfile)-1]='\0';
break;
case 18: /* pidfile */
strncpy(params.pidfile,optarg,sizeof(params.pidfile));
params.pidfile[sizeof(params.pidfile)-1]='\0';
break;
}
}
if (!params.port)
{
fprintf(stderr, "Need port number\n");
exit(1);
exit_clean(1);
}
}
@ -740,8 +732,18 @@ bool droproot()
return true;
}
bool writepid(const char *filename)
{
FILE *F;
if (!(F=fopen(filename,"w")))
return false;
fprintf(F,"%d",getpid());
fclose(F);
return true;
}
int main(int argc, char *argv[]) {
int listen_fd = 0;
int listen_fd = -1;
int yes = 1, retval = 0;
int r;
struct sockaddr_storage salisten;
@ -769,7 +771,7 @@ int main(int argc, char *argv[]) {
else
{
printf("bad bind addr\n");
exit(1);
goto exiterr;
}
}
else
@ -783,29 +785,32 @@ int main(int argc, char *argv[]) {
if (params.daemon) daemonize();
if (*params.pidfile && !writepid(params.pidfile))
{
fprintf(stderr,"could not write pidfile\n");
goto exiterr;
}
if ((listen_fd = socket(salisten.ss_family, SOCK_STREAM, 0)) == -1) {
perror("socket: ");
exit(EXIT_FAILURE);
goto exiterr;
}
if ((salisten.ss_family == AF_INET6) && setsockopt(listen_fd, IPPROTO_IPV6, IPV6_V6ONLY, &ipv6_only, sizeof(ipv6_only)) == -1)
{
perror("setsockopt (IPV6_ONLY): ");
close(listen_fd);
exit(EXIT_FAILURE);
goto exiterr;
}
if (setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(yes)) == -1)
{
perror("setsockopt (SO_REUSEADDR): ");
close(listen_fd);
exit(EXIT_FAILURE);
goto exiterr;
}
if (setsockopt(listen_fd, SOL_SOCKET, SO_KEEPALIVE, &yes, sizeof(yes)) == -1)
{
perror("setsockopt (SO_KEEPALIVE): ");
close(listen_fd);
exit(EXIT_FAILURE);
goto exiterr;
}
//Mark that this socket can be used for transparent proxying
@ -813,26 +818,22 @@ int main(int argc, char *argv[]) {
if (setsockopt(listen_fd, SOL_IP, IP_TRANSPARENT, &yes, sizeof(yes)) == -1)
{
perror("setsockopt (IP_TRANSPARENT): ");
close(listen_fd);
exit(EXIT_FAILURE);
goto exiterr;
}
if (!droproot())
{
close(listen_fd);
exit(EXIT_FAILURE);
goto exiterr;
}
if (bind(listen_fd, (struct sockaddr *)&salisten, salisten_len) == -1) {
perror("bind: ");
close(listen_fd);
exit(EXIT_FAILURE);
goto exiterr;
}
if (listen(listen_fd, BACKLOG) == -1) {
perror("listen: ");
close(listen_fd);
exit(EXIT_FAILURE);
goto exiterr;
}
//splice() causes the process to receive the SIGPIPE-signal if one part (for
@ -840,8 +841,7 @@ int main(int argc, char *argv[]) {
//fail and return -1, so blocking SIGPIPE.
if (block_sigpipe() == -1) {
fprintf(stderr, "Could not block SIGPIPE signal\n");
close(listen_fd);
exit(EXIT_FAILURE);
goto exiterr;
}
fprintf(stderr, "Will listen to port %d\n", params.port);
@ -849,14 +849,16 @@ int main(int argc, char *argv[]) {
signal(SIGHUP, onhup);
retval = event_loop(listen_fd);
close(listen_fd);
if (params.hostlist) StrPoolDestroy(&params.hostlist);
cleanup_params();
fprintf(stderr, "Will exit\n");
if (retval < 0)
exit(EXIT_FAILURE);
else
exit(EXIT_SUCCESS);
return retval < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
exiterr:
if (listen_fd!=-1) close(listen_fd);
cleanup_params();
return EXIT_FAILURE;
}

Loading…
Cancel
Save